summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/configs/apalis_t30_defconfig355
-rw-r--r--arch/arm/configs/colibri_pxa_defconfig340
-rw-r--r--arch/arm/configs/colibri_t20_defconfig344
-rw-r--r--arch/arm/configs/colibri_t30_defconfig342
-rw-r--r--arch/arm/include/asm/exception.h19
-rw-r--r--arch/arm/include/asm/system.h7
-rw-r--r--arch/arm/kernel/irq.c2
-rw-r--r--arch/arm/kernel/smp.c2
-rw-r--r--arch/arm/kernel/traps.c1
-rw-r--r--arch/arm/mach-pxa/Kconfig4
-rw-r--r--arch/arm/mach-pxa/colibri-evalboard.c2
-rw-r--r--arch/arm/mach-pxa/irq.c2
-rw-r--r--arch/arm/mach-tegra/Kconfig22
-rw-r--r--arch/arm/mach-tegra/Makefile19
-rw-r--r--arch/arm/mach-tegra/asm_macros.h2
-rw-r--r--arch/arm/mach-tegra/board-apalis_t30-memory.c2091
-rw-r--r--arch/arm/mach-tegra/board-apalis_t30-panel.c811
-rw-r--r--arch/arm/mach-tegra/board-apalis_t30-pinmux.c487
-rw-r--r--arch/arm/mach-tegra/board-apalis_t30-power.c510
-rw-r--r--arch/arm/mach-tegra/board-apalis_t30.c1238
-rw-r--r--arch/arm/mach-tegra/board-apalis_t30.h151
-rw-r--r--arch/arm/mach-tegra/board-aruba-sdhci.c2
-rw-r--r--arch/arm/mach-tegra/board-cardhu-sdhci.c2
-rw-r--r--arch/arm/mach-tegra/board-colibri_t20-memory.c464
-rw-r--r--arch/arm/mach-tegra/board-colibri_t20-panel.c715
-rw-r--r--arch/arm/mach-tegra/board-colibri_t20-pinmux.c381
-rw-r--r--arch/arm/mach-tegra/board-colibri_t20-power.c287
-rw-r--r--arch/arm/mach-tegra/board-colibri_t20.c1346
-rw-r--r--arch/arm/mach-tegra/board-colibri_t20.h89
-rw-r--r--arch/arm/mach-tegra/board-colibri_t30-memory.c525
-rw-r--r--arch/arm/mach-tegra/board-colibri_t30-panel.c806
-rw-r--r--arch/arm/mach-tegra/board-colibri_t30-pinmux.c648
-rw-r--r--arch/arm/mach-tegra/board-colibri_t30-power.c505
-rw-r--r--arch/arm/mach-tegra/board-colibri_t30.c1232
-rw-r--r--arch/arm/mach-tegra/board-colibri_t30.h120
-rw-r--r--arch/arm/mach-tegra/board-e1853.h2
-rw-r--r--arch/arm/mach-tegra/board-touch-kai-synaptics-spi.c2
-rw-r--r--arch/arm/mach-tegra/clock.h9
-rw-r--r--arch/arm/mach-tegra/common.c47
-rw-r--r--arch/arm/mach-tegra/devices.c25
-rw-r--r--arch/arm/mach-tegra/devices.h1
-rw-r--r--arch/arm/mach-tegra/gic.h2
-rw-r--r--arch/arm/mach-tegra/gpio-names.h2
-rw-r--r--arch/arm/mach-tegra/include/mach/ac97.h87
-rw-r--r--arch/arm/mach-tegra/include/mach/dc.h2
-rw-r--r--arch/arm/mach-tegra/include/mach/kfuse.h2
-rw-r--r--arch/arm/mach-tegra/include/mach/tegra_usb_modem_power.h2
-rw-r--r--arch/arm/mach-tegra/include/mach/tegra_wm8753_pdata.h2
-rw-r--r--arch/arm/mach-tegra/include/mach/thermal.h2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-gpio.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-i2c.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-panel.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-pinmux.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-sdhci.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-sku1-b00.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-sku1-c0x.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-sku1.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-sku13-b00.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-sku13.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-sku23-b00.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-sku23-c01.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-sku23.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-sku3.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-sku5-b00.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-sku5-c01.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-sku8-b00.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-sku8-c01.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-sku9-b00.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-sku9-c01.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852.c2
-rw-r--r--arch/arm/mach-tegra/p852/board-p852.h2
-rw-r--r--arch/arm/mach-tegra/pcie.c705
-rw-r--r--arch/arm/mach-tegra/pm-t3.c6
-rw-r--r--arch/arm/mach-tegra/pm.h2
-rw-r--r--arch/arm/mach-tegra/sleep-t2.S2
-rw-r--r--arch/arm/mach-tegra/sleep-t3.S2
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c10
-rw-r--r--arch/arm/mach-tegra/tegra2_emc.c12
-rw-r--r--arch/arm/mach-tegra/tegra2_mc.h2
-rw-r--r--arch/arm/mach-tegra/tegra2_usb_phy.c2
-rw-r--r--arch/arm/mach-tegra/tegra3_clocks.c3
-rw-r--r--arch/arm/mach-tegra/tegra_fiq_debugger.c2
-rw-r--r--arch/arm/mach-tegra/tegra_usb_phy.h2
-rw-r--r--arch/arm/mach-tegra/usb_phy.c19
-rw-r--r--arch/arm/mm/fault.c1
-rw-r--r--arch/arm/mm/pageattr.c2
-rw-r--r--arch/arm/tools/mach-types4
-rw-r--r--drivers/hwmon/lm95245.c128
-rw-r--r--drivers/input/touchscreen/Kconfig7
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/fusion_F0710A.c435
-rw-r--r--drivers/input/touchscreen/fusion_F0710A.h87
-rw-r--r--drivers/input/touchscreen/stmpe-ts.c11
-rw-r--r--drivers/input/touchscreen/wm97xx-core.c10
-rw-r--r--drivers/mfd/tps6586x.c40
-rw-r--r--drivers/mmc/host/sdhci.c3
-rw-r--r--drivers/mtd/devices/tegra_nand.c41
-rw-r--r--drivers/mtd/nand/nand_ids.c1
-rw-r--r--drivers/net/can/mcp251x.c13
-rw-r--r--drivers/net/igb/Makefile3
-rw-r--r--drivers/net/igb/e1000_82575.c276
-rw-r--r--drivers/net/igb/e1000_82575.h3
-rw-r--r--drivers/net/igb/e1000_defines.h33
-rw-r--r--drivers/net/igb/e1000_hw.h19
-rw-r--r--drivers/net/igb/e1000_i210.c603
-rw-r--r--drivers/net/igb/e1000_i210.h76
-rw-r--r--drivers/net/igb/e1000_mac.c1
-rw-r--r--drivers/net/igb/e1000_nvm.c1
-rw-r--r--drivers/net/igb/e1000_phy.c147
-rw-r--r--drivers/net/igb/e1000_phy.h22
-rw-r--r--drivers/net/igb/e1000_regs.h14
-rw-r--r--drivers/net/igb/igb.h16
-rw-r--r--drivers/net/igb/igb_ethtool.c103
-rw-r--r--drivers/net/igb/igb_main.c121
-rw-r--r--drivers/net/usb/asix.c4271
-rw-r--r--drivers/net/usb/asix.h558
-rw-r--r--drivers/net/usb/axusbnet.c1374
-rw-r--r--drivers/net/usb/axusbnet.h208
-rw-r--r--drivers/regulator/tps6586x-regulator.c81
-rw-r--r--drivers/tty/serial/8250.c21
-rw-r--r--drivers/usb/gadget/android.c4
-rw-r--r--drivers/usb/gadget/f_rndis.c21
-rw-r--r--drivers/usb/gadget/tegra_udc.c19
-rw-r--r--drivers/usb/gadget/u_ether.h23
-rw-r--r--drivers/usb/host/ehci-tegra.c115
-rw-r--r--drivers/usb/otg/Kconfig8
-rw-r--r--drivers/usb/otg/Makefile1
-rw-r--r--drivers/usb/otg/colibri-otg.c268
-rw-r--r--drivers/video/logo/Kconfig4
-rw-r--r--drivers/video/logo/Makefile2
-rw-r--r--drivers/video/logo/logo.c4
-rw-r--r--drivers/video/tegra/dc/dc.c6
-rw-r--r--drivers/video/tegra/dc/dc_priv.h6
-rw-r--r--drivers/video/tegra/dc/ext/dev.c28
-rw-r--r--drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h2
-rw-r--r--drivers/video/tegra/dc/mode.c4
-rw-r--r--drivers/video/tegra/dc/nvhdcp.c2
-rw-r--r--drivers/video/tegra/dc/window.c15
-rw-r--r--include/asm-generic/gpio.h10
-rw-r--r--include/linux/colibri_usb.h28
-rw-r--r--include/linux/linux_logo.h1
-rw-r--r--include/linux/lm95245.h36
-rw-r--r--include/linux/mfd/tps6586x.h10
-rw-r--r--include/linux/platform_data/tegra_usb.h1
-rw-r--r--kernel/workqueue.c8
-rw-r--r--sound/soc/codecs/sgtl5000.c86
-rw-r--r--sound/soc/codecs/sgtl5000.h2
-rw-r--r--sound/soc/tegra/Kconfig34
-rw-r--r--sound/soc/tegra/Makefile6
-rw-r--r--sound/soc/tegra/colibri_t20.c392
-rw-r--r--sound/soc/tegra/colibri_t30.c412
-rw-r--r--sound/soc/tegra/tegra20_ac97.c651
-rw-r--r--sound/soc/tegra/tegra20_ac97.h43
-rw-r--r--sound/soc/tegra/tegra_pcm.c37
154 files changed, 24113 insertions, 1784 deletions
diff --git a/arch/arm/configs/apalis_t30_defconfig b/arch/arm/configs/apalis_t30_defconfig
new file mode 100644
index 000000000000..f8fa13143461
--- /dev/null
+++ b/arch/arm/configs/apalis_t30_defconfig
@@ -0,0 +1,355 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_BLK_CGROUP=y
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_USER_NS=y
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_ELF_CORE is not set
+CONFIG_EMBEDDED=y
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PCI_QUIRKS is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_TEGRA=y
+CONFIG_ARCH_TEGRA_3x_SOC=y
+CONFIG_TEGRA_PCI=y
+CONFIG_MACH_APALIS_T30=y
+CONFIG_TEGRA_PWM=y
+CONFIG_TEGRA_EMC_SCALING_ENABLE=y
+CONFIG_TEGRA_CLOCK_DEBUG_WRITE=y
+CONFIG_USB_HOTPLUG=y
+CONFIG_TEGRA_DYNAMIC_PWRDET=y
+CONFIG_TEGRA_PLLM_RESTRICTED=y
+CONFIG_TEGRA_PREINIT_CLOCKS=y
+CONFIG_ARM_ERRATA_742230=y
+CONFIG_ARM_ERRATA_743622=y
+CONFIG_ARM_ERRATA_751472=y
+CONFIG_ARM_ERRATA_752520=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEASPM_POWERSAVE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_HIGHMEM=y
+CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_PM_RUNTIME=y
+CONFIG_SUSPEND_TIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+# CONFIG_ANDROID_PARANOID_NETWORK is not set
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_CAN=y
+CONFIG_CAN_RAW=y
+CONFIG_CAN_BCM=y
+CONFIG_CAN_DEV=y
+CONFIG_CAN_MCP251X=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_BLUESLEEP=y
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_MISC_DEVICES=y
+CONFIG_UID_STAT=y
+CONFIG_TEGRA_CRYPTO_DEV=y
+# CONFIG_INV_SENSORS is not set
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI_TEGRA=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+CONFIG_NETDEV_1000=y
+CONFIG_IGB=y
+# CONFIG_NETDEV_10000 is not set
+# Hack to force WIRELESS_EXT required to build Redpine Signals LiteFi driver
+CONFIG_USB_ZD1201=m
+CONFIG_B43=m
+CONFIG_RT2X00=y
+CONFIG_RT2800USB=y
+CONFIG_USB_USBNET=y
+# CONFIG_USB_NET_CDC_NCM is not set
+# CONFIG_USB_NET_NET1080 is not set
+# CONFIG_USB_BELKIN is not set
+# CONFIG_USB_NET_ZAURUS is not set
+CONFIG_PPP=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_KEYRESET=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_STMPE=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=9
+CONFIG_SERIAL_8250_RUNTIME_UARTS=9
+CONFIG_SERIAL_TEGRA=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_TEGRA=y
+CONFIG_SPI=y
+CONFIG_SPI_TEGRA=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_SENSORS_LM95245=y
+CONFIG_SENSORS_TEGRA_TSENSOR=y
+CONFIG_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_TEGRA_WATCHDOG=y
+CONFIG_MFD_TPS65910=y
+CONFIG_MFD_STMPE=y
+CONFIG_MFD_TPS6591X=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
+CONFIG_REGULATOR_USERSPACE_CONSUMER=y
+CONFIG_REGULATOR_TPS65910=y
+CONFIG_REGULATOR_TPS62360=y
+CONFIG_REGULATOR_TPS6591X=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+# CONFIG_TEGRA_AVP is not set
+# CONFIG_TEGRA_MEDIASERVER is not set
+CONFIG_TEGRA_NVAVP=y
+# CONFIG_TEGRA_DTV is not set
+CONFIG_USB_VIDEO_CLASS=y
+# CONFIG_RADIO_ADAPTERS is not set
+# CONFIG_VGA_ARB is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_TEGRA_GRHOST=y
+CONFIG_TEGRA_DC=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_BACKLIGHT_TEGRA_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_PCI is not set
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_TEGRA=y
+CONFIG_SND_SOC_TEGRA_COLIBRI_T30=y
+CONFIG_HIDRAW=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_ACM=y
+CONFIG_USB_WDM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_LIBUSUAL=y
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_PL2303=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_TEGRA=y
+CONFIG_USB_G_ANDROID=y
+CONFIG_USB_TEGRA_OTG=y
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_BKOPS=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_TEGRA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_PWM=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_SWITCH=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_TEGRA=y
+CONFIG_RTC_DRV_TPS6591x=y
+CONFIG_STAGING=y
+CONFIG_IIO=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=m
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_VM=y
+CONFIG_FUNCTION_TRACER=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DEV_TEGRA_SE=y
diff --git a/arch/arm/configs/colibri_pxa_defconfig b/arch/arm/configs/colibri_pxa_defconfig
new file mode 100644
index 000000000000..8e8fe898bf15
--- /dev/null
+++ b/arch/arm/configs/colibri_pxa_defconfig
@@ -0,0 +1,340 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_BLK_CGROUP=y
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_USER_NS=y
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_ELF_CORE is not set
+CONFIG_EMBEDDED=y
+# CONFIG_PERF_EVENTS is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_PXA=y
+CONFIG_MACH_COLIBRI=y
+CONFIG_MACH_COLIBRI300=y
+CONFIG_MACH_COLIBRI320=y
+CONFIG_MACH_LIMESTONE=y
+CONFIG_MACH_COLIBRI_EVALBOARD=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_PCCARD=y
+CONFIG_PCMCIA_PXA2XX=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_FPE_NWFPE=y
+CONFIG_PM_RUNTIME=y
+CONFIG_SUSPEND_TIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+# CONFIG_ANDROID_PARANOID_NETWORK is not set
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_LE_BYTE_SWAP=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PXA2XX=y
+CONFIG_MTD_BLOCK2MTD=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_PXA3xx=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_MISC_DEVICES=y
+CONFIG_UID_STAT=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+# CONFIG_SATA_PMP is not set
+# CONFIG_ATA_BMDMA is not set
+CONFIG_PATA_PCMCIA=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+CONFIG_PHYLIB=y
+CONFIG_NET_ETHERNET=y
+CONFIG_AX88796=y
+CONFIG_AX88796C=y
+CONFIG_DM9000=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# Hack to force WIRELESS_EXT required to build Redpine Signals LiteFi driver
+CONFIG_USB_ZD1201=m
+CONFIG_RT2X00=y
+CONFIG_RT2800USB=y
+CONFIG_USB_USBNET=y
+# CONFIG_USB_NET_CDC_NCM is not set
+# CONFIG_USB_NET_NET1080 is not set
+# CONFIG_USB_BELKIN is not set
+# CONFIG_USB_NET_ZAURUS is not set
+CONFIG_PPP=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_KEYRESET=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_UCB1400=y
+CONFIG_TOUCHSCREEN_WM97XX=y
+# CONFIG_TOUCHSCREEN_WM9705 is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_PXA=y
+CONFIG_SPI=y
+CONFIG_SPI_PXA2XX=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_BATTERY_WM97XX=y
+CONFIG_BATTERY_BQ27x00=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SA1100_WATCHDOG=y
+CONFIG_UCB1400_CORE=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+CONFIG_USB_VIDEO_CLASS=y
+# CONFIG_RADIO_ADAPTERS is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_PXA=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_PXA2XX_AC97=y
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+# CONFIG_SND_PCMCIA is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_PXA2XX_SOC=y
+CONFIG_SND_SOC_COLIBRI=y
+CONFIG_SND_SOC_LIMESTONE=y
+CONFIG_HIDRAW=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_ACM=y
+CONFIG_USB_WDM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_LIBUSUAL=y
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_PL2303=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_PXA27X=y
+CONFIG_USB_G_ANDROID=y
+CONFIG_USB_COLIBRI_OTG=y
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_BKOPS=y
+CONFIG_MMC_PXA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_PWM=y
+CONFIG_SWITCH=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_PXA=y
+CONFIG_STAGING=y
+CONFIG_IIO=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_TMPFS=y
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_DISABLE_TAGS_ECC=y
+CONFIG_UBIFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=m
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_VM=y
+CONFIG_FUNCTION_TRACER=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/configs/colibri_t20_defconfig b/arch/arm/configs/colibri_t20_defconfig
new file mode 100644
index 000000000000..0c3518b2579f
--- /dev/null
+++ b/arch/arm/configs/colibri_t20_defconfig
@@ -0,0 +1,344 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_BLK_CGROUP=y
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_USER_NS=y
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_ELF_CORE is not set
+CONFIG_EMBEDDED=y
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PCI_QUIRKS is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_TEGRA=y
+CONFIG_MACH_COLIBRI_T20=y
+CONFIG_TEGRA_PWM=y
+CONFIG_TEGRA_EMC_SCALING_ENABLE=y
+CONFIG_TEGRA_CLOCK_DEBUG_WRITE=y
+CONFIG_USB_HOTPLUG=y
+CONFIG_TEGRA_PREINIT_CLOCKS=y
+CONFIG_ARM_ERRATA_720789=y
+CONFIG_ARM_ERRATA_751472=y
+CONFIG_ARM_ERRATA_752520=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_HIGHMEM=y
+CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_PM_RUNTIME=y
+CONFIG_SUSPEND_TIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+# CONFIG_ANDROID_PARANOID_NETWORK is not set
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_BLUESLEEP=y
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_NAND_TEGRA=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_MISC_DEVICES=y
+CONFIG_UID_STAT=y
+CONFIG_TEGRA_CRYPTO_DEV=y
+# CONFIG_INV_SENSORS is not set
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# Hack to force WIRELESS_EXT required to build Redpine Signals LiteFi driver
+CONFIG_USB_ZD1201=m
+CONFIG_RT2X00=y
+CONFIG_RT2800USB=y
+CONFIG_USB_USBNET=y
+# CONFIG_USB_NET_CDC_NCM is not set
+# CONFIG_USB_NET_NET1080 is not set
+# CONFIG_USB_BELKIN is not set
+# CONFIG_USB_NET_ZAURUS is not set
+CONFIG_PPP=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_KEYRESET=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_WM97XX=y
+# CONFIG_TOUCHSCREEN_WM9705 is not set
+# CONFIG_TOUCHSCREEN_WM9713 is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=9
+CONFIG_SERIAL_8250_RUNTIME_UARTS=9
+CONFIG_SERIAL_TEGRA=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_TEGRA=y
+CONFIG_SPI=y
+CONFIG_SPI_TEGRA=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_BATTERY_WM97XX=y
+CONFIG_SENSORS_LM95245=y
+CONFIG_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_TEGRA_WATCHDOG=y
+CONFIG_MFD_TPS6586X=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
+CONFIG_REGULATOR_USERSPACE_CONSUMER=y
+CONFIG_REGULATOR_TPS6586X=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+# CONFIG_TEGRA_CAMERA is not set
+# CONFIG_TEGRA_DTV is not set
+CONFIG_USB_VIDEO_CLASS=y
+# CONFIG_RADIO_ADAPTERS is not set
+# CONFIG_VGA_ARB is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_TEGRA_GRHOST=y
+CONFIG_TEGRA_DC=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_BACKLIGHT_TEGRA_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_PCI is not set
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_TEGRA=y
+CONFIG_SND_SOC_TEGRA_COLIBRI_T20=y
+CONFIG_HIDRAW=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_TEGRA=y
+CONFIG_USB_ACM=y
+CONFIG_USB_WDM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_LIBUSUAL=y
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_PL2303=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_TEGRA=y
+CONFIG_USB_G_ANDROID=y
+CONFIG_USB_COLIBRI_OTG=y
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_BKOPS=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_TEGRA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_PWM=y
+CONFIG_SWITCH=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_TPS6586X=y
+CONFIG_RTC_DRV_TEGRA=y
+CONFIG_STAGING=y
+CONFIG_IIO=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_TMPFS=y
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_DISABLE_TAGS_ECC=y
+CONFIG_UBIFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=m
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_VM=y
+CONFIG_FUNCTION_TRACER=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DEV_TEGRA_AES=y
diff --git a/arch/arm/configs/colibri_t30_defconfig b/arch/arm/configs/colibri_t30_defconfig
new file mode 100644
index 000000000000..6e631d3b94ad
--- /dev/null
+++ b/arch/arm/configs/colibri_t30_defconfig
@@ -0,0 +1,342 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_BLK_CGROUP=y
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_USER_NS=y
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_ELF_CORE is not set
+CONFIG_EMBEDDED=y
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PCI_QUIRKS is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_TEGRA=y
+CONFIG_ARCH_TEGRA_3x_SOC=y
+CONFIG_MACH_COLIBRI_T30=y
+CONFIG_TEGRA_PWM=y
+CONFIG_TEGRA_EMC_SCALING_ENABLE=y
+CONFIG_TEGRA_CLOCK_DEBUG_WRITE=y
+CONFIG_USB_HOTPLUG=y
+CONFIG_TEGRA_DYNAMIC_PWRDET=y
+CONFIG_TEGRA_PLLM_RESTRICTED=y
+CONFIG_TEGRA_PREINIT_CLOCKS=y
+CONFIG_ARM_ERRATA_742230=y
+CONFIG_ARM_ERRATA_743622=y
+CONFIG_ARM_ERRATA_751472=y
+CONFIG_ARM_ERRATA_752520=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_HIGHMEM=y
+CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_PM_RUNTIME=y
+CONFIG_SUSPEND_TIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+# CONFIG_ANDROID_PARANOID_NETWORK is not set
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_BLUESLEEP=y
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_MISC_DEVICES=y
+CONFIG_UID_STAT=y
+CONFIG_TEGRA_CRYPTO_DEV=y
+# CONFIG_INV_SENSORS is not set
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# Hack to force WIRELESS_EXT required to build Redpine Signals LiteFi driver
+CONFIG_USB_ZD1201=m
+CONFIG_RT2X00=y
+CONFIG_RT2800USB=y
+CONFIG_USB_USBNET=y
+# CONFIG_USB_NET_CDC_NCM is not set
+# CONFIG_USB_NET_NET1080 is not set
+# CONFIG_USB_BELKIN is not set
+# CONFIG_USB_NET_ZAURUS is not set
+CONFIG_PPP=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_KEYRESET=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_STMPE=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=9
+CONFIG_SERIAL_8250_RUNTIME_UARTS=9
+CONFIG_SERIAL_TEGRA=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_TEGRA=y
+CONFIG_SPI=y
+CONFIG_SPI_TEGRA=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_SENSORS_LM95245=y
+CONFIG_SENSORS_TEGRA_TSENSOR=y
+CONFIG_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_TEGRA_WATCHDOG=y
+CONFIG_MFD_TPS65910=y
+CONFIG_MFD_STMPE=y
+CONFIG_MFD_TPS6591X=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
+CONFIG_REGULATOR_USERSPACE_CONSUMER=y
+CONFIG_REGULATOR_TPS65910=y
+CONFIG_REGULATOR_TPS62360=y
+CONFIG_REGULATOR_TPS6591X=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+# CONFIG_TEGRA_AVP is not set
+# CONFIG_TEGRA_MEDIASERVER is not set
+CONFIG_TEGRA_NVAVP=y
+# CONFIG_TEGRA_CAMERA is not set
+# CONFIG_TEGRA_DTV is not set
+CONFIG_USB_VIDEO_CLASS=y
+# CONFIG_RADIO_ADAPTERS is not set
+# CONFIG_VGA_ARB is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_TEGRA_GRHOST=y
+CONFIG_TEGRA_DC=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_BACKLIGHT_TEGRA_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_PCI is not set
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_TEGRA=y
+CONFIG_SND_SOC_TEGRA_COLIBRI_T30=y
+CONFIG_HIDRAW=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_ACM=y
+CONFIG_USB_WDM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_LIBUSUAL=y
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_PL2303=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_TEGRA=y
+CONFIG_USB_G_ANDROID=y
+CONFIG_USB_COLIBRI_OTG=y
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_BKOPS=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_TEGRA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_PWM=y
+CONFIG_SWITCH=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_TEGRA=y
+CONFIG_RTC_DRV_TPS6591x=y
+CONFIG_STAGING=y
+CONFIG_IIO=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=m
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_VM=y
+CONFIG_FUNCTION_TRACER=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DEV_TEGRA_SE=y
diff --git a/arch/arm/include/asm/exception.h b/arch/arm/include/asm/exception.h
new file mode 100644
index 000000000000..5abaf5bbd985
--- /dev/null
+++ b/arch/arm/include/asm/exception.h
@@ -0,0 +1,19 @@
+/*
+ * Annotations for marking C functions as exception handlers.
+ *
+ * These should only be used for C functions that are called from the low
+ * level exception entry code and not any intervening C code.
+ */
+#ifndef __ASM_ARM_EXCEPTION_H
+#define __ASM_ARM_EXCEPTION_H
+
+#include <linux/ftrace.h>
+
+#define __exception __attribute__((section(".exception.text")))
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+#define __exception_irq_entry __irq_entry
+#else
+#define __exception_irq_entry __exception
+#endif
+
+#endif /* __ASM_ARM_EXCEPTION_H */
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 832888d0c20c..ed6b0499a106 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -62,13 +62,6 @@
#include <asm/outercache.h>
-#define __exception __attribute__((section(".exception.text")))
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-#define __exception_irq_entry __irq_entry
-#else
-#define __exception_irq_entry __exception
-#endif
-
struct thread_info;
struct task_struct;
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index de3dcab8610b..53919b230e8b 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -35,8 +35,8 @@
#include <linux/list.h>
#include <linux/kallsyms.h>
#include <linux/proc_fs.h>
-#include <linux/ftrace.h>
+#include <asm/exception.h>
#include <asm/system.h>
#include <asm/mach/arch.h>
#include <asm/mach/irq.h>
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 016473c1d794..45664df79f05 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -16,7 +16,6 @@
#include <linux/cache.h>
#include <linux/profile.h>
#include <linux/errno.h>
-#include <linux/ftrace.h>
#include <linux/mm.h>
#include <linux/err.h>
#include <linux/cpu.h>
@@ -31,6 +30,7 @@
#include <asm/cacheflush.h>
#include <asm/cpu.h>
#include <asm/cputype.h>
+#include <asm/exception.h>
#include <asm/mmu_context.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 2534d2a1a164..6a7e9ee75290 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -30,6 +30,7 @@
#include <linux/atomic.h>
#include <asm/cacheflush.h>
+#include <asm/exception.h>
#include <asm/system.h>
#include <asm/unistd.h>
#include <asm/traps.h>
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index cd19309fd3b8..95ed956cf123 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -235,23 +235,25 @@ endchoice
config MACH_COLIBRI
bool "Toradex Colibri PXA270"
select PXA27x
+ select HAVE_PWM
config MACH_COLIBRI_PXA270_INCOME
bool "Income s.r.o. PXA270 SBC"
depends on MACH_COLIBRI
select PXA27x
- select HAVE_PWM
config MACH_COLIBRI300
bool "Toradex Colibri PXA300/310"
select PXA3xx
select CPU_PXA300
select CPU_PXA310
+ select HAVE_PWM
config MACH_COLIBRI320
bool "Toradex Colibri PXA320"
select PXA3xx
select CPU_PXA320
+ select HAVE_PWM
config MACH_COLIBRI_EVALBOARD
bool "Toradex Colibri Evaluation Carrier Board support"
diff --git a/arch/arm/mach-pxa/colibri-evalboard.c b/arch/arm/mach-pxa/colibri-evalboard.c
index d28e802e2448..64733482f25c 100644
--- a/arch/arm/mach-pxa/colibri-evalboard.c
+++ b/arch/arm/mach-pxa/colibri-evalboard.c
@@ -46,7 +46,7 @@ static void __init colibri_mmc_init(void)
if (machine_is_colibri()) /* PXA270 Colibri */
colibri_mci_platform_data.gpio_card_detect =
GPIO0_COLIBRI_PXA270_SD_DETECT;
- if (machine_is_colibri300()) /* PXA300 Colibri */
+ else if (machine_is_colibri300()) /* PXA300 Colibri */
colibri_mci_platform_data.gpio_card_detect =
GPIO13_COLIBRI_PXA300_SD_DETECT;
else /* PXA320 Colibri */
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index b09e848eb6c6..ca6075717824 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -19,6 +19,8 @@
#include <linux/io.h>
#include <linux/irq.h>
+#include <asm/exception.h>
+
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <mach/gpio.h>
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 8db76065ea6d..6ca839316e1a 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -29,9 +29,6 @@ config ARCH_TEGRA_2x_SOC
select USB_ULPI if USB_SUPPORT
select USB_ULPI_VIEWPORT if USB_SUPPORT
select ARM_ERRATA_742230 if SMP
- select USB_ARCH_HAS_EHCI if USB_SUPPORT
- select USB_ULPI if USB_SUPPORT
- select USB_ULPI_VIEWPORT if USB_SUPPORT
select ARCH_SUPPORTS_MSI if TEGRA_PCI
select PCI_MSI if TEGRA_PCI
select CPA
@@ -101,6 +98,12 @@ config TEGRA_IRDA
comment "Tegra board type"
+config MACH_COLIBRI_T20
+ bool "Toradex Colibri T20 module"
+ depends on ARCH_TEGRA_2x_SOC
+ help
+ Support for Toradex Colibri T20 module on Iris carrier board
+
config MACH_HARMONY
bool "Harmony board"
depends on ARCH_TEGRA_2x_SOC
@@ -166,6 +169,13 @@ config MACH_WHISTLER
help
Support for NVIDIA Whistler development platform
+config MACH_APALIS_T30
+ bool "Toradex Apalis T30 module"
+ depends on ARCH_TEGRA_3x_SOC
+ help
+ Support for Toradex Apalis T30 module on Apalis evaluation carrier
+ board
+
config MACH_ARUBA
bool "Aruba board"
depends on ARCH_TEGRA_3x_SOC
@@ -183,6 +193,12 @@ config MACH_CARDHU
help
Support for NVIDIA Cardhu development platform
+config MACH_COLIBRI_T30
+ bool "Toradex Colibri T30 module"
+ depends on ARCH_TEGRA_3x_SOC
+ help
+ Support for Toradex Colibri T30 module on Iris carrier board
+
config MACH_P1852
bool "P1852 board"
depends on ARCH_TEGRA_3x_SOC
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 85e1964a2284..4a74b6481a65 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -116,6 +116,13 @@ obj-$(CONFIG_SENSORS_TEGRA_TSENSOR) += tegra3_tsensor.o
obj-$(CONFIG_TEGRA_DYNAMIC_PWRDET) += powerdetect.o
obj-$(CONFIG_TEGRA_USB_MODEM_POWER) += tegra_usb_modem_power.o
obj-$(CONFIG_TEGRA_PCI) += pcie.o
+
+obj-${CONFIG_MACH_COLIBRI_T20} += board-colibri_t20.o
+obj-${CONFIG_MACH_COLIBRI_T20} += board-colibri_t20-memory.o
+obj-${CONFIG_MACH_COLIBRI_T20} += board-colibri_t20-panel.o
+obj-${CONFIG_MACH_COLIBRI_T20} += board-colibri_t20-pinmux.o
+obj-${CONFIG_MACH_COLIBRI_T20} += board-colibri_t20-power.o
+
obj-${CONFIG_MACH_HARMONY} += board-harmony.o
obj-${CONFIG_MACH_HARMONY} += board-harmony-kbc.o
obj-${CONFIG_MACH_HARMONY} += board-harmony-panel.o
@@ -162,6 +169,12 @@ obj-${CONFIG_MACH_WHISTLER} += board-whistler-kbc.o
obj-${CONFIG_MACH_WHISTLER} += board-whistler-baseband.o
obj-${CONFIG_MACH_WHISTLER} += board-whistler-memory.o
+obj-${CONFIG_MACH_APALIS_T30} += board-apalis_t30.o
+obj-${CONFIG_MACH_APALIS_T30} += board-apalis_t30-memory.o
+obj-${CONFIG_MACH_APALIS_T30} += board-apalis_t30-panel.o
+obj-${CONFIG_MACH_APALIS_T30} += board-apalis_t30-pinmux.o
+obj-${CONFIG_MACH_APALIS_T30} += board-apalis_t30-power.o
+
obj-${CONFIG_MACH_CARDHU} += board-cardhu.o
obj-${CONFIG_MACH_CARDHU} += board-cardhu-kbc.o
obj-${CONFIG_MACH_CARDHU} += board-cardhu-irda.o
@@ -175,6 +188,12 @@ obj-${CONFIG_MACH_CARDHU} += board-cardhu-sensors.o
obj-${CONFIG_MACH_CARDHU} += board-cardhu-memory.o
obj-${CONFIG_MACH_CARDHU} += board-cardhu-powermon.o
+obj-${CONFIG_MACH_COLIBRI_T30} += board-colibri_t30.o
+obj-${CONFIG_MACH_COLIBRI_T30} += board-colibri_t30-memory.o
+obj-${CONFIG_MACH_COLIBRI_T30} += board-colibri_t30-panel.o
+obj-${CONFIG_MACH_COLIBRI_T30} += board-colibri_t30-pinmux.o
+obj-${CONFIG_MACH_COLIBRI_T30} += board-colibri_t30-power.o
+
obj-${CONFIG_MACH_KAI} += board-touch-kai-synaptics-spi.o
obj-y += board-touch-raydium_spi.o
diff --git a/arch/arm/mach-tegra/asm_macros.h b/arch/arm/mach-tegra/asm_macros.h
index 2463d797ce39..1926418957ba 100644
--- a/arch/arm/mach-tegra/asm_macros.h
+++ b/arch/arm/mach-tegra/asm_macros.h
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/include/mach/asm_macros.h
+ * arch/arm/mach-tegra/asm_macros.h
*
* Copyright (C) 2011 NVIDIA Corporation
*
diff --git a/arch/arm/mach-tegra/board-apalis_t30-memory.c b/arch/arm/mach-tegra/board-apalis_t30-memory.c
new file mode 100644
index 000000000000..ee3d3858e285
--- /dev/null
+++ b/arch/arm/mach-tegra/board-apalis_t30-memory.c
@@ -0,0 +1,2091 @@
+/*
+ * Copyright (C) 2013 Toradex, Inc.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include "board.h"
+#include "board-apalis_t30.h"
+#include "tegra3_emc.h"
+#include "fuse.h"
+
+#if 0
+static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = {
+ {
+ 0x32, /* Rev 3.2 */
+ 25500, /* SDRAM frequency */
+ {
+ 0x00000001, /* EMC_RC */
+ 0x00000003, /* EMC_RFC */
+ 0x00000000, /* EMC_RAS */
+ 0x00000000, /* EMC_RP */
+ 0x00000002, /* EMC_R2W */
+ 0x0000000a, /* EMC_W2R */
+ 0x00000003, /* EMC_R2P */
+ 0x0000000b, /* EMC_W2P */
+ 0x00000000, /* EMC_RD_RCD */
+ 0x00000000, /* EMC_WR_RCD */
+ 0x00000003, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000005, /* EMC_WDV */
+ 0x00000005, /* EMC_QUSE */
+ 0x00000004, /* EMC_QRST */
+ 0x00000007, /* EMC_QSAFE */
+ 0x0000000c, /* EMC_RDV */
+ 0x000000bd, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x0000002f, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000002, /* EMC_PDEX2WR */
+ 0x00000002, /* EMC_PDEX2RD */
+ 0x00000001, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x00000007, /* EMC_AR2PDEN */
+ 0x0000000f, /* EMC_RW2PDEN */
+ 0x00000005, /* EMC_TXSR */
+ 0x00000005, /* EMC_TXSRDLL */
+ 0x00000004, /* EMC_TCKE */
+ 0x00000001, /* EMC_TFAW */
+ 0x00000000, /* EMC_TRPAB */
+ 0x00000004, /* EMC_TCLKSTABLE */
+ 0x00000005, /* EMC_TCLKSTOP */
+ 0x000000c3, /* EMC_TREFBW */
+ 0x00000000, /* EMC_QUSE_EXTRA */
+ 0x00000004, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00006288, /* EMC_FBIO_CFG5 */
+ 0x007800a4, /* EMC_CFG_DIG_DLL */
+ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
+ 0x00080000, /* EMC_DLL_XFORM_DQS0 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS1 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS2 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS3 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS4 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS5 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS6 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS7 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE0 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE1 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE2 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE3 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE4 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE5 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE6 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE7 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */
+ 0x00080000, /* EMC_DLL_XFORM_DQ0 */
+ 0x00080000, /* EMC_DLL_XFORM_DQ1 */
+ 0x00080000, /* EMC_DLL_XFORM_DQ2 */
+ 0x00080000, /* EMC_DLL_XFORM_DQ3 */
+ 0x000002a0, /* EMC_XM2CMDPADCTRL */
+ 0x0800211c, /* EMC_XM2DQSPADCTRL2 */
+ 0x00000000, /* EMC_XM2DQPADCTRL2 */
+ 0x77ffc084, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f108, /* EMC_XM2COMPPADCTRL */
+ 0x05057404, /* EMC_XM2VTTGENPADCTRL */
+ 0x54000007, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x08000168, /* EMC_XM2QUSEPADCTRL */
+ 0x08000000, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00000000, /* EMC_ZCAL_INTERVAL */
+ 0x00000040, /* EMC_ZCAL_WAIT_CNT */
+ 0x000c000c, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x80000280, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x00030003, /* MC_EMEM_ARB_CFG */
+ 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RC */
+ 0x00000000, /* MC_EMEM_ARB_TIMING_RAS */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x06020102, /* MC_EMEM_ARB_DA_TURNS */
+ 0x000a0402, /* MC_EMEM_ARB_DA_COVERS */
+ 0x74430303, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xd8000000, /* EMC_FBIO_SPARE */
+ 0xff00ff00, /* EMC_CFG_RSV */
+ },
+ 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000000, /* EMC_CFG.PERIODIC_QRST */
+ 0x80001221, /* Mode Register 0 */
+ 0x80100003, /* Mode Register 1 */
+ 0x80200008, /* Mode Register 2 */
+ 0x00000001, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 51000, /* SDRAM frequency */
+ {
+ 0x00000002, /* EMC_RC */
+ 0x00000008, /* EMC_RFC */
+ 0x00000001, /* EMC_RAS */
+ 0x00000000, /* EMC_RP */
+ 0x00000002, /* EMC_R2W */
+ 0x0000000a, /* EMC_W2R */
+ 0x00000003, /* EMC_R2P */
+ 0x0000000b, /* EMC_W2P */
+ 0x00000000, /* EMC_RD_RCD */
+ 0x00000000, /* EMC_WR_RCD */
+ 0x00000003, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000005, /* EMC_WDV */
+ 0x00000005, /* EMC_QUSE */
+ 0x00000004, /* EMC_QRST */
+ 0x00000007, /* EMC_QSAFE */
+ 0x0000000c, /* EMC_RDV */
+ 0x00000181, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x00000060, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000002, /* EMC_PDEX2WR */
+ 0x00000002, /* EMC_PDEX2RD */
+ 0x00000001, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x00000007, /* EMC_AR2PDEN */
+ 0x0000000f, /* EMC_RW2PDEN */
+ 0x00000009, /* EMC_TXSR */
+ 0x00000009, /* EMC_TXSRDLL */
+ 0x00000004, /* EMC_TCKE */
+ 0x00000002, /* EMC_TFAW */
+ 0x00000000, /* EMC_TRPAB */
+ 0x00000004, /* EMC_TCLKSTABLE */
+ 0x00000005, /* EMC_TCLKSTOP */
+ 0x0000018e, /* EMC_TREFBW */
+ 0x00000000, /* EMC_QUSE_EXTRA */
+ 0x00000004, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00006288, /* EMC_FBIO_CFG5 */
+ 0x007800a4, /* EMC_CFG_DIG_DLL */
+ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
+ 0x00080000, /* EMC_DLL_XFORM_DQS0 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS1 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS2 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS3 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS4 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS5 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS6 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS7 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE0 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE1 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE2 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE3 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE4 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE5 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE6 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE7 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */
+ 0x00080000, /* EMC_DLL_XFORM_DQ0 */
+ 0x00080000, /* EMC_DLL_XFORM_DQ1 */
+ 0x00080000, /* EMC_DLL_XFORM_DQ2 */
+ 0x00080000, /* EMC_DLL_XFORM_DQ3 */
+ 0x000002a0, /* EMC_XM2CMDPADCTRL */
+ 0x0800211c, /* EMC_XM2DQSPADCTRL2 */
+ 0x00000000, /* EMC_XM2DQPADCTRL2 */
+ 0x77ffc084, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f108, /* EMC_XM2COMPPADCTRL */
+ 0x05057404, /* EMC_XM2VTTGENPADCTRL */
+ 0x54000007, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x08000168, /* EMC_XM2QUSEPADCTRL */
+ 0x08000000, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00000000, /* EMC_ZCAL_INTERVAL */
+ 0x00000040, /* EMC_ZCAL_WAIT_CNT */
+ 0x000c000c, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x00010003, /* MC_EMEM_ARB_CFG */
+ 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RC */
+ 0x00000000, /* MC_EMEM_ARB_TIMING_RAS */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x06020102, /* MC_EMEM_ARB_DA_TURNS */
+ 0x000a0402, /* MC_EMEM_ARB_DA_COVERS */
+ 0x73430303, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xd8000000, /* EMC_FBIO_SPARE */
+ 0xff00ff00, /* EMC_CFG_RSV */
+ },
+ 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000000, /* EMC_CFG.PERIODIC_QRST */
+ 0x80001221, /* Mode Register 0 */
+ 0x80100003, /* Mode Register 1 */
+ 0x80200008, /* Mode Register 2 */
+ 0x00000001, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 102000, /* SDRAM frequency */
+ {
+ 0x00000004, /* EMC_RC */
+ 0x00000010, /* EMC_RFC */
+ 0x00000003, /* EMC_RAS */
+ 0x00000001, /* EMC_RP */
+ 0x00000002, /* EMC_R2W */
+ 0x0000000a, /* EMC_W2R */
+ 0x00000003, /* EMC_R2P */
+ 0x0000000b, /* EMC_W2P */
+ 0x00000001, /* EMC_RD_RCD */
+ 0x00000001, /* EMC_WR_RCD */
+ 0x00000003, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000005, /* EMC_WDV */
+ 0x00000005, /* EMC_QUSE */
+ 0x00000004, /* EMC_QRST */
+ 0x00000007, /* EMC_QSAFE */
+ 0x0000000c, /* EMC_RDV */
+ 0x00000303, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x000000c0, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000002, /* EMC_PDEX2WR */
+ 0x00000002, /* EMC_PDEX2RD */
+ 0x00000001, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x00000007, /* EMC_AR2PDEN */
+ 0x0000000f, /* EMC_RW2PDEN */
+ 0x00000012, /* EMC_TXSR */
+ 0x00000012, /* EMC_TXSRDLL */
+ 0x00000004, /* EMC_TCKE */
+ 0x00000004, /* EMC_TFAW */
+ 0x00000000, /* EMC_TRPAB */
+ 0x00000004, /* EMC_TCLKSTABLE */
+ 0x00000005, /* EMC_TCLKSTOP */
+ 0x0000031c, /* EMC_TREFBW */
+ 0x00000000, /* EMC_QUSE_EXTRA */
+ 0x00000004, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00006288, /* EMC_FBIO_CFG5 */
+ 0x007800a4, /* EMC_CFG_DIG_DLL */
+ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
+ 0x00080000, /* EMC_DLL_XFORM_DQS0 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS1 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS2 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS3 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS4 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS5 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS6 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS7 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE0 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE1 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE2 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE3 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE4 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE5 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE6 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE7 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */
+ 0x00080000, /* EMC_DLL_XFORM_DQ0 */
+ 0x00080000, /* EMC_DLL_XFORM_DQ1 */
+ 0x00080000, /* EMC_DLL_XFORM_DQ2 */
+ 0x00080000, /* EMC_DLL_XFORM_DQ3 */
+ 0x000002a0, /* EMC_XM2CMDPADCTRL */
+ 0x0800211c, /* EMC_XM2DQSPADCTRL2 */
+ 0x00000000, /* EMC_XM2DQPADCTRL2 */
+ 0x77ffc084, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f108, /* EMC_XM2COMPPADCTRL */
+ 0x05057404, /* EMC_XM2VTTGENPADCTRL */
+ 0x54000007, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x08000168, /* EMC_XM2QUSEPADCTRL */
+ 0x08000000, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00000000, /* EMC_ZCAL_INTERVAL */
+ 0x00000040, /* EMC_ZCAL_WAIT_CNT */
+ 0x000c000c, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x00000003, /* MC_EMEM_ARB_CFG */
+ 0xc0000018, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RC */
+ 0x00000000, /* MC_EMEM_ARB_TIMING_RAS */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x06020102, /* MC_EMEM_ARB_DA_TURNS */
+ 0x000a0403, /* MC_EMEM_ARB_DA_COVERS */
+ 0x72830504, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xd8000000, /* EMC_FBIO_SPARE */
+ 0xff00ff00, /* EMC_CFG_RSV */
+ },
+ 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000000, /* EMC_CFG.PERIODIC_QRST */
+ 0x80001221, /* Mode Register 0 */
+ 0x80100003, /* Mode Register 1 */
+ 0x80200008, /* Mode Register 2 */
+ 0x00000001, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 204000, /* SDRAM frequency */
+ {
+ 0x00000009, /* EMC_RC */
+ 0x00000020, /* EMC_RFC */
+ 0x00000007, /* EMC_RAS */
+ 0x00000002, /* EMC_RP */
+ 0x00000002, /* EMC_R2W */
+ 0x0000000a, /* EMC_W2R */
+ 0x00000005, /* EMC_R2P */
+ 0x0000000b, /* EMC_W2P */
+ 0x00000002, /* EMC_RD_RCD */
+ 0x00000002, /* EMC_WR_RCD */
+ 0x00000003, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000005, /* EMC_WDV */
+ 0x00000005, /* EMC_QUSE */
+ 0x00000004, /* EMC_QRST */
+ 0x00000009, /* EMC_QSAFE */
+ 0x0000000b, /* EMC_RDV */
+ 0x00000607, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x00000181, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000002, /* EMC_PDEX2WR */
+ 0x00000002, /* EMC_PDEX2RD */
+ 0x00000001, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x00000007, /* EMC_AR2PDEN */
+ 0x0000000f, /* EMC_RW2PDEN */
+ 0x00000023, /* EMC_TXSR */
+ 0x00000023, /* EMC_TXSRDLL */
+ 0x00000004, /* EMC_TCKE */
+ 0x00000007, /* EMC_TFAW */
+ 0x00000000, /* EMC_TRPAB */
+ 0x00000004, /* EMC_TCLKSTABLE */
+ 0x00000005, /* EMC_TCLKSTOP */
+ 0x00000638, /* EMC_TREFBW */
+ 0x00000006, /* EMC_QUSE_EXTRA */
+ 0x00000004, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00004288, /* EMC_FBIO_CFG5 */
+ 0x004400a4, /* EMC_CFG_DIG_DLL */
+ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
+ 0x00080000, /* EMC_DLL_XFORM_DQS0 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS1 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS2 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS3 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS4 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS5 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS6 */
+ 0x00080000, /* EMC_DLL_XFORM_DQS7 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE0 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE1 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE2 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE3 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE4 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE5 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE6 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE7 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */
+ 0x00080000, /* EMC_DLL_XFORM_DQ0 */
+ 0x00080000, /* EMC_DLL_XFORM_DQ1 */
+ 0x00080000, /* EMC_DLL_XFORM_DQ2 */
+ 0x00080000, /* EMC_DLL_XFORM_DQ3 */
+ 0x000002a0, /* EMC_XM2CMDPADCTRL */
+ 0x0800211c, /* EMC_XM2DQSPADCTRL2 */
+ 0x00000000, /* EMC_XM2DQPADCTRL2 */
+ 0x77fff884, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f108, /* EMC_XM2COMPPADCTRL */
+ 0x05057404, /* EMC_XM2VTTGENPADCTRL */
+ 0x54000007, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x08000168, /* EMC_XM2QUSEPADCTRL */
+ 0x08000000, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00020000, /* EMC_ZCAL_INTERVAL */
+ 0x00000100, /* EMC_ZCAL_WAIT_CNT */
+ 0x000c000c, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x80000d22, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x00000006, /* MC_EMEM_ARB_CFG */
+ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */
+ 0x00000005, /* MC_EMEM_ARB_TIMING_RC */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RAS */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x06020102, /* MC_EMEM_ARB_DA_TURNS */
+ 0x000a0505, /* MC_EMEM_ARB_DA_COVERS */
+ 0x72440a06, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xe8000000, /* EMC_FBIO_SPARE */
+ 0xff00ff00, /* EMC_CFG_RSV */
+ },
+ 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000001, /* EMC_CFG.PERIODIC_QRST */
+ 0x80001221, /* Mode Register 0 */
+ 0x80100003, /* Mode Register 1 */
+ 0x80200008, /* Mode Register 2 */
+ 0x00000001, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 375000, /* SDRAM frequency */
+ {
+ 0x00000011, /* EMC_RC */
+ 0x0000003a, /* EMC_RFC */
+ 0x0000000c, /* EMC_RAS */
+ 0x00000004, /* EMC_RP */
+ 0x00000003, /* EMC_R2W */
+ 0x00000008, /* EMC_W2R */
+ 0x00000002, /* EMC_R2P */
+ 0x0000000a, /* EMC_W2P */
+ 0x00000004, /* EMC_RD_RCD */
+ 0x00000004, /* EMC_WR_RCD */
+ 0x00000002, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000004, /* EMC_WDV */
+ 0x00000006, /* EMC_QUSE */
+ 0x00000004, /* EMC_QRST */
+ 0x00000008, /* EMC_QSAFE */
+ 0x0000000d, /* EMC_RDV */
+ 0x00000b2d, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x000002cb, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000008, /* EMC_PDEX2WR */
+ 0x00000008, /* EMC_PDEX2RD */
+ 0x00000001, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x00000007, /* EMC_AR2PDEN */
+ 0x0000000f, /* EMC_RW2PDEN */
+ 0x00000040, /* EMC_TXSR */
+ 0x00000200, /* EMC_TXSRDLL */
+ 0x00000009, /* EMC_TCKE */
+ 0x0000000c, /* EMC_TFAW */
+ 0x00000000, /* EMC_TRPAB */
+ 0x00000004, /* EMC_TCLKSTABLE */
+ 0x00000005, /* EMC_TCLKSTOP */
+ 0x00000b6d, /* EMC_TREFBW */
+ 0x00000000, /* EMC_QUSE_EXTRA */
+ 0x00000006, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00007088, /* EMC_FBIO_CFG5 */
+ 0x00200084, /* EMC_CFG_DIG_DLL */
+ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
+ 0x0003c000, /* EMC_DLL_XFORM_DQS0 */
+ 0x0003c000, /* EMC_DLL_XFORM_DQS1 */
+ 0x0003c000, /* EMC_DLL_XFORM_DQS2 */
+ 0x0003c000, /* EMC_DLL_XFORM_DQS3 */
+ 0x0003c000, /* EMC_DLL_XFORM_DQS4 */
+ 0x0003c000, /* EMC_DLL_XFORM_DQS5 */
+ 0x0003c000, /* EMC_DLL_XFORM_DQS6 */
+ 0x0003c000, /* EMC_DLL_XFORM_DQS7 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE0 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE1 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE2 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE3 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE4 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE5 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE6 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE7 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */
+ 0x00040000, /* EMC_DLL_XFORM_DQ0 */
+ 0x00040000, /* EMC_DLL_XFORM_DQ1 */
+ 0x00040000, /* EMC_DLL_XFORM_DQ2 */
+ 0x00040000, /* EMC_DLL_XFORM_DQ3 */
+ 0x000002a0, /* EMC_XM2CMDPADCTRL */
+ 0x0800013d, /* EMC_XM2DQSPADCTRL2 */
+ 0x00000000, /* EMC_XM2DQPADCTRL2 */
+ 0x77fff884, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f508, /* EMC_XM2COMPPADCTRL */
+ 0x05057404, /* EMC_XM2VTTGENPADCTRL */
+ 0x54000007, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x080001e8, /* EMC_XM2QUSEPADCTRL */
+ 0x08000021, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00020000, /* EMC_ZCAL_INTERVAL */
+ 0x00000100, /* EMC_ZCAL_WAIT_CNT */
+ 0x0184000c, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x8000174b, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x0000000b, /* MC_EMEM_ARB_CFG */
+ 0xc0000044, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */
+ 0x00000009, /* MC_EMEM_ARB_TIMING_RC */
+ 0x00000005, /* MC_EMEM_ARB_TIMING_RAS */
+ 0x00000005, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x06030202, /* MC_EMEM_ARB_DA_TURNS */
+ 0x000d0709, /* MC_EMEM_ARB_DA_COVERS */
+ 0x75c6110a, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0x58000000, /* EMC_FBIO_SPARE */
+ 0xff00ff88, /* EMC_CFG_RSV */
+ },
+ 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000000, /* EMC_CFG.PERIODIC_QRST */
+ 0x80000521, /* Mode Register 0 */
+ 0x80100002, /* Mode Register 1 */
+ 0x80200000, /* Mode Register 2 */
+ 0x00000000, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 400000, /* SDRAM frequency */
+ {
+ 0x00000012, /* EMC_RC */
+ 0x00000040, /* EMC_RFC */
+ 0x0000000d, /* EMC_RAS */
+ 0x00000004, /* EMC_RP */
+ 0x00000002, /* EMC_R2W */
+ 0x00000009, /* EMC_W2R */
+ 0x00000002, /* EMC_R2P */
+ 0x0000000c, /* EMC_W2P */
+ 0x00000004, /* EMC_RD_RCD */
+ 0x00000004, /* EMC_WR_RCD */
+ 0x00000002, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000005, /* EMC_WDV */
+ 0x00000007, /* EMC_QUSE */
+ 0x00000005, /* EMC_QRST */
+ 0x00000008, /* EMC_QSAFE */
+ 0x0000000e, /* EMC_RDV */
+ 0x00000c2e, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x0000030b, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000008, /* EMC_PDEX2WR */
+ 0x00000008, /* EMC_PDEX2RD */
+ 0x00000001, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x00000008, /* EMC_AR2PDEN */
+ 0x00000011, /* EMC_RW2PDEN */
+ 0x00000046, /* EMC_TXSR */
+ 0x00000200, /* EMC_TXSRDLL */
+ 0x0000000a, /* EMC_TCKE */
+ 0x0000000d, /* EMC_TFAW */
+ 0x00000000, /* EMC_TRPAB */
+ 0x00000004, /* EMC_TCLKSTABLE */
+ 0x00000005, /* EMC_TCLKSTOP */
+ 0x00000c6f, /* EMC_TREFBW */
+ 0x00000000, /* EMC_QUSE_EXTRA */
+ 0x00000006, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00007088, /* EMC_FBIO_CFG5 */
+ 0x001c0084, /* EMC_CFG_DIG_DLL */
+ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
+ 0x00034000, /* EMC_DLL_XFORM_DQS0 */
+ 0x00034000, /* EMC_DLL_XFORM_DQS1 */
+ 0x00034000, /* EMC_DLL_XFORM_DQS2 */
+ 0x00034000, /* EMC_DLL_XFORM_DQS3 */
+ 0x00034000, /* EMC_DLL_XFORM_DQS4 */
+ 0x00034000, /* EMC_DLL_XFORM_DQS5 */
+ 0x00034000, /* EMC_DLL_XFORM_DQS6 */
+ 0x00034000, /* EMC_DLL_XFORM_DQS7 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE0 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE1 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE2 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE3 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE4 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE5 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE6 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE7 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */
+ 0x00040000, /* EMC_DLL_XFORM_DQ0 */
+ 0x00040000, /* EMC_DLL_XFORM_DQ1 */
+ 0x00040000, /* EMC_DLL_XFORM_DQ2 */
+ 0x00040000, /* EMC_DLL_XFORM_DQ3 */
+ 0x000002a0, /* EMC_XM2CMDPADCTRL */
+ 0x0800013d, /* EMC_XM2DQSPADCTRL2 */
+ 0x00000000, /* EMC_XM2DQPADCTRL2 */
+ 0x77fff884, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f508, /* EMC_XM2COMPPADCTRL */
+ 0x05057404, /* EMC_XM2VTTGENPADCTRL */
+ 0x54000007, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x080001e8, /* EMC_XM2QUSEPADCTRL */
+ 0x08000021, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00020000, /* EMC_ZCAL_INTERVAL */
+ 0x00000100, /* EMC_ZCAL_WAIT_CNT */
+ 0x017f000c, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x80001941, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x0000000c, /* MC_EMEM_ARB_CFG */
+ 0xc000004a, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */
+ 0x0000000a, /* MC_EMEM_ARB_TIMING_RC */
+ 0x00000006, /* MC_EMEM_ARB_TIMING_RAS */
+ 0x00000006, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000009, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x06030202, /* MC_EMEM_ARB_DA_TURNS */
+ 0x000e070a, /* MC_EMEM_ARB_DA_COVERS */
+ 0x7547130b, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0x58000000, /* EMC_FBIO_SPARE */
+ 0xff00ff88, /* EMC_CFG_RSV */
+ },
+ 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000000, /* EMC_CFG.PERIODIC_QRST */
+ 0x80000731, /* Mode Register 0 */
+ 0x80100002, /* Mode Register 1 */
+ 0x80200008, /* Mode Register 2 */
+ 0x00000000, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 450000, /* SDRAM frequency */
+ {
+ 0x00000014, /* EMC_RC */
+ 0x00000046, /* EMC_RFC */
+ 0x0000000e, /* EMC_RAS */
+ 0x00000005, /* EMC_RP */
+ 0x00000003, /* EMC_R2W */
+ 0x00000009, /* EMC_W2R */
+ 0x00000002, /* EMC_R2P */
+ 0x0000000c, /* EMC_W2P */
+ 0x00000005, /* EMC_RD_RCD */
+ 0x00000005, /* EMC_WR_RCD */
+ 0x00000002, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000005, /* EMC_WDV */
+ 0x00000007, /* EMC_QUSE */
+ 0x00000005, /* EMC_QRST */
+ 0x0000000a, /* EMC_QSAFE */
+ 0x0000000e, /* EMC_RDV */
+ 0x00000d76, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x0000035d, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000001, /* EMC_PDEX2WR */
+ 0x00000009, /* EMC_PDEX2RD */
+ 0x00000001, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x00000009, /* EMC_AR2PDEN */
+ 0x00000011, /* EMC_RW2PDEN */
+ 0x0000004d, /* EMC_TXSR */
+ 0x00000200, /* EMC_TXSRDLL */
+ 0x00000004, /* EMC_TCKE */
+ 0x0000000e, /* EMC_TFAW */
+ 0x00000000, /* EMC_TRPAB */
+ 0x00000004, /* EMC_TCLKSTABLE */
+ 0x00000005, /* EMC_TCLKSTOP */
+ 0x00000db6, /* EMC_TREFBW */
+ 0x00000000, /* EMC_QUSE_EXTRA */
+ 0x00000006, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00007088, /* EMC_FBIO_CFG5 */
+ 0x00180084, /* EMC_CFG_DIG_DLL */
+ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
+ 0x00022000, /* EMC_DLL_XFORM_DQS0 */
+ 0x00022000, /* EMC_DLL_XFORM_DQS1 */
+ 0x00022000, /* EMC_DLL_XFORM_DQS2 */
+ 0x00022000, /* EMC_DLL_XFORM_DQS3 */
+ 0x00022000, /* EMC_DLL_XFORM_DQS4 */
+ 0x00022000, /* EMC_DLL_XFORM_DQS5 */
+ 0x00022000, /* EMC_DLL_XFORM_DQS6 */
+ 0x00022000, /* EMC_DLL_XFORM_DQS7 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE0 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE1 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE2 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE3 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE4 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE5 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE6 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE7 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */
+ 0x00030000, /* EMC_DLL_XFORM_DQ0 */
+ 0x00030000, /* EMC_DLL_XFORM_DQ1 */
+ 0x00030000, /* EMC_DLL_XFORM_DQ2 */
+ 0x00030000, /* EMC_DLL_XFORM_DQ3 */
+ 0x000002a0, /* EMC_XM2CMDPADCTRL */
+ 0x0800013d, /* EMC_XM2DQSPADCTRL2 */
+ 0x00000000, /* EMC_XM2DQPADCTRL2 */
+ 0x77fff884, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f508, /* EMC_XM2COMPPADCTRL */
+ 0x05057404, /* EMC_XM2VTTGENPADCTRL */
+ 0x54000007, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x080001e8, /* EMC_XM2QUSEPADCTRL */
+ 0x08000021, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00020000, /* EMC_ZCAL_INTERVAL */
+ 0x00000100, /* EMC_ZCAL_WAIT_CNT */
+ 0x0178000c, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x80001bc0, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x0000000d, /* MC_EMEM_ARB_CFG */
+ 0xc0000051, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RCD */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RP */
+ 0x0000000b, /* MC_EMEM_ARB_TIMING_RC */
+ 0x00000006, /* MC_EMEM_ARB_TIMING_RAS */
+ 0x00000006, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000009, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x06030202, /* MC_EMEM_ARB_DA_TURNS */
+ 0x000f080b, /* MC_EMEM_ARB_DA_COVERS */
+ 0x70a7150c, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xe8000000, /* EMC_FBIO_SPARE */
+ 0xff00ff8b, /* EMC_CFG_RSV */
+ },
+ 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000000, /* EMC_CFG.PERIODIC_QRST */
+ 0x80000731, /* Mode Register 0 */
+ 0x80100002, /* Mode Register 1 */
+ 0x80200008, /* Mode Register 2 */
+ 0x00000000, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 533000, /* SDRAM frequency */
+ {
+ 0x00000018, /* EMC_RC */
+ 0x00000054, /* EMC_RFC */
+ 0x00000011, /* EMC_RAS */
+ 0x00000006, /* EMC_RP */
+ 0x00000003, /* EMC_R2W */
+ 0x00000009, /* EMC_W2R */
+ 0x00000002, /* EMC_R2P */
+ 0x0000000d, /* EMC_W2P */
+ 0x00000006, /* EMC_RD_RCD */
+ 0x00000006, /* EMC_WR_RCD */
+ 0x00000002, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000005, /* EMC_WDV */
+ 0x00000008, /* EMC_QUSE */
+ 0x00000006, /* EMC_QRST */
+ 0x00000008, /* EMC_QSAFE */
+ 0x00000010, /* EMC_RDV */
+ 0x00000ffd, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x000003ff, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x0000000b, /* EMC_PDEX2WR */
+ 0x0000000b, /* EMC_PDEX2RD */
+ 0x00000001, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x0000000a, /* EMC_AR2PDEN */
+ 0x00000012, /* EMC_RW2PDEN */
+ 0x0000005b, /* EMC_TXSR */
+ 0x00000200, /* EMC_TXSRDLL */
+ 0x0000000d, /* EMC_TCKE */
+ 0x00000010, /* EMC_TFAW */
+ 0x00000000, /* EMC_TRPAB */
+ 0x00000005, /* EMC_TCLKSTABLE */
+ 0x00000006, /* EMC_TCLKSTOP */
+ 0x0000103e, /* EMC_TREFBW */
+ 0x00000000, /* EMC_QUSE_EXTRA */
+ 0x00000006, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00007088, /* EMC_FBIO_CFG5 */
+ 0x00120084, /* EMC_CFG_DIG_DLL */
+ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
+ 0x00010000, /* EMC_DLL_XFORM_DQS0 */
+ 0x00010000, /* EMC_DLL_XFORM_DQS1 */
+ 0x00010000, /* EMC_DLL_XFORM_DQS2 */
+ 0x00010000, /* EMC_DLL_XFORM_DQS3 */
+ 0x00010000, /* EMC_DLL_XFORM_DQS4 */
+ 0x00010000, /* EMC_DLL_XFORM_DQS5 */
+ 0x00010000, /* EMC_DLL_XFORM_DQS6 */
+ 0x00010000, /* EMC_DLL_XFORM_DQS7 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE0 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE1 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE2 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE3 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE4 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE5 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE6 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE7 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */
+ 0x00020000, /* EMC_DLL_XFORM_DQ0 */
+ 0x00020000, /* EMC_DLL_XFORM_DQ1 */
+ 0x00020000, /* EMC_DLL_XFORM_DQ2 */
+ 0x00020000, /* EMC_DLL_XFORM_DQ3 */
+ 0x000006a0, /* EMC_XM2CMDPADCTRL */
+ 0x0800013d, /* EMC_XM2DQSPADCTRL2 */
+ 0x00000000, /* EMC_XM2DQPADCTRL2 */
+ 0x77ffc084, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f508, /* EMC_XM2COMPPADCTRL */
+ 0x05057404, /* EMC_XM2VTTGENPADCTRL */
+ 0x54000007, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x08000168, /* EMC_XM2QUSEPADCTRL */
+ 0x08000021, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00000000, /* EMC_ZCAL_INTERVAL */
+ 0x00000040, /* EMC_ZCAL_WAIT_CNT */
+ 0x01ab000c, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10404, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x800020ae, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x0000000f, /* MC_EMEM_ARB_CFG */
+ 0xc0000060, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RCD */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RP */
+ 0x0000000d, /* MC_EMEM_ARB_TIMING_RC */
+ 0x00000008, /* MC_EMEM_ARB_TIMING_RAS */
+ 0x00000007, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000009, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x06030202, /* MC_EMEM_ARB_DA_TURNS */
+ 0x0010090d, /* MC_EMEM_ARB_DA_COVERS */
+ 0x7028180e, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0x00000000, /* EMC_FBIO_SPARE */
+ 0xff00ff00, /* EMC_CFG_RSV */
+ },
+ 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000000, /* EMC_CFG.PERIODIC_QRST */
+ 0x80000941, /* Mode Register 0 */
+ 0x80100002, /* Mode Register 1 */
+ 0x80200008, /* Mode Register 2 */
+ 0x00000000, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 667000, /* SDRAM frequency */
+ {
+ 0x0000001f, /* EMC_RC */
+ 0x00000069, /* EMC_RFC */
+ 0x00000016, /* EMC_RAS */
+ 0x00000008, /* EMC_RP */
+ 0x00000004, /* EMC_R2W */
+ 0x0000000c, /* EMC_W2R */
+ 0x00000003, /* EMC_R2P */
+ 0x00000011, /* EMC_W2P */
+ 0x00000008, /* EMC_RD_RCD */
+ 0x00000008, /* EMC_WR_RCD */
+ 0x00000002, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000007, /* EMC_WDV */
+ 0x0000000b, /* EMC_QUSE */
+ 0x00000009, /* EMC_QRST */
+ 0x0000000c, /* EMC_QSAFE */
+ 0x00000011, /* EMC_RDV */
+ 0x00001412, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x00000504, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x0000000e, /* EMC_PDEX2WR */
+ 0x0000000e, /* EMC_PDEX2RD */
+ 0x00000001, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x0000000c, /* EMC_AR2PDEN */
+ 0x00000016, /* EMC_RW2PDEN */
+ 0x00000072, /* EMC_TXSR */
+ 0x00000200, /* EMC_TXSRDLL */
+ 0x00000010, /* EMC_TCKE */
+ 0x00000015, /* EMC_TFAW */
+ 0x00000000, /* EMC_TRPAB */
+ 0x00000006, /* EMC_TCLKSTABLE */
+ 0x00000007, /* EMC_TCLKSTOP */
+ 0x00001453, /* EMC_TREFBW */
+ 0x0000000c, /* EMC_QUSE_EXTRA */
+ 0x00000004, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00005088, /* EMC_FBIO_CFG5 */
+ 0x40070191, /* EMC_CFG_DIG_DLL */
+ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
+ 0x00000008, /* EMC_DLL_XFORM_DQS0 */
+ 0x00000008, /* EMC_DLL_XFORM_DQS1 */
+ 0x00000008, /* EMC_DLL_XFORM_DQS2 */
+ 0x00000008, /* EMC_DLL_XFORM_DQS3 */
+ 0x00000008, /* EMC_DLL_XFORM_DQS4 */
+ 0x00000008, /* EMC_DLL_XFORM_DQS5 */
+ 0x00000008, /* EMC_DLL_XFORM_DQS6 */
+ 0x00000008, /* EMC_DLL_XFORM_DQS7 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE0 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE1 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE2 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE3 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE4 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE5 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE6 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE7 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */
+ 0x00000008, /* EMC_DLL_XFORM_DQ0 */
+ 0x00000008, /* EMC_DLL_XFORM_DQ1 */
+ 0x00000008, /* EMC_DLL_XFORM_DQ2 */
+ 0x00000008, /* EMC_DLL_XFORM_DQ3 */
+ 0x000002a0, /* EMC_XM2CMDPADCTRL */
+ 0x0600013d, /* EMC_XM2DQSPADCTRL2 */
+ 0x00000000, /* EMC_XM2DQPADCTRL2 */
+ 0x77fff884, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f508, /* EMC_XM2COMPPADCTRL */
+ 0x07077404, /* EMC_XM2VTTGENPADCTRL */
+ 0x54000000, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x080001e8, /* EMC_XM2QUSEPADCTRL */
+ 0x07000021, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00020000, /* EMC_ZCAL_INTERVAL */
+ 0x00000100, /* EMC_ZCAL_WAIT_CNT */
+ 0x01d6000c, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x800028a5, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x00000014, /* MC_EMEM_ARB_CFG */
+ 0xc0000079, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RCD */
+ 0x00000004, /* MC_EMEM_ARB_TIMING_RP */
+ 0x00000010, /* MC_EMEM_ARB_TIMING_RC */
+ 0x0000000a, /* MC_EMEM_ARB_TIMING_RAS */
+ 0x0000000a, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x0000000b, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000004, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000008, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x08040202, /* MC_EMEM_ARB_DA_TURNS */
+ 0x00140c10, /* MC_EMEM_ARB_DA_COVERS */
+ 0x734a1f11, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xf8000000, /* EMC_FBIO_SPARE */
+ 0xff00ff01, /* EMC_CFG_RSV */
+ },
+ 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000001, /* EMC_CFG.PERIODIC_QRST */
+ 0x80000b71, /* Mode Register 0 */
+ 0x80100002, /* Mode Register 1 */
+ 0x80200018, /* Mode Register 2 */
+ 0x00000000, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 750000, /* SDRAM frequency */
+ {
+ 0x00000025, /* EMC_RC */
+ 0x0000007e, /* EMC_RFC */
+ 0x0000001a, /* EMC_RAS */
+ 0x00000009, /* EMC_RP */
+ 0x00000004, /* EMC_R2W */
+ 0x0000000d, /* EMC_W2R */
+ 0x00000004, /* EMC_R2P */
+ 0x00000013, /* EMC_W2P */
+ 0x00000009, /* EMC_RD_RCD */
+ 0x00000009, /* EMC_WR_RCD */
+ 0x00000003, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000007, /* EMC_WDV */
+ 0x0000000b, /* EMC_QUSE */
+ 0x00000009, /* EMC_QRST */
+ 0x0000000c, /* EMC_QSAFE */
+ 0x00000011, /* EMC_RDV */
+ 0x0000169a, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x00000608, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000012, /* EMC_PDEX2WR */
+ 0x00000012, /* EMC_PDEX2RD */
+ 0x00000001, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x0000000f, /* EMC_AR2PDEN */
+ 0x00000018, /* EMC_RW2PDEN */
+ 0x00000088, /* EMC_TXSR */
+ 0x00000200, /* EMC_TXSRDLL */
+ 0x00000014, /* EMC_TCKE */
+ 0x00000018, /* EMC_TFAW */
+ 0x00000000, /* EMC_TRPAB */
+ 0x00000007, /* EMC_TCLKSTABLE */
+ 0x00000008, /* EMC_TCLKSTOP */
+ 0x00001860, /* EMC_TREFBW */
+ 0x0000000c, /* EMC_QUSE_EXTRA */
+ 0x00000004, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00005088, /* EMC_FBIO_CFG5 */
+ 0xf0080191, /* EMC_CFG_DIG_DLL */
+ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
+ 0x00000008, /* EMC_DLL_XFORM_DQS0 */
+ 0x00000008, /* EMC_DLL_XFORM_DQS1 */
+ 0x00000008, /* EMC_DLL_XFORM_DQS2 */
+ 0x00000008, /* EMC_DLL_XFORM_DQS3 */
+ 0x00000008, /* EMC_DLL_XFORM_DQS4 */
+ 0x00000008, /* EMC_DLL_XFORM_DQS5 */
+ 0x00000008, /* EMC_DLL_XFORM_DQS6 */
+ 0x00000008, /* EMC_DLL_XFORM_DQS7 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE0 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE1 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE2 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE3 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE4 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE5 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE6 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE7 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ0 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ1 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ2 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ3 */
+ 0x000002a0, /* EMC_XM2CMDPADCTRL */
+ 0x0600013d, /* EMC_XM2DQSPADCTRL2 */
+ 0x22220000, /* EMC_XM2DQPADCTRL2 */
+ 0x77fff884, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f501, /* EMC_XM2COMPPADCTRL */
+ 0x07077404, /* EMC_XM2VTTGENPADCTRL */
+ 0x54000000, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x080001e8, /* EMC_XM2QUSEPADCTRL */
+ 0x07000021, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00020000, /* EMC_ZCAL_INTERVAL */
+ 0x00000100, /* EMC_ZCAL_WAIT_CNT */
+ 0x0180000c, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x8000308c, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x00000016, /* MC_EMEM_ARB_CFG */
+ 0xc0000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */
+ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */
+ 0x00000013, /* MC_EMEM_ARB_TIMING_RC */
+ 0x0000000c, /* MC_EMEM_ARB_TIMING_RAS */
+ 0x0000000b, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x0000000c, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000004, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000008, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x08040202, /* MC_EMEM_ARB_DA_TURNS */
+ 0x00160d13, /* MC_EMEM_ARB_DA_COVERS */
+ 0x72ac2414, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xf8000000, /* EMC_FBIO_SPARE */
+ 0xff00ff49, /* EMC_CFG_RSV */
+ },
+ 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000001, /* EMC_CFG.PERIODIC_QRST */
+ 0x80000d71, /* Mode Register 0 */
+ 0x80100002, /* Mode Register 1 */
+ 0x80200018, /* Mode Register 2 */
+ 0x00000000, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 800000, /* SDRAM frequency */
+ {
+ 0x00000025, /* EMC_RC */
+ 0x0000007e, /* EMC_RFC */
+ 0x0000001a, /* EMC_RAS */
+ 0x00000009, /* EMC_RP */
+ 0x00000004, /* EMC_R2W */
+ 0x0000000d, /* EMC_W2R */
+ 0x00000004, /* EMC_R2P */
+ 0x00000013, /* EMC_W2P */
+ 0x00000009, /* EMC_RD_RCD */
+ 0x00000009, /* EMC_WR_RCD */
+ 0x00000003, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000007, /* EMC_WDV */
+ 0x0000000b, /* EMC_QUSE */
+ 0x00000009, /* EMC_QRST */
+ 0x0000000c, /* EMC_QSAFE */
+ 0x00000011, /* EMC_RDV */
+ 0x00001820, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x00000608, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000012, /* EMC_PDEX2WR */
+ 0x00000012, /* EMC_PDEX2RD */
+ 0x00000001, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x0000000f, /* EMC_AR2PDEN */
+ 0x00000018, /* EMC_RW2PDEN */
+ 0x00000088, /* EMC_TXSR */
+ 0x00000200, /* EMC_TXSRDLL */
+ 0x00000014, /* EMC_TCKE */
+ 0x00000018, /* EMC_TFAW */
+ 0x00000000, /* EMC_TRPAB */
+ 0x00000007, /* EMC_TCLKSTABLE */
+ 0x00000008, /* EMC_TCLKSTOP */
+ 0x00001860, /* EMC_TREFBW */
+ 0x0000000c, /* EMC_QUSE_EXTRA */
+ 0x00000004, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00005088, /* EMC_FBIO_CFG5 */
+ 0xf0070191, /* EMC_CFG_DIG_DLL */
+ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
+ 0x0000800a, /* EMC_DLL_XFORM_DQS0 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQS1 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQS2 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQS3 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQS4 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQS5 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQS6 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQS7 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE0 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE1 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE2 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE3 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE4 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE5 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE6 */
+ 0x00000000, /* EMC_DLL_XFORM_QUSE7 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */
+ 0x007fc00a, /* EMC_DLL_XFORM_DQ0 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQ1 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQ2 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQ3 */
+ 0x000002a0, /* EMC_XM2CMDPADCTRL */
+ 0x0600013d, /* EMC_XM2DQSPADCTRL2 */
+ 0x22220000, /* EMC_XM2DQPADCTRL2 */
+ 0x77fff884, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f501, /* EMC_XM2COMPPADCTRL */
+ 0x07077404, /* EMC_XM2VTTGENPADCTRL */
+ 0x54000000, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x080001e8, /* EMC_XM2QUSEPADCTRL */
+ 0x07000021, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00020000, /* EMC_ZCAL_INTERVAL */
+ 0x00000100, /* EMC_ZCAL_WAIT_CNT */
+ 0x0180000c, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x8000308c, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x00000018, /* MC_EMEM_ARB_CFG */
+ 0xc0000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */
+ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */
+ 0x00000013, /* MC_EMEM_ARB_TIMING_RC */
+ 0x0000000c, /* MC_EMEM_ARB_TIMING_RAS */
+ 0x0000000b, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x0000000c, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000004, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000008, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x08040202, /* MC_EMEM_ARB_DA_TURNS */
+ 0x00160d13, /* MC_EMEM_ARB_DA_COVERS */
+ 0x72ac2414, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xf8000000, /* EMC_FBIO_SPARE */
+ 0xff00ff49, /* EMC_CFG_RSV */
+ },
+ 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000001, /* EMC_CFG.PERIODIC_QRST */
+ 0x80000d71, /* Mode Register 0 */
+ 0x80100002, /* Mode Register 1 */
+ 0x80200018, /* Mode Register 2 */
+ 0x00000000, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 900000, /* SDRAM frequency */
+ {
+ 0x0000002a, /* EMC_RC */
+ 0x0000008e, /* EMC_RFC */
+ 0x0000001e, /* EMC_RAS */
+ 0x0000000b, /* EMC_RP */
+ 0x00000006, /* EMC_R2W */
+ 0x0000000f, /* EMC_W2R */
+ 0x00000005, /* EMC_R2P */
+ 0x00000016, /* EMC_W2P */
+ 0x0000000b, /* EMC_RD_RCD */
+ 0x0000000b, /* EMC_WR_RCD */
+ 0x00000004, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000008, /* EMC_WDV */
+ 0x0000000d, /* EMC_QUSE */
+ 0x0000000b, /* EMC_QRST */
+ 0x0000000b, /* EMC_QSAFE */
+ 0x00000014, /* EMC_RDV */
+ 0x00001b2c, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x000006cb, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000004, /* EMC_PDEX2WR */
+ 0x00000014, /* EMC_PDEX2RD */
+ 0x00000001, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x00000011, /* EMC_AR2PDEN */
+ 0x0000001b, /* EMC_RW2PDEN */
+ 0x00000099, /* EMC_TXSR */
+ 0x00000200, /* EMC_TXSRDLL */
+ 0x00000006, /* EMC_TCKE */
+ 0x0000001b, /* EMC_TFAW */
+ 0x00000000, /* EMC_TRPAB */
+ 0x00000008, /* EMC_TCLKSTABLE */
+ 0x00000009, /* EMC_TCLKSTOP */
+ 0x00001b6c, /* EMC_TREFBW */
+ 0x0000000e, /* EMC_QUSE_EXTRA */
+ 0x00000004, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00005088, /* EMC_FBIO_CFG5 */
+ 0xf0040191, /* EMC_CFG_DIG_DLL */
+ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
+ 0x0000800a, /* EMC_DLL_XFORM_DQS0 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQS1 */
+ 0x007fc00a, /* EMC_DLL_XFORM_DQS2 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQS3 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQS4 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQS5 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQS6 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQS7 */
+ 0x0001c000, /* EMC_DLL_XFORM_QUSE0 */
+ 0x0001c000, /* EMC_DLL_XFORM_QUSE1 */
+ 0x0001c000, /* EMC_DLL_XFORM_QUSE2 */
+ 0x0001c000, /* EMC_DLL_XFORM_QUSE3 */
+ 0x0001c000, /* EMC_DLL_XFORM_QUSE4 */
+ 0x0001c000, /* EMC_DLL_XFORM_QUSE5 */
+ 0x0001c000, /* EMC_DLL_XFORM_QUSE6 */
+ 0x0001c000, /* EMC_DLL_XFORM_QUSE7 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */
+ 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */
+ 0x007fc00a, /* EMC_DLL_XFORM_DQ0 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQ1 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQ2 */
+ 0x0000000a, /* EMC_DLL_XFORM_DQ3 */
+ 0x000002a0, /* EMC_XM2CMDPADCTRL */
+ 0x0600013d, /* EMC_XM2DQSPADCTRL2 */
+ 0x22220000, /* EMC_XM2DQPADCTRL2 */
+ 0x77fff884, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f501, /* EMC_XM2COMPPADCTRL */
+ 0x07077404, /* EMC_XM2VTTGENPADCTRL */
+ 0x54000000, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x080001e8, /* EMC_XM2QUSEPADCTRL */
+ 0x07000021, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00020000, /* EMC_ZCAL_INTERVAL */
+ 0x00000120, /* EMC_ZCAL_WAIT_CNT */
+ 0x0128000c, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x8000367d, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x0000001b, /* MC_EMEM_ARB_CFG */
+ 0xc00000a2, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0x00000005, /* MC_EMEM_ARB_TIMING_RCD */
+ 0x00000006, /* MC_EMEM_ARB_TIMING_RP */
+ 0x00000016, /* MC_EMEM_ARB_TIMING_RC */
+ 0x0000000e, /* MC_EMEM_ARB_TIMING_RAS */
+ 0x0000000d, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000004, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x0000000e, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000005, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000009, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x09050202, /* MC_EMEM_ARB_DA_TURNS */
+ 0x001a1016, /* MC_EMEM_ARB_DA_COVERS */
+ 0x714e2917, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xe8000000, /* EMC_FBIO_SPARE */
+ 0xff00ff4b, /* EMC_CFG_RSV */
+ },
+ 0x00000048, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000001, /* EMC_CFG.PERIODIC_QRST */
+ 0x80000f15, /* Mode Register 0 */
+ 0x80100002, /* Mode Register 1 */
+ 0x80200020, /* Mode Register 2 */
+ 0x00000000, /* EMC_CFG.DYN_SELF_REF */
+ },
+};
+#endif
+
+static const struct tegra_emc_table apalis_t30_emc_tables_mt41k256m16re_15e[] = {
+//25.5, 51, 102
+ {
+ 0x32, /* Rev 3.2 */
+//204 MHz crashes
+ 200000, /* SDRAM frequency [kHz] */
+ {
+ 0x0000000a, /* EmcRc */
+ 0x00000033, /* EmcRfc */
+ 0x00000007, /* EmcRas */
+ 0x00000002, /* EmcRp */
+ 0x00000003, /* EmcR2w */
+ 0x00000009, /* EmcW2r */
+ 0x00000005, /* EmcR2p */
+ 0x0000000a, /* EmcW2p */
+ 0x00000002, /* EmcRdRcd */
+ 0x00000002, /* EmcWrRcd */
+ 0x00000003, /* EmcRrd */
+ 0x00000001, /* EmcRext */
+ 0x00000000, /* EmcWext */
+ 0x00000004, /* EmcWdv */
+ 0x00000005, /* EmcQUse */
+ 0x00000004, /* EmcQRst */
+ 0x00000009, /* EmcQSafe */
+ 0x0000000b, /* EmcRdv */
+ 0x000005e9, /* EmcRefresh */
+ 0x00000000, /* EmcBurstRefreshNum */
+ 0x0000017a, /* EmcPreRefreshReqCnt */
+ 0x00000002, /* EmcPdEx2Wr */
+ 0x00000002, /* EmcPdEx2Rd */
+ 0x00000001, /* EmcPChg2Pden */
+ 0x00000000, /* EmcAct2Pden */
+ 0x00000007, /* EmcAr2Pden */
+ 0x0000000e, /* EmcRw2Pden */
+ 0x00000036, /* EmcTxsr */
+ 0x00000134, /* EmcTxsrDll */
+ 0x00000004, /* EmcTcke */
+ 0x0000000a, /* EmcTfaw */
+ 0x00000000, /* EmcTrpab */
+ 0x00000004, /* EmcTClkStable */
+ 0x00000005, /* EmcTClkStop */
+ 0x00000618, /* EmcTRefBw */
+ 0x00000006, /* EmcQUseExtra */
+ 0x00000004, /* EmcFbioCfg6 */
+ 0x00000000, /* EmcOdtWrite */
+ 0x00000000, /* EmcOdtRead */
+ 0x00004288, /* EmcFbioCfg5 */
+ 0x004600a4, /* EmcCfgDigDll */
+ 0x00008000, /* EmcCfgDigDllPeriod */
+ 0x00080000, /* EmcDllXformDqs0 */
+ 0x00080000, /* EmcDllXformDqs1 */
+ 0x00080000, /* EmcDllXformDqs2 */
+ 0x00080000, /* EmcDllXformDqs3 */
+ 0x00080000, /* EmcDllXformDqs4 */
+ 0x00080000, /* EmcDllXformDqs5 */
+ 0x00080000, /* EmcDllXformDqs6 */
+ 0x00080000, /* EmcDllXformDqs7 */
+ 0x00000000, /* EmcDllXformQUse0 */
+ 0x00000000, /* EmcDllXformQUse1 */
+ 0x00000000, /* EmcDllXformQUse2 */
+ 0x00000000, /* EmcDllXformQUse3 */
+ 0x00000000, /* EmcDllXformQUse4 */
+ 0x00000000, /* EmcDllXformQUse5 */
+ 0x00000000, /* EmcDllXformQUse6 */
+ 0x00000000, /* EmcDllXformQUse7 */
+ 0x00000000, /* EmcDliTrimTxDqs0 */
+ 0x00000000, /* EmcDliTrimTxDqs1 */
+ 0x00000000, /* EmcDliTrimTxDqs2 */
+ 0x00000000, /* EmcDliTrimTxDqs3 */
+ 0x00000000, /* EmcDliTrimTxDqs4 */
+ 0x00000000, /* EmcDliTrimTxDqs5 */
+ 0x00000000, /* EmcDliTrimTxDqs6 */
+ 0x00000000, /* EmcDliTrimTxDqs7 */
+ 0x00080000, /* EmcDllXformDq0 */
+ 0x00080000, /* EmcDllXformDq1 */
+ 0x00080000, /* EmcDllXformDq2 */
+ 0x00080000, /* EmcDllXformDq3 */
+ 0x000002a0, /* EmcXm2CmdPadCtrl */
+ 0x0800211c, /* EmcXm2DqsPadCtrl2 */
+ 0x00000000, /* EmcXm2DqPadCtrl2 */
+ 0x77fff884, /* EmcXm2ClkPadCtrl */
+ 0x01f1f108, /* EmcXm2CompPadCtrl */
+ 0x05057404, /* EmcXm2VttGenPadCtrl */
+ 0x54000007, /* EmcXm2VttGenPadCtrl2 */
+ 0x08000168, /* EmcXm2QUsePadCtrl */
+ 0x08000000, /* EmcXm2DqsPadCtrl3 */
+ 0x00000802, /* EmcCttTermCtrl */
+ 0x00020000, /* EmcZcalInterval */
+ 0x00000040, /* EmcZcalWaitCnt */
+ 0x000c000c, /* EmcMrsWaitCnt */
+ 0x001fffff, /* EmcAutoCalInterval */
+ 0x00000000, /* EmcCtt */
+ 0x00000000, /* EmcCttDuration */
+ 0x80000ce6, /* EmcDynSelfRefControl */
+ 0x00000003, /* McEmemArbCfg */
+ 0xc0000024, /* McEmemArbOutstandingReq */
+ 0x00000001, /* McEmemArbTimingRcd */
+ 0x00000001, /* McEmemArbTimingRp */
+ 0x00000005, /* McEmemArbTimingRc */
+ 0x00000002, /* McEmemArbTimingRas */
+ 0x00000004, /* McEmemArbTimingFaw */
+ 0x00000001, /* McEmemArbTimingRrd */
+ 0x00000003, /* McEmemArbTimingRap2Pre */
+ 0x00000007, /* McEmemArbTimingWap2Pre */
+ 0x00000002, /* McEmemArbTimingR2R */
+ 0x00000001, /* McEmemArbTimingW2W */
+ 0x00000003, /* McEmemArbTimingR2W */
+ 0x00000006, /* McEmemArbTimingW2R */
+ 0x06030102, /* McEmemArbDaTurns */
+ 0x00090505, /* McEmemArbDaCovers */
+ 0x76a30906, /* McEmemArbMisc0 */
+ 0x001f0000, /* McEmemArbRing1Throttle */
+ 0xe8000000, /* EmcFbioSpare */
+ 0xff00ff00, /* EmcCfgRsv */
+ },
+ 0x00000040, /* EmcZcalWaitCnt */
+ 0x00020000, /* EmcZcalInterval */
+ 0x00000001, /* EmcCfg bit 27PERIODIC_QRST */
+ 0x80001221, /* EmcMrs */
+ 0x80100003, /* EmcEmrs */
+ 0x00000000, /* EmcMrw1 */
+ 0x00000001, /* EmcCfg bit 28 DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 300000, /* SDRAM frequency [kHz] */
+ {
+ 0x00000010, /* EmcRc */
+ 0x0000004d, /* EmcRfc */
+ 0x0000000b, /* EmcRas */
+ 0x00000003, /* EmcRp */
+ 0x00000002, /* EmcR2w */
+ 0x00000008, /* EmcW2r */
+ 0x00000003, /* EmcR2p */
+ 0x00000009, /* EmcW2p */
+ 0x00000003, /* EmcRdRcd */
+ 0x00000002, /* EmcWrRcd */
+ 0x00000002, /* EmcRrd */
+ 0x00000001, /* EmcRext */
+ 0x00000000, /* EmcWext */
+ 0x00000004, /* EmcWdv */
+ 0x00000006, /* EmcQUse */
+ 0x00000004, /* EmcQRst */
+ 0x0000000a, /* EmcQSafe */
+ 0x0000000c, /* EmcRdv */
+ 0x000008e6, /* EmcRefresh */
+ 0x00000000, /* EmcBurstRefreshNum */
+ 0x00000240, /* EmcPreRefreshReqCnt */
+ 0x0000000a, /* EmcPdEx2Wr */
+ 0x00000008, /* EmcPdEx2Rd */
+ 0x00000007, /* EmcPChg2Pden */
+ 0x00000000, /* EmcAct2Pden */
+ 0x00000007, /* EmcAr2Pden */
+ 0x0000000e, /* EmcRw2Pden */
+ 0x000000b4, /* EmcTxsr */
+ 0x00000200, /* EmcTxsrDll */
+ 0x00000004, /* EmcTcke */
+ 0x00000010, /* EmcTfaw */
+ 0x00000000, /* EmcTrpab */
+ 0x00000004, /* EmcTClkStable */
+ 0x00000005, /* EmcTClkStop */
+ 0x00000927, /* EmcTRefBw */
+ 0x00000007, /* EmcQUseExtra */
+ 0x00000004, /* EmcFbioCfg6 */
+ 0x00000000, /* EmcOdtWrite */
+ 0x00000000, /* EmcOdtRead */
+ 0x00005288, /* EmcFbioCfg5 */
+ 0x002b00a4, /* EmcCfgDigDll */
+ 0x00008000, /* EmcCfgDigDllPeriod */
+ 0x00014000, /* EmcDllXformDqs0 */
+ 0x00014000, /* EmcDllXformDqs1 */
+ 0x00014000, /* EmcDllXformDqs2 */
+ 0x00014000, /* EmcDllXformDqs3 */
+ 0x00014000, /* EmcDllXformDqs4 */
+ 0x00014000, /* EmcDllXformDqs5 */
+ 0x00014000, /* EmcDllXformDqs6 */
+ 0x00014000, /* EmcDllXformDqs7 */
+ 0x00000000, /* EmcDllXformQUse0 */
+ 0x00000000, /* EmcDllXformQUse1 */
+ 0x00000000, /* EmcDllXformQUse2 */
+ 0x00000000, /* EmcDllXformQUse3 */
+ 0x00000000, /* EmcDllXformQUse4 */
+ 0x00000000, /* EmcDllXformQUse5 */
+ 0x00000000, /* EmcDllXformQUse6 */
+ 0x00000000, /* EmcDllXformQUse7 */
+ 0x00000000, /* EmcDliTrimTxDqs0 */
+ 0x00000000, /* EmcDliTrimTxDqs1 */
+ 0x00000000, /* EmcDliTrimTxDqs2 */
+ 0x00000000, /* EmcDliTrimTxDqs3 */
+ 0x00000000, /* EmcDliTrimTxDqs4 */
+ 0x00000000, /* EmcDliTrimTxDqs5 */
+ 0x00000000, /* EmcDliTrimTxDqs6 */
+ 0x00000000, /* EmcDliTrimTxDqs7 */
+ 0x00020000, /* EmcDllXformDq0 */
+ 0x00020000, /* EmcDllXformDq1 */
+ 0x00020000, /* EmcDllXformDq2 */
+ 0x00020000, /* EmcDllXformDq3 */
+ 0x000002a0, /* EmcXm2CmdPadCtrl */
+ 0x0800211c, /* EmcXm2DqsPadCtrl2 */
+ 0x00000000, /* EmcXm2DqPadCtrl2 */
+ 0x77fff884, /* EmcXm2ClkPadCtrl */
+ 0x01f1f508, /* EmcXm2CompPadCtrl */
+ 0x05057404, /* EmcXm2VttGenPadCtrl */
+ 0x54000007, /* EmcXm2VttGenPadCtrl2 */
+ 0x08000168, /* EmcXm2QUsePadCtrl */
+ 0x08000000, /* EmcXm2DqsPadCtrl3 */
+ 0x00000802, /* EmcCttTermCtrl */
+ 0x00020000, /* EmcZcalInterval */
+ 0x00000040, /* EmcZcalWaitCnt */
+ 0x0172000c, /* EmcMrsWaitCnt */
+ 0x001fffff, /* EmcAutoCalInterval */
+ 0x00000000, /* EmcCtt */
+ 0x00000000, /* EmcCttDuration */
+ 0x800012db, /* EmcDynSelfRefControl */
+ 0x00000004, /* McEmemArbCfg */
+ 0x80000037, /* McEmemArbOutstandingReq */
+ 0x00000001, /* McEmemArbTimingRcd */
+ 0x00000001, /* McEmemArbTimingRp */
+ 0x00000007, /* McEmemArbTimingRc */
+ 0x00000004, /* McEmemArbTimingRas */
+ 0x00000007, /* McEmemArbTimingFaw */
+ 0x00000001, /* McEmemArbTimingRrd */
+ 0x00000002, /* McEmemArbTimingRap2Pre */
+ 0x00000007, /* McEmemArbTimingWap2Pre */
+ 0x00000002, /* McEmemArbTimingR2R */
+ 0x00000002, /* McEmemArbTimingW2W */
+ 0x00000005, /* McEmemArbTimingR2W */
+ 0x00000006, /* McEmemArbTimingW2R */
+ 0x06030202, /* McEmemArbDaTurns */
+ 0x000a0507, /* McEmemArbDaCovers */
+ 0x70850e08, /* McEmemArbMisc0 */
+ 0x001f0000, /* McEmemArbRing1Throttle */
+ 0xe8000000, /* EmcFbioSpare */
+ 0xff00ff88, /* EmcCfgRsv */
+ },
+ 0x00000040, /* EmcZcalWaitCnt */
+ 0x00020000, /* EmcZcalInterval */
+ 0x00000001, /* EmcCfg bit 27PERIODIC_QRST */
+ 0x80000321, /* EmcMrs */
+ 0x80100002, /* EmcEmrs */
+ 0x00000000, /* EmcMrw1 */
+ 0x00000000, /* EmcCfg bit 28 DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 333000, /* SDRAM frequency [kHz] */
+ {
+ 0x00000010, /* EmcRc */
+ 0x00000055, /* EmcRfc */
+ 0x0000000c, /* EmcRas */
+ 0x00000004, /* EmcRp */
+ 0x00000006, /* EmcR2w */
+ 0x00000008, /* EmcW2r */
+ 0x00000003, /* EmcR2p */
+ 0x00000009, /* EmcW2p */
+ 0x00000004, /* EmcRdRcd */
+ 0x00000003, /* EmcWrRcd */
+ 0x00000002, /* EmcRrd */
+ 0x00000001, /* EmcRext */
+ 0x00000000, /* EmcWext */
+ 0x00000004, /* EmcWdv */
+ 0x00000006, /* EmcQUse */
+ 0x00000004, /* EmcQRst */
+ 0x0000000a, /* EmcQSafe */
+ 0x0000000c, /* EmcRdv */
+ 0x000009e8, /* EmcRefresh */
+ 0x00000000, /* EmcBurstRefreshNum */
+ 0x0000027e, /* EmcPreRefreshReqCnt */
+ 0x0000000a, /* EmcPdEx2Wr */
+ 0x00000008, /* EmcPdEx2Rd */
+ 0x00000007, /* EmcPChg2Pden */
+ 0x00000000, /* EmcAct2Pden */
+ 0x00000007, /* EmcAr2Pden */
+ 0x0000000e, /* EmcRw2Pden */
+ 0x000000b4, /* EmcTxsr */
+ 0x00000200, /* EmcTxsrDll */
+ 0x00000004, /* EmcTcke */
+ 0x00000015, /* EmcTfaw */
+ 0x00000000, /* EmcTrpab */
+ 0x00000004, /* EmcTClkStable */
+ 0x00000005, /* EmcTClkStop */
+ 0x00000a28, /* EmcTRefBw */
+ 0x00000000, /* EmcQUseExtra */
+ 0x00000006, /* EmcFbioCfg6 */
+ 0x00000000, /* EmcOdtWrite */
+ 0x00000000, /* EmcOdtRead */
+ 0x00007088, /* EmcFbioCfg5 */
+ 0x002600a4, /* EmcCfgDigDll */
+ 0x00008000, /* EmcCfgDigDllPeriod */
+ 0x00014000, /* EmcDllXformDqs0 */
+ 0x00014000, /* EmcDllXformDqs1 */
+ 0x00014000, /* EmcDllXformDqs2 */
+ 0x00014000, /* EmcDllXformDqs3 */
+ 0x00014000, /* EmcDllXformDqs4 */
+ 0x00014000, /* EmcDllXformDqs5 */
+ 0x00014000, /* EmcDllXformDqs6 */
+ 0x00014000, /* EmcDllXformDqs7 */
+ 0x00000000, /* EmcDllXformQUse0 */
+ 0x00000000, /* EmcDllXformQUse1 */
+ 0x00000000, /* EmcDllXformQUse2 */
+ 0x00000000, /* EmcDllXformQUse3 */
+ 0x00000000, /* EmcDllXformQUse4 */
+ 0x00000000, /* EmcDllXformQUse5 */
+ 0x00000000, /* EmcDllXformQUse6 */
+ 0x00000000, /* EmcDllXformQUse7 */
+ 0x00000000, /* EmcDliTrimTxDqs0 */
+ 0x00000000, /* EmcDliTrimTxDqs1 */
+ 0x00000000, /* EmcDliTrimTxDqs2 */
+ 0x00000000, /* EmcDliTrimTxDqs3 */
+ 0x00000000, /* EmcDliTrimTxDqs4 */
+ 0x00000000, /* EmcDliTrimTxDqs5 */
+ 0x00000000, /* EmcDliTrimTxDqs6 */
+ 0x00000000, /* EmcDliTrimTxDqs7 */
+ 0x00020000, /* EmcDllXformDq0 */
+ 0x00020000, /* EmcDllXformDq1 */
+ 0x00020000, /* EmcDllXformDq2 */
+ 0x00020000, /* EmcDllXformDq3 */
+ 0x000002a0, /* EmcXm2CmdPadCtrl */
+ 0x0800013d, /* EmcXm2DqsPadCtrl2 */
+ 0x00000000, /* EmcXm2DqPadCtrl2 */
+ 0x77fff884, /* EmcXm2ClkPadCtrl */
+ 0x01f1f508, /* EmcXm2CompPadCtrl */
+ 0x05057404, /* EmcXm2VttGenPadCtrl */
+ 0x54000007, /* EmcXm2VttGenPadCtrl2 */
+ 0x080001e8, /* EmcXm2QUsePadCtrl */
+ 0x08000021, /* EmcXm2DqsPadCtrl3 */
+ 0x00000802, /* EmcCttTermCtrl */
+ 0x00020000, /* EmcZcalInterval */
+ 0x00000040, /* EmcZcalWaitCnt */
+ 0x016a000c, /* EmcMrsWaitCnt */
+ 0x001fffff, /* EmcAutoCalInterval */
+ 0x00000000, /* EmcCtt */
+ 0x00000000, /* EmcCttDuration */
+ 0x800014d2, /* EmcDynSelfRefControl */
+ 0x00000005, /* McEmemArbCfg */
+ 0x8000003c, /* McEmemArbOutstandingReq */
+ 0x00000001, /* McEmemArbTimingRcd */
+ 0x00000002, /* McEmemArbTimingRp */
+ 0x00000008, /* McEmemArbTimingRc */
+ 0x00000005, /* McEmemArbTimingRas */
+ 0x0000000a, /* McEmemArbTimingFaw */
+ 0x00000001, /* McEmemArbTimingRrd */
+ 0x00000002, /* McEmemArbTimingRap2Pre */
+ 0x00000007, /* McEmemArbTimingWap2Pre */
+ 0x00000002, /* McEmemArbTimingR2R */
+ 0x00000002, /* McEmemArbTimingW2W */
+ 0x00000005, /* McEmemArbTimingR2W */
+ 0x00000006, /* McEmemArbTimingW2R */
+ 0x06030202, /* McEmemArbDaTurns */
+ 0x000b0608, /* McEmemArbDaCovers */
+ 0x70850f09, /* McEmemArbMisc0 */
+ 0x001f0000, /* McEmemArbRing1Throttle */
+ 0xe8000000, /* EmcFbioSpare */
+ 0xff00ff88, /* EmcCfgRsv */
+ },
+ 0x00000040, /* EmcZcalWaitCnt */
+ 0x00020000, /* EmcZcalInterval */
+ 0x00000000, /* EmcCfg bit 27PERIODIC_QRST */
+ 0x80000321, /* EmcMrs */
+ 0x80100002, /* EmcEmrs */
+ 0x00000000, /* EmcMrw1 */
+ 0x00000000, /* EmcCfg bit 28 DYN_SELF_REF */
+ },
+//400
+ {
+ 0x32, /* Rev 3.2 */
+ 533000, /* SDRAM frequency [kHz] */
+ {
+ 0x0000001a, /* EmcRc */
+ 0x0000008b, /* EmcRfc */
+ 0x00000013, /* EmcRas */
+ 0x00000006, /* EmcRp */
+ 0x00000006, /* EmcR2w */
+ 0x0000000b, /* EmcW2r */
+ 0x00000003, /* EmcR2p */
+ 0x0000000e, /* EmcW2p */
+ 0x00000006, /* EmcRdRcd */
+ 0x00000006, /* EmcWrRcd */
+ 0x00000003, /* EmcRrd */
+ 0x00000001, /* EmcRext */
+ 0x00000000, /* EmcWext */
+ 0x00000006, /* EmcWdv */
+ 0x00000009, /* EmcQUse */
+ 0x00000007, /* EmcQRst */
+ 0x0000000a, /* EmcQSafe */
+ 0x0000000f, /* EmcRdv */
+ 0x0000100b, /* EmcRefresh */
+ 0x00000000, /* EmcBurstRefreshNum */
+ 0x000003ff, /* EmcPreRefreshReqCnt */
+ 0x0000000c, /* EmcPdEx2Wr */
+ 0x0000000c, /* EmcPdEx2Rd */
+ 0x00000007, /* EmcPChg2Pden */
+ 0x00000000, /* EmcAct2Pden */
+ 0x0000000a, /* EmcAr2Pden */
+ 0x00000012, /* EmcRw2Pden */
+ 0x000000b4, /* EmcTxsr */
+ 0x00000200, /* EmcTxsrDll */
+ 0x00000004, /* EmcTcke */
+ 0x0000001e, /* EmcTfaw */
+ 0x00000000, /* EmcTrpab */
+ 0x00000005, /* EmcTClkStable */
+ 0x00000006, /* EmcTClkStop */
+ 0x0000103e, /* EmcTRefBw */
+ 0x00000000, /* EmcQUseExtra */
+ 0x00000006, /* EmcFbioCfg6 */
+ 0x00000000, /* EmcOdtWrite */
+ 0x00000000, /* EmcOdtRead */
+ 0x00007088, /* EmcFbioCfg5 */
+ 0xf0120091, /* EmcCfgDigDll */
+ 0x00008000, /* EmcCfgDigDllPeriod */
+ 0x0000000a, /* EmcDllXformDqs0 */
+ 0x0000000a, /* EmcDllXformDqs1 */
+ 0x0000000a, /* EmcDllXformDqs2 */
+ 0x0000000a, /* EmcDllXformDqs3 */
+ 0x0000000a, /* EmcDllXformDqs4 */
+ 0x0000000a, /* EmcDllXformDqs5 */
+ 0x0000000a, /* EmcDllXformDqs6 */
+ 0x0000000a, /* EmcDllXformDqs7 */
+ 0x00000000, /* EmcDllXformQUse0 */
+ 0x00000000, /* EmcDllXformQUse1 */
+ 0x00000000, /* EmcDllXformQUse2 */
+ 0x00000000, /* EmcDllXformQUse3 */
+ 0x00000000, /* EmcDllXformQUse4 */
+ 0x00000000, /* EmcDllXformQUse5 */
+ 0x00000000, /* EmcDllXformQUse6 */
+ 0x00000000, /* EmcDllXformQUse7 */
+ 0x00000000, /* EmcDliTrimTxDqs0 */
+ 0x00000000, /* EmcDliTrimTxDqs1 */
+ 0x00000000, /* EmcDliTrimTxDqs2 */
+ 0x00000000, /* EmcDliTrimTxDqs3 */
+ 0x00000000, /* EmcDliTrimTxDqs4 */
+ 0x00000000, /* EmcDliTrimTxDqs5 */
+ 0x00000000, /* EmcDliTrimTxDqs6 */
+ 0x00000000, /* EmcDliTrimTxDqs7 */
+ 0x0000000a, /* EmcDllXformDq0 */
+ 0x0000000a, /* EmcDllXformDq1 */
+ 0x0000000a, /* EmcDllXformDq2 */
+ 0x0000000a, /* EmcDllXformDq3 */
+ 0x000002a0, /* EmcXm2CmdPadCtrl */
+ 0x0800013d, /* EmcXm2DqsPadCtrl2 */
+ 0x00000000, /* EmcXm2DqPadCtrl2 */
+ 0x77fff884, /* EmcXm2ClkPadCtrl */
+ 0x01f1f508, /* EmcXm2CompPadCtrl */
+ 0x05057404, /* EmcXm2VttGenPadCtrl */
+ 0x54000007, /* EmcXm2VttGenPadCtrl2 */
+ 0x080001e8, /* EmcXm2QUsePadCtrl */
+ 0x08000021, /* EmcXm2DqsPadCtrl3 */
+ 0x00000802, /* EmcCttTermCtrl */
+ 0x00020000, /* EmcZcalInterval */
+ 0x00000040, /* EmcZcalWaitCnt */
+ 0x016b000c, /* EmcMrsWaitCnt */
+ 0x001fffff, /* EmcAutoCalInterval */
+ 0x00000000, /* EmcCtt */
+ 0x00000000, /* EmcCttDuration */
+ 0x800020ae, /* EmcDynSelfRefControl */
+ 0x00000008, /* McEmemArbCfg */
+ 0x80000060, /* McEmemArbOutstandingReq */
+ 0x00000002, /* McEmemArbTimingRcd */
+ 0x00000003, /* McEmemArbTimingRp */
+ 0x0000000d, /* McEmemArbTimingRc */
+ 0x00000008, /* McEmemArbTimingRas */
+ 0x0000000f, /* McEmemArbTimingFaw */
+ 0x00000002, /* McEmemArbTimingRrd */
+ 0x00000002, /* McEmemArbTimingRap2Pre */
+ 0x00000009, /* McEmemArbTimingWap2Pre */
+ 0x00000002, /* McEmemArbTimingR2R */
+ 0x00000002, /* McEmemArbTimingW2W */
+ 0x00000005, /* McEmemArbTimingR2W */
+ 0x00000006, /* McEmemArbTimingW2R */
+ 0x06030202, /* McEmemArbDaTurns */
+ 0x000f080d, /* McEmemArbDaCovers */
+ 0x70c8180e, /* McEmemArbMisc0 */
+ 0x001f0000, /* McEmemArbRing1Throttle */
+ 0xe8000000, /* EmcFbioSpare */
+ 0xff00ff88, /* EmcCfgRsv */
+ },
+ 0x00000040, /* EmcZcalWaitCnt */
+ 0x00020000, /* EmcZcalInterval */
+ 0x00000000, /* EmcCfg bit 27PERIODIC_QRST */
+ 0x80000931, /* EmcMrs */
+ 0x80100002, /* EmcEmrs */
+ 0x00000000, /* EmcMrw1 */
+ 0x00000000, /* EmcCfg bit 28 DYN_SELF_REF */
+ },
+#if 0
+ {
+ 0x32, /* Rev 3.2 */
+ 667000, /* SDRAM frequency [kHz] */
+ {
+ 0x0000001f, /* EmcRc */
+ 0x000000ac, /* EmcRfc */
+ 0x00000016, /* EmcRas */
+ 0x00000007, /* EmcRp */
+ 0x00000006, /* EmcR2w */
+ 0x0000000b, /* EmcW2r */
+ 0x00000003, /* EmcR2p */
+ 0x00000010, /* EmcW2p */
+ 0x00000007, /* EmcRdRcd */
+ 0x00000007, /* EmcWrRcd */
+ 0x00000003, /* EmcRrd */
+ 0x00000001, /* EmcRext */
+ 0x00000000, /* EmcWext */
+ 0x00000006, /* EmcWdv */
+ 0x00000009, /* EmcQUse */
+ 0x00000007, /* EmcQRst */
+ 0x0000000a, /* EmcQSafe */
+ 0x0000000f, /* EmcRdv */
+ 0x00001410, /* EmcRefresh */
+ 0x00000000, /* EmcBurstRefreshNum */
+ 0x00000504, /* EmcPreRefreshReqCnt */
+ 0x0000000e, /* EmcPdEx2Wr */
+ 0x0000000e, /* EmcPdEx2Rd */
+ 0x00000007, /* EmcPChg2Pden */
+ 0x00000000, /* EmcAct2Pden */
+ 0x0000000c, /* EmcAr2Pden */
+ 0x00000015, /* EmcRw2Pden */
+ 0x000000b4, /* EmcTxsr */
+ 0x00000200, /* EmcTxsrDll */
+ 0x00000004, /* EmcTcke */
+ 0x0000001e, /* EmcTfaw */
+ 0x00000000, /* EmcTrpab */
+ 0x00000006, /* EmcTClkStable */
+ 0x00000007, /* EmcTClkStop */
+ 0x00001450, /* EmcTRefBw */
+ 0x0000000a, /* EmcQUseExtra */
+ 0x00000006, /* EmcFbioCfg6 */
+ 0x00000000, /* EmcOdtWrite */
+ 0x00000000, /* EmcOdtRead */
+ 0x00005088, /* EmcFbioCfg5 */
+ 0xf00b0191, /* EmcCfgDigDll */
+ 0x00008000, /* EmcCfgDigDllPeriod */
+ 0x0000000a, /* EmcDllXformDqs0 */
+ 0x0000000a, /* EmcDllXformDqs1 */
+ 0x0000000a, /* EmcDllXformDqs2 */
+ 0x0000000a, /* EmcDllXformDqs3 */
+ 0x0000000a, /* EmcDllXformDqs4 */
+ 0x0000000a, /* EmcDllXformDqs5 */
+ 0x0000000a, /* EmcDllXformDqs6 */
+ 0x0000000a, /* EmcDllXformDqs7 */
+ 0x00000000, /* EmcDllXformQUse0 */
+ 0x00000000, /* EmcDllXformQUse1 */
+ 0x00000000, /* EmcDllXformQUse2 */
+ 0x00000000, /* EmcDllXformQUse3 */
+ 0x00000000, /* EmcDllXformQUse4 */
+ 0x00000000, /* EmcDllXformQUse5 */
+ 0x00000000, /* EmcDllXformQUse6 */
+ 0x00000000, /* EmcDllXformQUse7 */
+ 0x00000000, /* EmcDliTrimTxDqs0 */
+ 0x00000000, /* EmcDliTrimTxDqs1 */
+ 0x00000000, /* EmcDliTrimTxDqs2 */
+ 0x00000000, /* EmcDliTrimTxDqs3 */
+ 0x00000000, /* EmcDliTrimTxDqs4 */
+ 0x00000000, /* EmcDliTrimTxDqs5 */
+ 0x00000000, /* EmcDliTrimTxDqs6 */
+ 0x00000000, /* EmcDliTrimTxDqs7 */
+ 0x0000000a, /* EmcDllXformDq0 */
+ 0x0000000a, /* EmcDllXformDq1 */
+ 0x0000000a, /* EmcDllXformDq2 */
+ 0x0000000a, /* EmcDllXformDq3 */
+ 0x000002a0, /* EmcXm2CmdPadCtrl */
+ 0x0800013d, /* EmcXm2DqsPadCtrl2 */
+ 0x22220000, /* EmcXm2DqPadCtrl2 */
+ 0x77fff884, /* EmcXm2ClkPadCtrl */
+ 0x01f1f508, /* EmcXm2CompPadCtrl */
+ 0x07077404, /* EmcXm2VttGenPadCtrl */
+ 0x54000000, /* EmcXm2VttGenPadCtrl2 */
+ 0x080001e8, /* EmcXm2QUsePadCtrl */
+ 0x08000021, /* EmcXm2DqsPadCtrl3 */
+ 0x00000802, /* EmcCttTermCtrl */
+ 0x00020000, /* EmcZcalInterval */
+ 0x00000040, /* EmcZcalWaitCnt */
+ 0x0196000c, /* EmcMrsWaitCnt */
+ 0x001fffff, /* EmcAutoCalInterval */
+ 0x00000000, /* EmcCtt */
+ 0x00000000, /* EmcCttDuration */
+ 0x800028a0, /* EmcDynSelfRefControl */
+ 0x0000000a, /* McEmemArbCfg */
+ 0x80000078, /* McEmemArbOutstandingReq */
+ 0x00000003, /* McEmemArbTimingRcd */
+ 0x00000004, /* McEmemArbTimingRp */
+ 0x00000010, /* McEmemArbTimingRc */
+ 0x0000000a, /* McEmemArbTimingRas */
+ 0x0000000f, /* McEmemArbTimingFaw */
+ 0x00000002, /* McEmemArbTimingRrd */
+ 0x00000003, /* McEmemArbTimingRap2Pre */
+ 0x0000000b, /* McEmemArbTimingWap2Pre */
+ 0x00000002, /* McEmemArbTimingR2R */
+ 0x00000002, /* McEmemArbTimingW2W */
+ 0x00000004, /* McEmemArbTimingR2W */
+ 0x00000007, /* McEmemArbTimingW2R */
+ 0x07040202, /* McEmemArbDaTurns */
+ 0x00130b10, /* McEmemArbDaCovers */
+ 0x70ea1e11, /* McEmemArbMisc0 */
+ 0x001f0000, /* McEmemArbRing1Throttle */
+ 0xe8000000, /* EmcFbioSpare */
+ 0xff00ff49, /* EmcCfgRsv */
+ },
+ 0x00000040, /* EmcZcalWaitCnt */
+ 0x00020000, /* EmcZcalInterval */
+ 0x00000001, /* EmcCfg bit 27PERIODIC_QRST */
+ 0x80000b51, /* EmcMrs */
+ 0x80100002, /* EmcEmrs */
+ 0x00000000, /* EmcMrw1 */
+ 0x00000000, /* EmcCfg bit 28 DYN_SELF_REF */
+ },
+//750
+#endif
+};
+
+int apalis_t30_emc_init(void)
+{
+#if 1
+ tegra_init_emc(apalis_t30_emc_tables_mt41k256m16re_15e,
+ ARRAY_SIZE(apalis_t30_emc_tables_mt41k256m16re_15e));
+#else
+ tegra_init_emc(cardhu_emc_tables_h5tc2g_a2,
+ ARRAY_SIZE(cardhu_emc_tables_h5tc2g_a2));
+#endif
+ return 0;
+}
diff --git a/arch/arm/mach-tegra/board-apalis_t30-panel.c b/arch/arm/mach-tegra/board-apalis_t30-panel.c
new file mode 100644
index 000000000000..d8bfbec38706
--- /dev/null
+++ b/arch/arm/mach-tegra/board-apalis_t30-panel.c
@@ -0,0 +1,811 @@
+/*
+ * arch/arm/mach-tegra/board-apalis_t30-panel.c
+ *
+ * Copyright (c) 2013, Toradex, Inc.
+ *
+ * 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.
+ */
+
+#include <asm/atomic.h>
+#include <asm/mach-types.h>
+
+#include <linux/delay.h>
+#include <linux/earlysuspend.h>
+#include <linux/gpio.h>
+#include <linux/ion.h>
+#include <linux/nvhost.h>
+#include <linux/nvmap.h>
+#include <linux/platform_device.h>
+#include <linux/pwm_backlight.h>
+#include <linux/regulator/consumer.h>
+#include <linux/resource.h>
+#include <linux/tegra_ion.h>
+
+#include <mach/dc.h>
+#include <mach/fb.h>
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+#include <mach/smmu.h>
+
+#include "board.h"
+#include "board-apalis_t30.h"
+#include "devices.h"
+#include "gpio-names.h"
+#include "tegra3_host1x_devices.h"
+
+#define apalis_t30_bl_enb TEGRA_GPIO_PV2 /* BL_ON */
+#define apalis_t30_hdmi_hpd TEGRA_GPIO_PN7 /* HDMI_INT_N */
+
+static struct regulator *apalis_t30_hdmi_pll = NULL;
+static struct regulator *apalis_t30_hdmi_reg = NULL;
+static struct regulator *apalis_t30_hdmi_vddio = NULL;
+
+static int apalis_t30_backlight_init(struct device *dev) {
+ int ret;
+
+ ret = gpio_request(apalis_t30_bl_enb, "BL_ON");
+ if (ret < 0)
+ return ret;
+
+ ret = gpio_direction_output(apalis_t30_bl_enb, 1);
+ if (ret < 0)
+ gpio_free(apalis_t30_bl_enb);
+
+ return ret;
+};
+
+static void apalis_t30_backlight_exit(struct device *dev) {
+ gpio_set_value(apalis_t30_bl_enb, 0);
+ gpio_free(apalis_t30_bl_enb);
+}
+
+static int apalis_t30_backlight_notify(struct device *dev, int brightness)
+{
+ struct platform_pwm_backlight_data *pdata = dev->platform_data;
+
+ gpio_set_value(apalis_t30_bl_enb, !!brightness);
+
+ /* Unified TFT interface displays (e.g. EDT ET070080DH6) LEDCTRL pin
+ with inverted behaviour (e.g. 0V brightest vs. 3.3V darkest)
+ Note: brightness polarity display model specific */
+ if (brightness) return pdata->max_brightness - brightness;
+ else return brightness;
+}
+
+static int apalis_t30_disp1_check_fb(struct device *dev, struct fb_info *info);
+
+static struct platform_pwm_backlight_data apalis_t30_backlight_data = {
+ .pwm_id = 0,
+ .max_brightness = 255,
+ .dft_brightness = 127,
+ .pwm_period_ns = 1000000, /* 1 kHz */
+ .init = apalis_t30_backlight_init,
+ .exit = apalis_t30_backlight_exit,
+ .notify = apalis_t30_backlight_notify,
+ /* Only toggle backlight on fb blank notifications for disp1 */
+ .check_fb = apalis_t30_disp1_check_fb,
+};
+
+static struct platform_device apalis_t30_backlight_device = {
+ .name = "pwm-backlight",
+ .id = -1,
+ .dev = {
+ .platform_data = &apalis_t30_backlight_data,
+ },
+};
+
+static int apalis_t30_panel_enable(void)
+{
+ return 0;
+}
+
+static int apalis_t30_panel_disable(void)
+{
+ return 0;
+}
+
+#ifdef CONFIG_TEGRA_DC
+static int apalis_t30_hdmi_vddio_enable(void)
+{
+ int ret;
+ if (!apalis_t30_hdmi_vddio) {
+ apalis_t30_hdmi_vddio = regulator_get(NULL, "vdd_hdmi_con");
+ if (IS_ERR_OR_NULL(apalis_t30_hdmi_vddio)) {
+ ret = PTR_ERR(apalis_t30_hdmi_vddio);
+ pr_err("hdmi: couldn't get regulator vdd_hdmi_con\n");
+ apalis_t30_hdmi_vddio = NULL;
+ return ret;
+ }
+ }
+ ret = regulator_enable(apalis_t30_hdmi_vddio);
+ if (ret < 0) {
+ pr_err("hdmi: couldn't enable regulator vdd_hdmi_con\n");
+ regulator_put(apalis_t30_hdmi_vddio);
+ apalis_t30_hdmi_vddio = NULL;
+ return ret;
+ }
+ return ret;
+}
+
+static int apalis_t30_hdmi_vddio_disable(void)
+{
+ if (apalis_t30_hdmi_vddio) {
+ regulator_disable(apalis_t30_hdmi_vddio);
+ regulator_put(apalis_t30_hdmi_vddio);
+ apalis_t30_hdmi_vddio = NULL;
+ }
+ return 0;
+}
+
+static int apalis_t30_hdmi_enable(void)
+{
+ int ret;
+ if (!apalis_t30_hdmi_reg) {
+ apalis_t30_hdmi_reg = regulator_get(NULL, "avdd_hdmi");
+ if (IS_ERR_OR_NULL(apalis_t30_hdmi_reg)) {
+ pr_err("hdmi: couldn't get regulator avdd_hdmi\n");
+ apalis_t30_hdmi_reg = NULL;
+ return PTR_ERR(apalis_t30_hdmi_reg);
+ }
+ }
+ ret = regulator_enable(apalis_t30_hdmi_reg);
+ if (ret < 0) {
+ pr_err("hdmi: couldn't enable regulator avdd_hdmi\n");
+ return ret;
+ }
+ if (!apalis_t30_hdmi_pll) {
+ apalis_t30_hdmi_pll = regulator_get(NULL, "avdd_hdmi_pll");
+ if (IS_ERR_OR_NULL(apalis_t30_hdmi_pll)) {
+ pr_err("hdmi: couldn't get regulator avdd_hdmi_pll\n");
+ apalis_t30_hdmi_pll = NULL;
+ regulator_put(apalis_t30_hdmi_reg);
+ apalis_t30_hdmi_reg = NULL;
+ return PTR_ERR(apalis_t30_hdmi_pll);
+ }
+ }
+ ret = regulator_enable(apalis_t30_hdmi_pll);
+ if (ret < 0) {
+ pr_err("hdmi: couldn't enable regulator avdd_hdmi_pll\n");
+ return ret;
+ }
+ return 0;
+}
+
+static int apalis_t30_hdmi_disable(void)
+{
+ regulator_disable(apalis_t30_hdmi_reg);
+ regulator_put(apalis_t30_hdmi_reg);
+ apalis_t30_hdmi_reg = NULL;
+
+ regulator_disable(apalis_t30_hdmi_pll);
+ regulator_put(apalis_t30_hdmi_pll);
+ apalis_t30_hdmi_pll = NULL;
+ return 0;
+}
+static struct resource apalis_t30_disp1_resources[] = {
+ {
+ .name = "irq",
+ .start = INT_DISPLAY_GENERAL,
+ .end = INT_DISPLAY_GENERAL,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "regs",
+ .start = TEGRA_DISPLAY_BASE,
+ .end = TEGRA_DISPLAY_BASE + TEGRA_DISPLAY_SIZE-1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "fbmem",
+ .start = 0, /* Filled in by apalis_t30_panel_init() */
+ .end = 0, /* Filled in by apalis_t30_panel_init() */
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct resource apalis_t30_disp2_resources[] = {
+ {
+ .name = "irq",
+ .start = INT_DISPLAY_B_GENERAL,
+ .end = INT_DISPLAY_B_GENERAL,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "regs",
+ .start = TEGRA_DISPLAY2_BASE,
+ .end = TEGRA_DISPLAY2_BASE + TEGRA_DISPLAY2_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "fbmem",
+ .flags = IORESOURCE_MEM,
+ .start = 0,
+ .end = 0,
+ },
+ {
+ .name = "hdmi_regs",
+ .start = TEGRA_HDMI_BASE,
+ .end = TEGRA_HDMI_BASE + TEGRA_HDMI_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+#endif /* CONFIG_TEGRA_DC */
+
+static struct tegra_dc_mode apalis_t30_panel_modes[] = {
+#ifdef TEGRA_FB_VGA
+ {
+ /* 640x480p 60hz: EIA/CEA-861-B Format 1 */
+ .pclk = 25175000, /* pixclock */
+ .h_ref_to_sync = 8,
+ .v_ref_to_sync = 2,
+ .h_sync_width = 96, /* hsync_len */
+ .v_sync_width = 2, /* vsync_len */
+ .h_back_porch = 48, /* left_margin */
+ .v_back_porch = 33, /* upper_margin */
+ .h_active = 640,
+ .v_active = 480,
+ .h_front_porch = 16, /* right_margin */
+ .v_front_porch = 10, /* lower_margin */
+ },
+#else /* TEGRA_FB_VGA */
+ {
+ /* 800x480@60 (e.g. EDT ET070080DH6) */
+ .pclk = 32460000,
+ .h_ref_to_sync = 1,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 64,
+ .v_sync_width = 3,
+ .h_back_porch = 128,
+ .v_back_porch = 22,
+ .h_active = 800,
+ .v_active = 480,
+ .h_front_porch = 64,
+ .v_front_porch = 20,
+ },
+ {
+ /* 800x600@60 */
+ .pclk = 39272727,
+ .h_sync_width = 80,
+ .v_sync_width = 2,
+ .h_back_porch = 160,
+ .v_back_porch = 21,
+ .h_active = 800,
+ .v_active = 600,
+ .h_front_porch = 16,
+ .v_front_porch = 1,
+ },
+ {
+ /* TouchRevolution Fusion 10 aka Chunghwa Picture Tubes
+ CLAA101NC05 10.1 inch 1024x600 single channel LVDS panel */
+ .pclk = 48000000,
+ .h_sync_width = 5,
+ .v_sync_width = 5,
+ .h_back_porch = 104,
+ .v_back_porch = 24,
+ .h_active = 1024,
+ .v_active = 600,
+ .h_front_porch = 43,
+ .v_front_porch = 20,
+ },
+ {
+ /* 1024x768@60 */
+ .pclk = 78800000,
+ .h_sync_width = 96,
+ .v_sync_width = 3,
+ .h_back_porch = 176,
+ .v_back_porch = 28,
+ .h_active = 1024,
+ .v_active = 768,
+ .h_front_porch = 16,
+ .v_front_porch = 1,
+ },
+ {
+ /* 1024x768@75 */
+ .pclk = 82000000,
+ .h_sync_width = 104,
+ .v_sync_width = 4,
+ .h_back_porch = 168,
+ .v_back_porch = 34,
+ .h_active = 1024,
+ .v_active = 768,
+ .h_front_porch = 64,
+ .v_front_porch = 3,
+ },
+ {
+ /* 1280x720@60 */
+ .pclk = 74250000,
+ .h_ref_to_sync = 1,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 40,
+ .v_sync_width = 5,
+ .h_back_porch = 220,
+ .v_back_porch = 20,
+ .h_active = 1280,
+ .v_active = 720,
+ .h_front_porch = 110,
+ .v_front_porch = 5,
+//high active sync polarities
+ },
+ {
+ /* 1280x1024@60 */
+ .pclk = 108000000,
+// .h_ref_to_sync = 1,
+// .v_ref_to_sync = 1,
+ .h_sync_width = 144,
+ .v_sync_width = 3,
+ .h_back_porch = 248,
+ .v_back_porch = 38,
+ .h_active = 1280,
+ .v_active = 1024,
+ .h_front_porch = 16,
+ .v_front_porch = 1,
+//high active sync polarities
+ },
+ {
+ /* 1366x768@60 */
+ .pclk = 72072000,
+ .h_ref_to_sync = 11,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 58,
+ .v_sync_width = 4,
+ .h_back_porch = 58,
+ .v_back_porch = 4,
+ .h_active = 1366,
+ .v_active = 768,
+ .h_front_porch = 58,
+ .v_front_porch = 4,
+ },
+ {
+ /* 1600x1200@60 */
+ .pclk = 162000000,
+// .h_ref_to_sync = 1,
+// .v_ref_to_sync = 1,
+ .h_sync_width = 192,
+ .v_sync_width = 3,
+ .h_back_porch = 304,
+ .v_back_porch = 46,
+ .h_active = 1600,
+ .v_active = 1200,
+ .h_front_porch = 64,
+ .v_front_porch = 1,
+//high active sync polarities
+ },
+ {
+ .pclk = 119000000,
+ .h_ref_to_sync = 1,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 32,
+ .v_sync_width = 6,
+ .h_back_porch = 80,
+ .v_back_porch = 21,
+ .h_active = 1680,
+ .v_active = 1050,
+ .h_front_porch = 48,
+ .v_front_porch = 3,
+ },
+ {
+ /* 1680x1050@60 */
+ .pclk = 147140000,
+// .h_ref_to_sync = 1,
+// .v_ref_to_sync = 1,
+ .h_sync_width = 184,
+ .v_sync_width = 3,
+ .h_back_porch = 288,
+ .v_back_porch = 33,
+ .h_active = 1680,
+ .v_active = 1050,
+ .h_front_porch = 104,
+ .v_front_porch = 1,
+//high active vertical sync polarity
+ },
+ {
+ /* LG LP156WF1 15.6 inch full HD dual channel LVDS panel */
+ .pclk = 138500000,
+ .h_sync_width = 32,
+ .v_sync_width = 5,
+ .h_back_porch = 80,
+ .v_back_porch = 46,
+ .h_active = 1920,
+ .v_active = 1080,
+ .h_front_porch = 48,
+ .v_front_porch = 6,
+ //low active sync polarities, high pixel clock polarity
+ },
+ {
+ /* 1920x1080p 59.94/60hz EIA/CEA-861-B Format 16 */
+ .pclk = 148500000,
+ .h_ref_to_sync = 11,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 44,
+ .v_sync_width = 5,
+ .h_back_porch = 148,
+ .v_back_porch = 36,
+ .h_active = 1920,
+ .v_active = 1080,
+ .h_front_porch = 88,
+ .v_front_porch = 4,
+//high active sync polarities
+ },
+ {
+ .pclk = 154000000,
+ .h_ref_to_sync = 11,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 32,
+ .v_sync_width = 6,
+ .h_back_porch = 80,
+ .v_back_porch = 26,
+ .h_active = 1920,
+ .v_active = 1200,
+ .h_front_porch = 48,
+ .v_front_porch = 3,
+ },
+
+ /* portrait modes */
+
+ {
+ .pclk = 18000000,
+ .h_ref_to_sync = 8,
+ .v_ref_to_sync = 2,
+ .h_sync_width = 4,
+ .v_sync_width = 1,
+ .h_back_porch = 20,
+ .v_back_porch = 7,
+ .h_active = 480,
+ .v_active = 640,
+ .h_front_porch = 8,
+ .v_front_porch = 8,
+ },
+ {
+ .pclk = 10000000,
+ .h_ref_to_sync = 4,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 16,
+ .v_sync_width = 1,
+ .h_back_porch = 32,
+ .v_back_porch = 1,
+ .h_active = 540,
+ .v_active = 960,
+ .h_front_porch = 32,
+ .v_front_porch = 2,
+ },
+ {
+ .pclk = 61417000,
+ .h_ref_to_sync = 2,
+ .v_ref_to_sync = 2,
+ .h_sync_width = 4,
+ .v_sync_width = 4,
+ .h_back_porch = 100,
+ .v_back_porch = 14,
+ .h_active = 720,
+ .v_active = 1280,
+ .h_front_porch = 4,
+ .v_front_porch = 4,
+ },
+#endif /* TEGRA_FB_VGA */
+};
+
+#ifdef CONFIG_TEGRA_DC
+static struct tegra_fb_data apalis_t30_fb_data = {
+ .win = 0,
+#ifdef TEGRA_FB_VGA
+ .xres = 640,
+ .yres = 480,
+#else /* TEGRA_FB_VGA */
+ .xres = 800,
+ .yres = 480,
+#endif /* TEGRA_FB_VGA */
+ .bits_per_pixel = 16,
+ .flags = TEGRA_FB_FLIP_ON_PROBE,
+};
+
+static struct tegra_fb_data apalis_t30_hdmi_fb_data = {
+ .win = 0,
+ .xres = 640,
+ .yres = 480,
+ .bits_per_pixel = 16,
+ .flags = TEGRA_FB_FLIP_ON_PROBE,
+};
+
+static struct tegra_dc_out_pin apalis_t30_dc_out_pins[] = {
+ {
+ .name = TEGRA_DC_OUT_PIN_H_SYNC,
+ .pol = TEGRA_DC_OUT_PIN_POL_LOW,
+ },
+ {
+ .name = TEGRA_DC_OUT_PIN_V_SYNC,
+ .pol = TEGRA_DC_OUT_PIN_POL_LOW,
+ },
+ {
+ .name = TEGRA_DC_OUT_PIN_PIXEL_CLOCK,
+ .pol = TEGRA_DC_OUT_PIN_POL_LOW,
+ },
+};
+
+static struct tegra_dc_out apalis_t30_disp1_out = {
+ .type = TEGRA_DC_OUT_RGB,
+ .parent_clk = "pll_d_out0",
+ .parent_clk_backup = "pll_d2_out0",
+
+ .align = TEGRA_DC_ALIGN_MSB,
+ .order = TEGRA_DC_ORDER_RED_BLUE,
+ .depth = 24,
+ .dither = TEGRA_DC_ORDERED_DITHER,
+
+ .modes = apalis_t30_panel_modes,
+ .n_modes = ARRAY_SIZE(apalis_t30_panel_modes),
+
+ .out_pins = apalis_t30_dc_out_pins,
+ .n_out_pins = ARRAY_SIZE(apalis_t30_dc_out_pins),
+
+ .enable = apalis_t30_panel_enable,
+ .disable = apalis_t30_panel_disable,
+};
+
+static struct tegra_dc_out apalis_t30_disp2_out = {
+ .type = TEGRA_DC_OUT_HDMI,
+ .flags = TEGRA_DC_OUT_HOTPLUG_HIGH,
+ .parent_clk = "pll_d2_out0",
+
+ .dcc_bus = 3,
+ .hotplug_gpio = apalis_t30_hdmi_hpd,
+
+ .max_pixclock = KHZ2PICOS(148500),
+
+ .align = TEGRA_DC_ALIGN_MSB,
+ .order = TEGRA_DC_ORDER_RED_BLUE,
+
+ .enable = apalis_t30_hdmi_enable,
+ .disable = apalis_t30_hdmi_disable,
+
+ .postsuspend = apalis_t30_hdmi_vddio_disable,
+ .hotplug_init = apalis_t30_hdmi_vddio_enable,
+};
+
+static struct tegra_dc_platform_data apalis_t30_disp1_pdata = {
+ .flags = TEGRA_DC_FLAG_ENABLED,
+ .default_out = &apalis_t30_disp1_out,
+ .emc_clk_rate = 300000000,
+ .fb = &apalis_t30_fb_data,
+};
+
+static struct tegra_dc_platform_data apalis_t30_disp2_pdata = {
+ .flags = TEGRA_DC_FLAG_ENABLED,
+ .default_out = &apalis_t30_disp2_out,
+ .fb = &apalis_t30_hdmi_fb_data,
+ .emc_clk_rate = 300000000,
+};
+
+static struct nvhost_device apalis_t30_disp1_device = {
+ .name = "tegradc",
+ .id = 0,
+ .resource = apalis_t30_disp1_resources,
+ .num_resources = ARRAY_SIZE(apalis_t30_disp1_resources),
+ .dev = {
+ .platform_data = &apalis_t30_disp1_pdata,
+ },
+};
+
+static int apalis_t30_disp1_check_fb(struct device *dev, struct fb_info *info)
+{
+ return info->device == &apalis_t30_disp1_device.dev;
+}
+
+static struct nvhost_device apalis_t30_disp2_device = {
+ .name = "tegradc",
+ .id = 1,
+ .resource = apalis_t30_disp2_resources,
+ .num_resources = ARRAY_SIZE(apalis_t30_disp2_resources),
+ .dev = {
+ .platform_data = &apalis_t30_disp2_pdata,
+ },
+};
+#else /* CONFIG_TEGRA_DC */
+static int apalis_t30_disp1_check_fb(struct device *dev, struct fb_info *info)
+{
+ return 0;
+}
+#endif /* CONFIG_TEGRA_DC */
+
+#if defined(CONFIG_TEGRA_NVMAP)
+static struct nvmap_platform_carveout apalis_t30_carveouts[] = {
+ [0] = NVMAP_HEAP_CARVEOUT_IRAM_INIT,
+ [1] = {
+ .name = "generic-0",
+ .usage_mask = NVMAP_HEAP_CARVEOUT_GENERIC,
+ .base = 0, /* Filled in by apalis_t30_panel_init() */
+ .size = 0, /* Filled in by apalis_t30_panel_init() */
+ .buddy_size = SZ_32K,
+ },
+};
+
+static struct nvmap_platform_data apalis_t30_nvmap_data = {
+ .carveouts = apalis_t30_carveouts,
+ .nr_carveouts = ARRAY_SIZE(apalis_t30_carveouts),
+};
+
+static struct platform_device apalis_t30_nvmap_device = {
+ .name = "tegra-nvmap",
+ .id = -1,
+ .dev = {
+ .platform_data = &apalis_t30_nvmap_data,
+ },
+};
+#endif /* CONFIG_TEGRA_NVMAP */
+
+#if defined(CONFIG_ION_TEGRA)
+static struct platform_device tegra_iommu_device = {
+ .name = "tegra_iommu_device",
+ .id = -1,
+ .dev = {
+ .platform_data = (void *)((1 << HWGRP_COUNT) - 1),
+ },
+};
+
+static struct ion_platform_data tegra_ion_data = {
+ .nr = 4,
+ .heaps = {
+ {
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .id = TEGRA_ION_HEAP_CARVEOUT,
+ .name = "carveout",
+ .base = 0,
+ .size = 0,
+ },
+ {
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .id = TEGRA_ION_HEAP_IRAM,
+ .name = "iram",
+ .base = TEGRA_IRAM_BASE + TEGRA_RESET_HANDLER_SIZE,
+ .size = TEGRA_IRAM_SIZE - TEGRA_RESET_HANDLER_SIZE,
+ },
+ {
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .id = TEGRA_ION_HEAP_VPR,
+ .name = "vpr",
+ .base = 0,
+ .size = 0,
+ },
+ {
+ .type = ION_HEAP_TYPE_IOMMU,
+ .id = TEGRA_ION_HEAP_IOMMU,
+ .name = "iommu",
+ .base = TEGRA_SMMU_BASE,
+ .size = TEGRA_SMMU_SIZE,
+ .priv = &tegra_iommu_device.dev,
+ },
+ },
+};
+
+static struct platform_device tegra_ion_device = {
+ .name = "ion-tegra",
+ .id = -1,
+ .dev = {
+ .platform_data = &tegra_ion_data,
+ },
+};
+#endif /* CONFIG_ION_TEGRA */
+
+static struct platform_device *apalis_t30_gfx_devices[] __initdata = {
+#if defined(CONFIG_TEGRA_NVMAP)
+ &apalis_t30_nvmap_device,
+#endif
+#if defined(CONFIG_ION_TEGRA)
+ &tegra_ion_device,
+#endif
+ &tegra_pwfm0_device,
+ &apalis_t30_backlight_device,
+};
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+/* put early_suspend/late_resume handlers here for the display in order
+ * to keep the code out of the display driver, keeping it closer to upstream
+ */
+struct early_suspend apalis_t30_panel_early_suspender;
+
+static void apalis_t30_panel_early_suspend(struct early_suspend *h)
+{
+ /* power down LCD, add use a black screen for HDMI */
+ if (num_registered_fb > 0)
+ fb_blank(registered_fb[0], FB_BLANK_POWERDOWN);
+ if (num_registered_fb > 1)
+ fb_blank(registered_fb[1], FB_BLANK_NORMAL);
+}
+
+static void apalis_t30_panel_late_resume(struct early_suspend *h)
+{
+ unsigned i;
+ for (i = 0; i < num_registered_fb; i++)
+ fb_blank(registered_fb[i], FB_BLANK_UNBLANK);
+}
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+int __init apalis_t30_panel_init(void)
+{
+ int err = 0;
+ struct resource *res;
+ void __iomem *to_io;
+
+ /* enable hdmi hotplug gpio for hotplug detection */
+ gpio_request(apalis_t30_hdmi_hpd, "hdmi_hpd");
+ gpio_direction_input(apalis_t30_hdmi_hpd);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ apalis_t30_panel_early_suspender.suspend = apalis_t30_panel_early_suspend;
+ apalis_t30_panel_early_suspender.resume = apalis_t30_panel_late_resume;
+ apalis_t30_panel_early_suspender.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
+ register_early_suspend(&apalis_t30_panel_early_suspender);
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+#ifdef CONFIG_TEGRA_NVMAP
+ apalis_t30_carveouts[1].base = tegra_carveout_start;
+ apalis_t30_carveouts[1].size = tegra_carveout_size;
+#endif /* CONFIG_TEGRA_NVMAP */
+
+#ifdef CONFIG_ION_TEGRA
+ tegra_ion_data.heaps[0].base = tegra_carveout_start;
+ tegra_ion_data.heaps[0].size = tegra_carveout_size;
+#endif /* CONFIG_ION_TEGRA */
+
+#ifdef CONFIG_TEGRA_GRHOST
+ err = tegra3_register_host1x_devices();
+ if (err)
+ return err;
+#endif /* CONFIG_TEGRA_GRHOST */
+
+ err = platform_add_devices(apalis_t30_gfx_devices,
+ ARRAY_SIZE(apalis_t30_gfx_devices));
+
+#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC)
+ res = nvhost_get_resource_byname(&apalis_t30_disp1_device,
+ IORESOURCE_MEM, "fbmem");
+ res->start = tegra_fb_start;
+ res->end = tegra_fb_start + tegra_fb_size - 1;
+
+ res = nvhost_get_resource_byname(&apalis_t30_disp2_device,
+ IORESOURCE_MEM, "fbmem");
+ res->start = tegra_fb2_start;
+ res->end = tegra_fb2_start + tegra_fb2_size - 1;
+#endif /* CONFIG_TEGRA_GRHOST & CONFIG_TEGRA_DC */
+
+ /* Make sure LVDS framebuffer is cleared. */
+ to_io = ioremap(tegra_fb_start, tegra_fb_size);
+ if (to_io) {
+ memset(to_io, 0, tegra_fb_size);
+ iounmap(to_io);
+ } else pr_err("%s: Failed to map LVDS framebuffer\n", __func__);
+
+ /* Make sure HDMI framebuffer is cleared.
+ Note: this seems to fix a tegradc.1 initialisation race in case of
+ framebuffer console as well. */
+ to_io = ioremap(tegra_fb2_start, tegra_fb2_size);
+ if (to_io) {
+ memset(to_io, 0, tegra_fb2_size);
+ iounmap(to_io);
+ } else pr_err("%s: Failed to map HDMI framebuffer\n", __func__);
+
+#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC)
+ if (!err)
+ err = nvhost_device_register(&apalis_t30_disp1_device);
+
+ if (!err)
+ err = nvhost_device_register(&apalis_t30_disp2_device);
+#endif /* CONFIG_TEGRA_GRHOST & CONFIG_TEGRA_DC */
+
+#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_NVAVP)
+ if (!err)
+ err = nvhost_device_register(&nvavp_device);
+#endif
+ return err;
+}
diff --git a/arch/arm/mach-tegra/board-apalis_t30-pinmux.c b/arch/arm/mach-tegra/board-apalis_t30-pinmux.c
new file mode 100644
index 000000000000..a04a15587129
--- /dev/null
+++ b/arch/arm/mach-tegra/board-apalis_t30-pinmux.c
@@ -0,0 +1,487 @@
+/*
+ * arch/arm/mach-tegra/board-apalis_t30-pinmux.c
+ *
+ * Copyright (C) 2013 Toradex, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <mach/pinmux.h>
+
+#include "board-apalis_t30.h"
+#include "board.h"
+#include "gpio-names.h"
+
+#define DEFAULT_DRIVE(_name) \
+ { \
+ .pingroup = TEGRA_DRIVE_PINGROUP_##_name, \
+ .hsm = TEGRA_HSM_DISABLE, \
+ .schmitt = TEGRA_SCHMITT_ENABLE, \
+ .drive = TEGRA_DRIVE_DIV_1, \
+ .pull_down = TEGRA_PULL_31, \
+ .pull_up = TEGRA_PULL_31, \
+ .slew_rising = TEGRA_SLEW_SLOWEST, \
+ .slew_falling = TEGRA_SLEW_SLOWEST, \
+ }
+
+/* Setting the drive strength of pins
+ * hsm: Enable High speed mode (ENABLE/DISABLE)
+ * Schimit: Enable/disable schimit (ENABLE/DISABLE)
+ * drive: low power mode (DIV_1, DIV_2, DIV_4, DIV_8)
+ * pulldn_drive - drive down (falling edge) - Driver Output Pull-Down drive
+ * strength code. Value from 0 to 31.
+ * pullup_drive - drive up (rising edge) - Driver Output Pull-Up drive
+ * strength code. Value from 0 to 31.
+ * pulldn_slew - Driver Output Pull-Up slew control code - 2bit code
+ * code 11 is least slewing of signal. code 00 is highest
+ * slewing of the signal.
+ * Value - FASTEST, FAST, SLOW, SLOWEST
+ * pullup_slew - Driver Output Pull-Down slew control code -
+ * code 11 is least slewing of signal. code 00 is highest
+ * slewing of the signal.
+ * Value - FASTEST, FAST, SLOW, SLOWEST
+ */
+#define SET_DRIVE(_name, _hsm, _schmitt, _drive, _pulldn_drive, _pullup_drive, _pulldn_slew, _pullup_slew) \
+ { \
+ .pingroup = TEGRA_DRIVE_PINGROUP_##_name, \
+ .hsm = TEGRA_HSM_##_hsm, \
+ .schmitt = TEGRA_SCHMITT_##_schmitt, \
+ .drive = TEGRA_DRIVE_##_drive, \
+ .pull_down = TEGRA_PULL_##_pulldn_drive, \
+ .pull_up = TEGRA_PULL_##_pullup_drive, \
+ .slew_rising = TEGRA_SLEW_##_pulldn_slew, \
+ .slew_falling = TEGRA_SLEW_##_pullup_slew, \
+ }
+
+static __initdata struct tegra_drive_pingroup_config apalis_t30_drive_pinmux[] = {
+ /* DEFAULT_DRIVE(<pin_group>), */
+
+ /* Audio codec */
+ SET_DRIVE(DAP2, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+
+ /* All I2C pins are driven to maximum drive strength */
+
+ /* GEN1_I2C: I2C_SDA/SCL on SODIMM pin 194/196 (e.g. RTC on carrier board) */
+ SET_DRIVE(DBG, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+
+ /* DDC_CLOCK/DATA on X3 pin 15/16 (e.g. display EDID) */
+ SET_DRIVE(DDC, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+
+ /* PWR_I2C: power I2C to audio codec, PMIC, temperature sensor and
+ touch screen controller */
+ SET_DRIVE(AO1, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+
+ /* SDMMC2 */
+ SET_DRIVE(AO2, DISABLE, DISABLE, DIV_1, 46, 42, FAST, FAST),
+
+ /* eMMC on SDMMC4 */
+ SET_DRIVE(GMA, DISABLE, DISABLE, DIV_1, 9, 9, SLOWEST, SLOWEST),
+ SET_DRIVE(GMB, DISABLE, DISABLE, DIV_1, 9, 9, SLOWEST, SLOWEST),
+ SET_DRIVE(GMC, DISABLE, DISABLE, DIV_1, 9, 9, SLOWEST, SLOWEST),
+ SET_DRIVE(GMD, DISABLE, DISABLE, DIV_1, 9, 9, SLOWEST, SLOWEST),
+};
+
+#define DEFAULT_PINMUX(_pingroup, _mux, _pupd, _tri, _io) \
+ { \
+ .pingroup = TEGRA_PINGROUP_##_pingroup, \
+ .func = TEGRA_MUX_##_mux, \
+ .pupd = TEGRA_PUPD_##_pupd, \
+/* TRISTATE here means output driver is tri-stated */ \
+ .tristate = TEGRA_TRI_##_tri, \
+/* INPUT here means input driver is enabled vs. OUTPUT where it is disabled */ \
+ .io = TEGRA_PIN_##_io, \
+ .lock = TEGRA_PIN_LOCK_DEFAULT, \
+ .od = TEGRA_PIN_OD_DEFAULT, \
+ .ioreset = TEGRA_PIN_IO_RESET_DEFAULT, \
+ }
+
+#define I2C_PINMUX(_pingroup, _mux, _pupd, _tri, _io, _lock, _od) \
+ { \
+ .pingroup = TEGRA_PINGROUP_##_pingroup, \
+ .func = TEGRA_MUX_##_mux, \
+ .pupd = TEGRA_PUPD_##_pupd, \
+ .tristate = TEGRA_TRI_##_tri, \
+ .io = TEGRA_PIN_##_io, \
+ .lock = TEGRA_PIN_LOCK_##_lock, \
+ .od = TEGRA_PIN_OD_##_od, \
+ .ioreset = TEGRA_PIN_IO_RESET_DEFAULT, \
+ }
+
+#define VI_PINMUX(_pingroup, _mux, _pupd, _tri, _io, _lock, _ioreset) \
+ { \
+ .pingroup = TEGRA_PINGROUP_##_pingroup, \
+ .func = TEGRA_MUX_##_mux, \
+ .pupd = TEGRA_PUPD_##_pupd, \
+ .tristate = TEGRA_TRI_##_tri, \
+ .io = TEGRA_PIN_##_io, \
+ .lock = TEGRA_PIN_LOCK_##_lock, \
+ .od = TEGRA_PIN_OD_DEFAULT, \
+ .ioreset = TEGRA_PIN_IO_RESET_##_ioreset \
+ }
+
+static __initdata struct tegra_pingroup_config apalis_t30_pinmux[] = {
+ I2C_PINMUX(CAM_I2C_SCL, I2C3, NORMAL, NORMAL, INPUT, DEFAULT, ENABLE),
+ I2C_PINMUX(CAM_I2C_SDA, I2C3, NORMAL, NORMAL, INPUT, DEFAULT, ENABLE),
+ DEFAULT_PINMUX(CAM_MCLK, VI_ALT2, NORMAL, NORMAL, OUTPUT),
+
+ DEFAULT_PINMUX(CLK1_OUT, EXTPERIPH1, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(CLK1_REQ, HDA, NORMAL, NORMAL, OUTPUT),
+
+ DEFAULT_PINMUX(CLK2_OUT, EXTPERIPH2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(CLK2_REQ, RSVD1, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(CLK3_OUT, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(CLK3_REQ, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+
+ DEFAULT_PINMUX(CLK_32K_OUT, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+
+ DEFAULT_PINMUX(CRT_HSYNC, CRT, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(CRT_VSYNC, CRT, NORMAL, NORMAL, OUTPUT),
+
+ DEFAULT_PINMUX(DAP1_DIN, HDA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(DAP1_DOUT, HDA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(DAP1_FS, HDA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(DAP1_SCLK, HDA, NORMAL, NORMAL, INPUT),
+
+//multiplexed CAN1/2_RX/TX
+ DEFAULT_PINMUX(DAP2_DIN, RSVD2, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(DAP2_DOUT, RSVD2, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(DAP2_FS, RSVD2, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(DAP2_SCLK, RSVD2, NORMAL, TRISTATE, OUTPUT),
+
+ DEFAULT_PINMUX(DAP3_DIN, I2S2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(DAP3_DOUT, I2S2, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(DAP3_FS, I2S2, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(DAP3_SCLK, I2S2, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(DAP4_DIN, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(DAP4_DOUT, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(DAP4_FS, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(DAP4_SCLK, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+
+ I2C_PINMUX(DDC_SCL, I2C4, NORMAL, NORMAL, INPUT, DEFAULT, ENABLE),
+ I2C_PINMUX(DDC_SDA, I2C4, NORMAL, NORMAL, INPUT, DEFAULT, ENABLE),
+
+ I2C_PINMUX(GEN1_I2C_SCL, I2C1, NORMAL, NORMAL, INPUT, DEFAULT, ENABLE),
+ I2C_PINMUX(GEN1_I2C_SDA, I2C1, NORMAL, NORMAL, INPUT, DEFAULT, ENABLE),
+
+ I2C_PINMUX(GEN2_I2C_SCL, RSVD3, NORMAL, NORMAL, INPUT, DEFAULT, DISABLE),
+ I2C_PINMUX(GEN2_I2C_SDA, RSVD3, NORMAL, NORMAL, INPUT, DEFAULT, DISABLE),
+
+ DEFAULT_PINMUX(GMI_A16, SPI4, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_A17, SPI4, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_A18, SPI4, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_A19, SPI4, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(GMI_AD0, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_AD1, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_AD2, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_AD3, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_AD4, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_AD5, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_AD6, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_AD7, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_AD8, RSVD2, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_AD9, RSVD2, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_AD10, RSVD2, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_AD11, RSVD2, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_AD12, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_AD13, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_AD14, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_AD15, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_ADV_N, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_CLK, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_CS0_N, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_CS1_N, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_CS2_N, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_CS3_N, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_CS4_N, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_CS6_N, GMI, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_CS7_N, GMI, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_DQS, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_IORDY, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+
+ DEFAULT_PINMUX(GMI_OE_N, RSVD1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_RST_N, RSVD3, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(GMI_WAIT, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_WP_N, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GMI_WR_N, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+
+ DEFAULT_PINMUX(GPIO_PBB0, RSVD1, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(GPIO_PBB3, VGP3, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(GPIO_PBB4, VGP4, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(GPIO_PBB5, VGP5, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(GPIO_PBB6, VGP6, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(GPIO_PBB7, RSVD1, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(GPIO_PCC1, RSVD1, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(GPIO_PCC2, RSVD1, NORMAL, NORMAL, OUTPUT),
+
+ DEFAULT_PINMUX(GPIO_PU0, GMI, PULL_DOWN, NORMAL, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GPIO_PU1, GMI, PULL_DOWN, NORMAL, OUTPUT), /* NC */
+ DEFAULT_PINMUX(GPIO_PU2, GMI, PULL_DOWN, NORMAL, OUTPUT), /* NC */
+
+ DEFAULT_PINMUX(GPIO_PU3, PWM0, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(GPIO_PU4, PWM1, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(GPIO_PU5, PWM2, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(GPIO_PU6, PWM3, NORMAL, NORMAL, OUTPUT),
+
+ DEFAULT_PINMUX(GPIO_PV0, RSVD, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GPIO_PV1, RSVD, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GPIO_PV2, RSVD1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GPIO_PV3, RSVD1, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(HDMI_CEC, CEC, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(HDMI_INT, RSVD0, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(JTAG_RTCK, RTCK, NORMAL, NORMAL, OUTPUT),
+
+//multiplexed OWR
+ DEFAULT_PINMUX(KB_COL0, KBC, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(KB_COL1, KBC, NORMAL, NORMAL, INPUT),
+
+//multiplexed VI_PCLK, VI_VSYNC and VI_HSYNC
+ DEFAULT_PINMUX(KB_COL2, KBC, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_COL3, KBC, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_COL4, KBC, NORMAL, TRISTATE, INPUT),
+
+//multiplexed VI_D11
+ DEFAULT_PINMUX(KB_COL5, KBC, NORMAL, NORMAL, INPUT),
+//multiplexed VI_D10
+ DEFAULT_PINMUX(KB_COL6, KBC, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(KB_COL7, KBC, NORMAL, NORMAL, INPUT),
+
+//multiplexed VI_D2, VI_D3, VI_D4, VI_D5, VI_D6, VI_D7, VI_D8 and VI_D9
+ DEFAULT_PINMUX(KB_ROW0, RSVD2, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_ROW1, RSVD2, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_ROW2, RSVD2, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_ROW3, RSVD2, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_ROW4, RSVD3, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_ROW5, KBC, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_ROW6, KBC, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_ROW7, KBC, NORMAL, TRISTATE, INPUT),
+
+//multiplexed VI_D0
+ DEFAULT_PINMUX(KB_ROW8, KBC, NORMAL, NORMAL, INPUT),
+//multiplexed VI_D1
+ DEFAULT_PINMUX(KB_ROW9, KBC, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(KB_ROW10, KBC, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(KB_ROW11, KBC, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(KB_ROW12, KBC, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(KB_ROW13, KBC, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(KB_ROW14, KBC, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(KB_ROW15, KBC, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(LCD_CS0_N, SPI5, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(LCD_CS1_N, RSVD2, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+
+ DEFAULT_PINMUX(LCD_D0, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D1, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D2, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D3, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D4, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D5, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D6, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D7, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D8, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D9, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D10, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D11, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D12, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D13, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D14, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D15, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D16, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D17, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D18, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D19, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D20, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D21, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D22, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D23, DISPLAYA, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(LCD_DC0, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+
+ DEFAULT_PINMUX(LCD_DC1, RSVD1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_DE, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_HSYNC, DISPLAYA, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(LCD_M1, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+
+ DEFAULT_PINMUX(LCD_PCLK, DISPLAYA, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(LCD_PWR0, DISPLAYB, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(LCD_PWR1, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(LCD_PWR2, RSVD, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+
+ DEFAULT_PINMUX(LCD_SCK, SPI5, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_SDIN, SPI5, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_SDOUT, SPI5, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(LCD_VSYNC, DISPLAYA, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(LCD_WR_N, RSVD, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+
+//multiplexed KB_COL0
+ DEFAULT_PINMUX(OWR, OWR, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(PEX_L0_CLKREQ_N, RSVD2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(PEX_L0_PRSNT_N, RSVD2, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(PEX_L0_RST_N, RSVD2, NORMAL, NORMAL, OUTPUT),
+
+ DEFAULT_PINMUX(PEX_L1_CLKREQ_N, RSVD2, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(PEX_L1_PRSNT_N, RSVD2, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(PEX_L1_RST_N, RSVD2, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+
+ DEFAULT_PINMUX(PEX_L2_CLKREQ_N, PCIE, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(PEX_L2_PRSNT_N, PCIE, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(PEX_L2_RST_N, PCIE, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(PEX_WAKE_N, PCIE, NORMAL, NORMAL, INPUT),
+
+/* Power I2C pinmux */
+ I2C_PINMUX(PWR_I2C_SCL, I2CPWR, NORMAL, NORMAL, INPUT, DEFAULT, ENABLE),
+ I2C_PINMUX(PWR_I2C_SDA, I2CPWR, NORMAL, NORMAL, INPUT, DEFAULT, ENABLE),
+
+ DEFAULT_PINMUX(SDMMC1_CLK, SDMMC1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC1_CMD, SDMMC1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC1_DAT0, SDMMC1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC1_DAT1, SDMMC1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC1_DAT2, SDMMC1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC1_DAT3, SDMMC1, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(SDMMC3_CLK, SDMMC3, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC3_CMD, SDMMC3, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC3_DAT0, SDMMC3, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC3_DAT1, SDMMC3, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC3_DAT2, SDMMC3, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC3_DAT3, SDMMC3, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC3_DAT4, SDMMC3, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC3_DAT5, SDMMC3, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC3_DAT6, SDMMC3, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC3_DAT7, SDMMC3, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(SDMMC4_CLK, SDMMC4, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_CMD, SDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT0, SDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT1, SDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT2, SDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT3, SDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT4, SDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT5, SDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT6, SDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT7, SDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_RST_N, RSVD1, PULL_DOWN, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(SPDIF_IN, SPDIF, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SPDIF_OUT, SPDIF, NORMAL, NORMAL, OUTPUT),
+
+ DEFAULT_PINMUX(SPI1_CS0_N, SPI1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SPI1_MISO, SPI1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SPI1_MOSI, SPI1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SPI1_SCK, SPI1, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(SPI2_CS0_N, SPI2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SPI2_CS1_N, SPI2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SPI2_CS2_N, SPI2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SPI2_MISO, SPI2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SPI2_MOSI, SPI2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SPI2_SCK, SPI2, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(SYS_CLK_REQ, SYSCLK, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(UART2_CTS_N, GMI, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(UART2_RTS_N, GMI, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+
+ DEFAULT_PINMUX(UART2_RXD, IRDA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(UART2_TXD, IRDA, NORMAL, NORMAL, OUTPUT),
+
+//disable BKL1_PWM_EN# (e.g. PMIC PWM backlight enable) for now
+ DEFAULT_PINMUX(UART3_CTS_N, RSVD1, PULL_UP, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(UART3_RTS_N, PWM0, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(UART3_RXD, UARTC, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(UART3_TXD, UARTC, NORMAL, NORMAL, OUTPUT),
+
+ DEFAULT_PINMUX(ULPI_CLK, UARTD, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_DATA0, UARTA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_DATA1, UARTA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_DATA2, UARTA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_DATA3, UARTA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_DATA4, UARTA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_DATA5, UARTA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_DATA6, UARTA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_DATA7, UARTA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_DIR, UARTD, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_NXT, UARTD, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_STP, UARTD, NORMAL, NORMAL, INPUT),
+
+//VI pins are all input level-shifted and multiplexed
+//unused VI pins could disable input drivers
+ VI_PINMUX(VI_D0, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D1, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D2, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D3, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D4, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D5, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D6, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D7, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D8, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D9, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D10, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D11, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_HSYNC, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ DEFAULT_PINMUX(VI_MCLK, VI, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ VI_PINMUX(VI_PCLK, VI, PULL_UP, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_VSYNC, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+};
+
+#define GPIO_INIT_PIN_MODE(_gpio, _is_input, _value) \
+ { \
+ .gpio_nr = _gpio, \
+ .is_input = _is_input, \
+ .value = _value, \
+ }
+
+static struct gpio_init_pin_info apalis_t30_init_gpio_mode[] = {
+};
+
+static void __init apalis_t30_gpio_init_configure(void)
+{
+ int len;
+ int i;
+ struct gpio_init_pin_info *pins_info;
+
+ len = ARRAY_SIZE(apalis_t30_init_gpio_mode);
+ pins_info = apalis_t30_init_gpio_mode;
+
+ for (i = 0; i < len; ++i) {
+ tegra_gpio_init_configure(pins_info->gpio_nr,
+ pins_info->is_input,
+ pins_info->value);
+ pins_info++;
+ }
+}
+
+int __init apalis_t30_pinmux_init(void)
+{
+ apalis_t30_gpio_init_configure();
+
+ tegra_pinmux_config_table(apalis_t30_pinmux,
+ ARRAY_SIZE(apalis_t30_pinmux));
+ tegra_drive_pinmux_config_table(apalis_t30_drive_pinmux,
+ ARRAY_SIZE(apalis_t30_drive_pinmux));
+
+ return 0;
+}
diff --git a/arch/arm/mach-tegra/board-apalis_t30-power.c b/arch/arm/mach-tegra/board-apalis_t30-power.c
new file mode 100644
index 000000000000..5e1bc2231b0d
--- /dev/null
+++ b/arch/arm/mach-tegra/board-apalis_t30-power.c
@@ -0,0 +1,510 @@
+/*
+ * arch/arm/mach-tegra/board-apalis_t30-power.c
+ *
+ * Copyright (C) 2013 Toradex, Inc.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#include <asm/mach-types.h>
+
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/mfd/tps6591x.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/tps62360.h>
+#include <linux/regulator/tps6591x-regulator.h>
+#include <linux/resource.h>
+
+#include <mach/edp.h>
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+#include <mach/pinmux.h>
+
+#include "board-apalis_t30.h"
+#include "board.h"
+#include "gpio-names.h"
+#include "tegra3_tsensor.h"
+#include "pm.h"
+#include "wakeups.h"
+#include "wakeups-t3.h"
+
+#define PMC_CTRL 0x0
+#define PMC_CTRL_INTR_LOW (1 << 17)
+
+/* SW1: +V1.35_VDDIO_DDR */
+static struct regulator_consumer_supply tps6591x_vdd1_supply_0[] = {
+ REGULATOR_SUPPLY("mem_vddio_ddr", NULL),
+ REGULATOR_SUPPLY("t30_vddio_ddr", NULL),
+};
+
+/* SW2: +V1.05 */
+static struct regulator_consumer_supply tps6591x_vdd2_supply_0[] = {
+ REGULATOR_SUPPLY("avdd_sata", NULL),
+ REGULATOR_SUPPLY("vdd_sata", NULL),
+ REGULATOR_SUPPLY("avdd_sata_pll", NULL),
+};
+
+/* SW CTRL: +V1.0_VDD_CPU */
+static struct regulator_consumer_supply tps6591x_vddctrl_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_cpu_pmu", NULL),
+ REGULATOR_SUPPLY("vdd_cpu", NULL),
+//!=vddio_sys!
+ REGULATOR_SUPPLY("vdd_sys", NULL),
+};
+
+/* SWIO: +V1.8 */
+static struct regulator_consumer_supply tps6591x_vio_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_gen1v8", NULL),
+ REGULATOR_SUPPLY("avdd_usb_pll", NULL),
+ REGULATOR_SUPPLY("avdd_osc", NULL),
+ REGULATOR_SUPPLY("vddio_sdmmc", "sdhci-tegra.3"),
+ REGULATOR_SUPPLY("pwrdet_sdmmc4", NULL),
+ REGULATOR_SUPPLY("vdd1v8_satelite", NULL),
+ REGULATOR_SUPPLY("vddio_vi", NULL),
+ REGULATOR_SUPPLY("pwrdet_vi", NULL),
+ REGULATOR_SUPPLY("ldo1", NULL),
+ REGULATOR_SUPPLY("ldo2", NULL),
+ REGULATOR_SUPPLY("ldo6", NULL),
+ REGULATOR_SUPPLY("ldo7", NULL),
+ REGULATOR_SUPPLY("ldo8", NULL),
+ REGULATOR_SUPPLY("vcore_audio", NULL),
+ REGULATOR_SUPPLY("avcore_audio", NULL),
+ REGULATOR_SUPPLY("vcore1_lpddr2", NULL),
+ REGULATOR_SUPPLY("vcom_1v8", NULL),
+ REGULATOR_SUPPLY("pmuio_1v8", NULL),
+ REGULATOR_SUPPLY("avdd_ic_usb", NULL),
+};
+
+/* unused */
+static struct regulator_consumer_supply tps6591x_ldo1_supply_0[] = {
+ REGULATOR_SUPPLY("unused_rail_ldo1", NULL),
+};
+
+/* EN_+V3.3 switching via FET: +V3.3_AUDIO_AVDD_S, +V3.3 and +V1.8_VDD_LAN
+ see also v3_3 fixed supply */
+//Apalis T30
+//+V3.3_VPP_FUSE
+//POWER_ENABLE_MOCI
+//+V3.3_TOUCH_AVDD_S
+//+V3.3_AUDIO_AVDD_S
+static struct regulator_consumer_supply tps6591x_ldo2_supply_0[] = {
+ REGULATOR_SUPPLY("en_V3_3", NULL),
+};
+
+/* +V1.2_CSI */
+static struct regulator_consumer_supply tps6591x_ldo3_supply_0[] = {
+ REGULATOR_SUPPLY("avdd_dsi_csi", NULL),
+ REGULATOR_SUPPLY("pwrdet_mipi", NULL),
+};
+
+/* +V1.2_VDD_RTC */
+static struct regulator_consumer_supply tps6591x_ldo4_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_rtc", NULL),
+};
+
+/* +V2.8_AVDD_VDAC */
+//only required for analog RGB
+static struct regulator_consumer_supply tps6591x_ldo5_supply_0[] = {
+ REGULATOR_SUPPLY("avdd_vdac", NULL),
+};
+
+//Apalis T30
+/* +V1.05_AVDD_PLLE */
+static struct regulator_consumer_supply tps6591x_ldo6_supply_0[] = {
+ REGULATOR_SUPPLY("avdd_plle", NULL),
+};
+
+/* +V1.2_AVDD_PLL */
+static struct regulator_consumer_supply tps6591x_ldo7_supply_0[] = {
+ REGULATOR_SUPPLY("avdd_plla_p_c_s", NULL),
+ REGULATOR_SUPPLY("avdd_pllm", NULL),
+ REGULATOR_SUPPLY("avdd_pllu_d", NULL),
+ REGULATOR_SUPPLY("avdd_pllu_d2", NULL),
+ REGULATOR_SUPPLY("avdd_pllx", NULL),
+};
+
+/* +V1.0_VDD_DDR_HS */
+static struct regulator_consumer_supply tps6591x_ldo8_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_ddr_hs", NULL),
+};
+
+#define TPS_PDATA_INIT(_name, _sname, _minmv, _maxmv, _supply_reg, _always_on, \
+ _boot_on, _apply_uv, _init_uV, _init_enable, _init_apply, _ectrl, _flags) \
+ static struct tps6591x_regulator_platform_data pdata_##_name##_##_sname = \
+ { \
+ .regulator = { \
+ .constraints = { \
+ .min_uV = (_minmv)*1000, \
+ .max_uV = (_maxmv)*1000, \
+ .valid_modes_mask = (REGULATOR_MODE_NORMAL | \
+ REGULATOR_MODE_STANDBY), \
+ .valid_ops_mask = (REGULATOR_CHANGE_MODE | \
+ REGULATOR_CHANGE_STATUS | \
+ REGULATOR_CHANGE_VOLTAGE), \
+ .always_on = _always_on, \
+ .boot_on = _boot_on, \
+ .apply_uV = _apply_uv, \
+ }, \
+ .num_consumer_supplies = \
+ ARRAY_SIZE(tps6591x_##_name##_supply_##_sname), \
+ .consumer_supplies = tps6591x_##_name##_supply_##_sname, \
+ .supply_regulator = _supply_reg, \
+ }, \
+ .init_uV = _init_uV * 1000, \
+ .init_enable = _init_enable, \
+ .init_apply = _init_apply, \
+ .ectrl = _ectrl, \
+ .flags = _flags, \
+ }
+
+TPS_PDATA_INIT(vdd1, 0, 1350, 1350, 0, 1, 1, 1, -1, 0, 0, 0, 0);
+TPS_PDATA_INIT(vdd2, 0, 1050, 1050, 0, 1, 1, 1, -1, 0, 0, EXT_CTRL_SLEEP_OFF, 0);
+TPS_PDATA_INIT(vddctrl, 0, 800, 1300, 0, 1, 1, 0, -1, 0, 0, EXT_CTRL_EN1, 0);
+TPS_PDATA_INIT(vio, 0, 1800, 1800, 0, 1, 1, 0, -1, 0, 0, 0, 0);
+
+TPS_PDATA_INIT(ldo1, 0, 1000, 3300, tps6591x_rails(VIO), 0, 0, 0, -1, 0, 1, 0, 0);
+/* Make sure EN_+V3.3 is always on! */
+TPS_PDATA_INIT(ldo2, 0, 1200, 1200, tps6591x_rails(VIO), 1, 1, 1, -1, 0, 1, 0, 0);
+
+TPS_PDATA_INIT(ldo3, 0, 1200, 1200, 0, 0, 0, 0, -1, 0, 0, 0, 0);
+TPS_PDATA_INIT(ldo4, 0, 900, 1400, 0, 1, 0, 0, -1, 0, 0, 0, LDO_LOW_POWER_ON_SUSPEND);
+TPS_PDATA_INIT(ldo5, 0, 2800, 2800, 0, 0, 0, 0, -1, 0, 0, 0, 0);
+/* AVDD_PLLE should be 1.05V, but ldo_6 can not be adjusted in a 50mV granularity */
+TPS_PDATA_INIT(ldo6, 0, 1000, 1100, tps6591x_rails(VIO), 0, 0, 1, -1, 0, 0, 0, 0);
+
+TPS_PDATA_INIT(ldo7, 0, 1200, 1200, tps6591x_rails(VIO), 1, 1, 1, -1, 0, 0, EXT_CTRL_SLEEP_OFF, LDO_LOW_POWER_ON_SUSPEND);
+TPS_PDATA_INIT(ldo8, 0, 1000, 1000, tps6591x_rails(VIO), 1, 0, 0, -1, 0, 0, EXT_CTRL_SLEEP_OFF, LDO_LOW_POWER_ON_SUSPEND);
+
+#if defined(CONFIG_RTC_DRV_TPS6591x)
+static struct tps6591x_rtc_platform_data rtc_data = {
+ .irq = TEGRA_NR_IRQS + TPS6591X_INT_RTC_ALARM,
+ .time = {
+ .tm_year = 2000,
+ .tm_mon = 0,
+ .tm_mday = 1,
+ .tm_hour = 0,
+ .tm_min = 0,
+ .tm_sec = 0,
+ },
+};
+
+#define TPS_RTC_REG() \
+ { \
+ .id = 0, \
+ .name = "rtc_tps6591x", \
+ .platform_data = &rtc_data, \
+ }
+#endif
+
+#define TPS_REG(_id, _name, _sname) \
+ { \
+ .id = TPS6591X_ID_##_id, \
+ .name = "tps6591x-regulator", \
+ .platform_data = &pdata_##_name##_##_sname, \
+ }
+
+static struct tps6591x_subdev_info apalis_t30_tps_devs[] = {
+ TPS_REG(VDD_1, vdd1, 0),
+ TPS_REG(VDD_2, vdd2, 0),
+ TPS_REG(VDDCTRL, vddctrl, 0),
+ TPS_REG(VIO, vio, 0),
+ TPS_REG(LDO_1, ldo1, 0),
+ TPS_REG(LDO_2, ldo2, 0),
+ TPS_REG(LDO_3, ldo3, 0),
+ TPS_REG(LDO_4, ldo4, 0),
+ TPS_REG(LDO_5, ldo5, 0),
+ TPS_REG(LDO_6, ldo6, 0),
+ TPS_REG(LDO_7, ldo7, 0),
+ TPS_REG(LDO_8, ldo8, 0),
+#if defined(CONFIG_RTC_DRV_TPS6591x)
+ TPS_RTC_REG(),
+#endif
+};
+
+static struct tps6591x_sleep_keepon_data tps_slp_keepon = {
+ .clkout32k_keepon = 1,
+};
+
+static struct tps6591x_platform_data tps_platform = {
+ .irq_base = TPS6591X_IRQ_BASE,
+ .gpio_base = TPS6591X_GPIO_BASE,
+ .dev_slp_en = true,
+ .slp_keepon = &tps_slp_keepon,
+ .use_power_off = true,
+};
+
+static struct i2c_board_info __initdata apalis_t30_regulators[] = {
+ {
+ I2C_BOARD_INFO("tps6591x", 0x2D),
+//PWR_INT_IN wake18
+ .irq = INT_EXTERNAL_PMU,
+ .platform_data = &tps_platform,
+ },
+};
+
+/* TPS62362 DC-DC converter
+ SW: +V1.2_VDD_CORE */
+static struct regulator_consumer_supply tps6236x_dcdc_supply[] = {
+ REGULATOR_SUPPLY("vdd_core", NULL),
+};
+
+static struct tps62360_regulator_platform_data tps6236x_pdata = {
+ .reg_init_data = { \
+ .constraints = { \
+ .min_uV = 900000, \
+ .max_uV = 1400000, \
+ .valid_modes_mask = (REGULATOR_MODE_NORMAL | \
+ REGULATOR_MODE_STANDBY), \
+ .valid_ops_mask = (REGULATOR_CHANGE_MODE | \
+ REGULATOR_CHANGE_STATUS | \
+ REGULATOR_CHANGE_VOLTAGE), \
+ .always_on = 1, \
+ .boot_on = 1, \
+ .apply_uV = 0, \
+ }, \
+ .num_consumer_supplies = ARRAY_SIZE(tps6236x_dcdc_supply), \
+ .consumer_supplies = tps6236x_dcdc_supply, \
+ }, \
+ .en_discharge = true, \
+ .vsel0_gpio = -1, \
+ .vsel1_gpio = -1, \
+ .vsel0_def_state = 1, \
+ .vsel1_def_state = 1, \
+};
+
+static struct i2c_board_info __initdata tps6236x_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("tps62360", 0x60),
+ .platform_data = &tps6236x_pdata,
+ },
+};
+
+/* Macro for defining fixed regulator sub device data */
+#define FIXED_SUPPLY(_name) "fixed_reg_"#_name
+#define FIXED_REG_OD(_id, _var, _name, _in_supply, _always_on, \
+ _boot_on, _gpio_nr, _active_high, _boot_state, \
+ _millivolts, _od_state) \
+ static struct regulator_init_data ri_data_##_var = \
+ { \
+ .supply_regulator = _in_supply, \
+ .num_consumer_supplies = \
+ ARRAY_SIZE(fixed_reg_##_name##_supply), \
+ .consumer_supplies = fixed_reg_##_name##_supply, \
+ .constraints = { \
+ .valid_modes_mask = (REGULATOR_MODE_NORMAL), \
+ .valid_ops_mask = (REGULATOR_CHANGE_STATUS), \
+ .always_on = _always_on, \
+ .boot_on = _boot_on, \
+ }, \
+ }; \
+ static struct fixed_voltage_config fixed_reg_##_var##_pdata = \
+ { \
+ .supply_name = FIXED_SUPPLY(_name), \
+ .microvolts = _millivolts * 1000, \
+ .gpio = _gpio_nr, \
+ .enable_high = _active_high, \
+ .enabled_at_boot = _boot_state, \
+ .init_data = &ri_data_##_var, \
+ .gpio_is_open_drain = _od_state, \
+ }; \
+ static struct platform_device fixed_reg_##_var##_dev = { \
+ .name = "reg-fixed-voltage", \
+ .id = _id, \
+ .dev = { \
+ .platform_data = &fixed_reg_##_var##_pdata, \
+ }, \
+ }
+
+#define FIXED_REG(_id, _var, _name, _in_supply, _always_on, _boot_on, \
+ _gpio_nr, _active_high, _boot_state, _millivolts) \
+ FIXED_REG_OD(_id, _var, _name, _in_supply, _always_on, _boot_on, \
+ _gpio_nr, _active_high, _boot_state, _millivolts, false)
+
+#define ADD_FIXED_REG(_name) (&fixed_reg_##_name##_dev)
+
+/* PMU GP6: EN_VDD_HDMI switching via FET: +V1.8_AVDD_HDMI_PLL and +V3.3_AVDD_HDMI */
+static struct regulator_consumer_supply fixed_reg_en_hdmi_supply[] = {
+ REGULATOR_SUPPLY("avdd_hdmi", NULL),
+ REGULATOR_SUPPLY("avdd_hdmi_pll", NULL),
+// REGULATOR_SUPPLY("vdd_3v3_hdmi_cec", NULL),
+// REGULATOR_SUPPLY("vdd_hdmi_con", NULL),
+};
+
+//EN_VDD_CORE PMIC GPIO2
+//EN_VDD_FUSE PMIC GPIO4
+//EN_VDD_HDMI PMIC GPIO6
+
+FIXED_REG(2, en_hdmi, en_hdmi, NULL, 0, 0, TPS6591X_GPIO_6, true, 1, 1800);
+
+/* +V3.3 is switched on by LDO2, As this can not be modeled we use a fixed
+ regulator without enable, 3.3V must not be switched off anyway.
++V3.3:
+VDD_DDR_RX
+VDDIO_LCD_1
+VDDIO_LCD_2
+VDDIO_CAM
+LM95245
+VDDIO_SYS_01
+VDDIO_SYS_02
+VDDIO_BB
+VDDIO_AUDIO
+VDDIO_GMI_1
+VDDIO_GMI_2
+VDDIO_GMI_3
+VDDIO_UART
+VDDIO_SDMMC1
+AVDD_USB
+VDDIO_SDMMC3
+74AVCAH164245
+VDDIO_PEX_CTL
+TPS65911 VDDIO
+MT29F16G08
+SGTL5000 VDDIO
+STMPE811
+AX88772B VCC3x
+SDIN5D2-2G VCCx */
+static struct regulator_consumer_supply fixed_reg_v3_3_supply[] = {
+ REGULATOR_SUPPLY("avdd_audio", NULL),
+ REGULATOR_SUPPLY("avdd_usb", NULL),
+ REGULATOR_SUPPLY("vddio_sd_slot", "sdhci-tegra.1"),
+ REGULATOR_SUPPLY("vddio_sys", NULL),
+ REGULATOR_SUPPLY("vddio_uart", NULL),
+ REGULATOR_SUPPLY("pwrdet_uart", NULL),
+ REGULATOR_SUPPLY("vddio_audio", NULL),
+ REGULATOR_SUPPLY("pwrdet_audio", NULL),
+ REGULATOR_SUPPLY("vddio_bb", NULL),
+ REGULATOR_SUPPLY("pwrdet_bb", NULL),
+ REGULATOR_SUPPLY("vddio_lcd_pmu", NULL),
+ REGULATOR_SUPPLY("pwrdet_lcd", NULL),
+ REGULATOR_SUPPLY("vddio_cam", NULL),
+ REGULATOR_SUPPLY("pwrdet_cam", NULL),
+ /* if this supply is defined, the sdhci driver tries
+ * to set it to 1.8V */
+// REGULATOR_SUPPLY("vddio_sdmmc", "sdhci-tegra.1"),
+ REGULATOR_SUPPLY("pwrdet_sdmmc2", NULL),
+ REGULATOR_SUPPLY("pwrdet_sdmmc1", NULL),
+ REGULATOR_SUPPLY("pwrdet_sdmmc3", NULL),
+ REGULATOR_SUPPLY("pwrdet_pex_ctl", NULL),
+ REGULATOR_SUPPLY("pwrdet_nand", NULL),
+
+ /* SGTL5000 */
+ REGULATOR_SUPPLY("VDDA", "4-000a"),
+ REGULATOR_SUPPLY("VDDIO", "4-000a"),
+
+ REGULATOR_SUPPLY("hvdd_pex", NULL),
+ REGULATOR_SUPPLY("hvdd_sata", NULL),
+};
+
+FIXED_REG(3, v3_3, v3_3, NULL, 1, 1, -1, true, 1, 3300);
+
+/* Gpio switch regulator platform data */
+static struct platform_device *fixed_reg_devs_apalis_t30[] = {
+ ADD_FIXED_REG(en_hdmi),
+ ADD_FIXED_REG(v3_3),
+};
+
+int __init apalis_t30_regulator_init(void)
+{
+ void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
+ u32 pmc_ctrl;
+
+ /* configure the power management controller to trigger PMU
+ * interrupts when low */
+
+ pmc_ctrl = readl(pmc + PMC_CTRL);
+ writel(pmc_ctrl | PMC_CTRL_INTR_LOW, pmc + PMC_CTRL);
+
+ /* The regulator details have complete constraints */
+ regulator_has_full_constraints();
+
+ tps_platform.num_subdevs =
+ ARRAY_SIZE(apalis_t30_tps_devs);
+ tps_platform.subdevs = apalis_t30_tps_devs;
+
+ i2c_register_board_info(4, apalis_t30_regulators, 1);
+
+ /* Register the TPS6236x. */
+ pr_info("Registering the device TPS62360\n");
+ i2c_register_board_info(4, tps6236x_boardinfo, 1);
+
+ return 0;
+}
+
+int __init apalis_t30_fixed_regulator_init(void)
+{
+ return platform_add_devices(fixed_reg_devs_apalis_t30, ARRAY_SIZE(fixed_reg_devs_apalis_t30));
+}
+subsys_initcall_sync(apalis_t30_fixed_regulator_init);
+
+static void apalis_t30_board_suspend(int lp_state, enum suspend_stage stg)
+{
+ if ((lp_state == TEGRA_SUSPEND_LP1) && (stg == TEGRA_SUSPEND_BEFORE_CPU))
+ tegra_console_uart_suspend();
+}
+
+static void apalis_t30_board_resume(int lp_state, enum resume_stage stg)
+{
+ if ((lp_state == TEGRA_SUSPEND_LP1) && (stg == TEGRA_RESUME_AFTER_CPU))
+ tegra_console_uart_resume();
+}
+
+static struct tegra_suspend_platform_data apalis_t30_suspend_data = {
+ .cpu_timer = 2000,
+ .cpu_off_timer = 200,
+ .suspend_mode = TEGRA_SUSPEND_LP1,
+ .core_timer = 0x7e7e,
+ .core_off_timer = 0,
+ .corereq_high = true,
+ .sysclkreq_high = true,
+ .cpu_lp2_min_residency = 2000,
+ .board_suspend = apalis_t30_board_suspend,
+ .board_resume = apalis_t30_board_resume,
+};
+
+int __init apalis_t30_suspend_init(void)
+{
+ /* Make core_pwr_req to high */
+ apalis_t30_suspend_data.corereq_high = true;
+
+ /* CORE_PWR_REQ to be high required to enable the dc-dc converter tps62361x */
+ apalis_t30_suspend_data.corereq_high = true;
+
+//required?
+ apalis_t30_suspend_data.cpu_timer = 5000;
+ apalis_t30_suspend_data.cpu_off_timer = 5000;
+
+ tegra_init_suspend(&apalis_t30_suspend_data);
+ return 0;
+}
+
+#ifdef CONFIG_TEGRA_EDP_LIMITS
+int __init apalis_t30_edp_init(void)
+{
+ unsigned int regulator_mA;
+
+ regulator_mA = get_maximum_cpu_current_supported();
+ if (!regulator_mA) {
+ regulator_mA = 6000; /* regular T30/s */
+ }
+ pr_info("%s: CPU regulator %d mA\n", __func__, regulator_mA);
+
+ tegra_init_cpu_edp_limits(regulator_mA);
+ return 0;
+}
+#endif
diff --git a/arch/arm/mach-tegra/board-apalis_t30.c b/arch/arm/mach-tegra/board-apalis_t30.c
new file mode 100644
index 000000000000..5103c3ca2f4a
--- /dev/null
+++ b/arch/arm/mach-tegra/board-apalis_t30.c
@@ -0,0 +1,1238 @@
+/*
+ * arch/arm/mach-tegra/board-apalis_t30.c
+ *
+ * Copyright (c) 2013 Toradex, Inc.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <linux/can/platform/mcp251x.h>
+#include <linux/clk.h>
+#include <linux/types.h> /* required by linux/gpio_keys.h */
+#include <linux/gpio_keys.h>
+#include <linux/i2c.h>
+#include <linux/i2c-tegra.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/leds.h>
+#include <linux/leds_pwm.h>
+#include <linux/lm95245.h>
+#include <linux/mfd/stmpe.h>
+#include <linux/platform_data/tegra_usb.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/spi/spi.h>
+#include <linux/spi-tegra.h>
+#include <linux/tegra_uart.h>
+
+#include <mach/io_dpd.h>
+#include <mach/pci.h>
+#include <mach/sdhci.h>
+#include <mach/tegra_asoc_pdata.h>
+#include <mach/tegra_fiq_debugger.h>
+#include <mach/thermal.h>
+#include <mach/usb_phy.h>
+#include <mach/w1.h>
+
+#include "board-apalis_t30.h"
+#include "board.h"
+#include "clock.h"
+#include "devices.h"
+#include "gpio-names.h"
+#include "pm.h"
+
+/* ADC */
+
+//TODO
+
+/* Audio */
+
+/* HDA */
+
+//TODO
+
+/* I2S */
+
+static struct tegra_asoc_platform_data apalis_t30_audio_sgtl5000_pdata = {
+ .gpio_spkr_en = -1,
+ .gpio_hp_det = -1,
+ .gpio_hp_mute = -1,
+ .gpio_int_mic_en = -1,
+ .gpio_ext_mic_en = -1,
+ .i2s_param[HIFI_CODEC] = {
+ .audio_port_id = 0, /* index of below registered
+ tegra_i2s_device */
+ .i2s_mode = TEGRA_DAIFMT_I2S,
+ .is_i2s_master = 1,
+ .sample_size = 16,
+ },
+ .i2s_param[BASEBAND] = {
+ .audio_port_id = -1,
+ },
+ .i2s_param[BT_SCO] = {
+ .audio_port_id = -1,
+ },
+};
+
+static struct platform_device apalis_t30_audio_sgtl5000_device = {
+ .name = "tegra-snd-colibri_t30-sgtl5000",
+ .id = 0,
+ .dev = {
+ .platform_data = &apalis_t30_audio_sgtl5000_pdata,
+ },
+};
+
+#ifdef CONFIG_TEGRA_CAMERA
+/* Camera */
+static struct platform_device tegra_camera = {
+ .name = "tegra_camera",
+ .id = -1,
+};
+#endif /* CONFIG_TEGRA_CAMERA */
+
+/* CAN */
+
+#if defined(CONFIG_CAN_MCP251X) || defined(CONFIG_CAN_MCP251X_MODULE)
+static struct mcp251x_platform_data can_pdata = {
+ .oscillator_frequency = 16000000,
+ .power_enable = NULL,
+ .transceiver_enable = NULL
+};
+
+static struct spi_board_info can_board_info[] = {
+ {
+ .bus_num = 1, /* SPI2: CAN1 */
+ .chip_select = 0,
+ .max_speed_hz = 10000000,
+ .modalias = "mcp2515",
+ .platform_data = &can_pdata,
+ },
+ {
+ .bus_num = 3, /* SPI4: CAN2 */
+ .chip_select = 1,
+ .max_speed_hz = 10000000,
+ .modalias = "mcp2515",
+ .platform_data = &can_pdata,
+ },
+};
+
+static void __init apalis_t30_mcp2515_can_init(void)
+{
+ can_board_info[0].irq = gpio_to_irq(CAN1_INT);
+ can_board_info[1].irq = gpio_to_irq(CAN2_INT);
+ spi_register_board_info(can_board_info, ARRAY_SIZE(can_board_info));
+}
+#else /* CONFIG_CAN_MCP251X | CONFIG_CAN_MCP251X_MODULE */
+#define apalis_t30_mcp2515_can_init() do {} while (0)
+#endif /* CONFIG_CAN_MCP251X | CONFIG_CAN_MCP251X_MODULE */
+
+/* CEC */
+
+//TODO
+
+/* Clocks */
+static struct tegra_clk_init_table apalis_t30_clk_init_table[] __initdata = {
+ /* name parent rate enabled */
+ {"audio1", "i2s1_sync", 0, false},
+ {"audio2", "i2s2_sync", 0, false},
+ {"audio3", "i2s3_sync", 0, false},
+ {"blink", "clk_32k", 32768, true},
+ {"d_audio", "clk_m", 12000000, false},
+ {"dam0", "clk_m", 12000000, false},
+ {"dam1", "clk_m", 12000000, false},
+ {"dam2", "clk_m", 12000000, false},
+ {"hda", "pll_p", 108000000, false},
+ {"hda2codec_2x","pll_p", 48000000, false},
+ {"i2c1", "pll_p", 3200000, false},
+ {"i2c2", "pll_p", 3200000, false},
+ {"i2c3", "pll_p", 3200000, false},
+ {"i2c4", "pll_p", 3200000, false},
+ {"i2c5", "pll_p", 3200000, false},
+ {"i2s0", "pll_a_out0", 0, false},
+ {"i2s1", "pll_a_out0", 0, false},
+ {"i2s2", "pll_a_out0", 0, false},
+ {"i2s3", "pll_a_out0", 0, false},
+ {"pll_m", NULL, 0, false},
+ {"pwm", "pll_p", 3187500, false},
+ {"spdif_out", "pll_a_out0", 0, false},
+ {"vi", "pll_p", 0, false},
+ {"vi_sensor", "pll_p", 150000000, false},
+ {NULL, NULL, 0, 0},
+};
+
+/* GPIO */
+
+static struct gpio apalis_t30_gpios[] = {
+ {TEGRA_GPIO_PBB0, GPIOF_IN, "LVDS: Single/Dual Ch"},
+ {TEGRA_GPIO_PBB3, GPIOF_IN, "LVDS: 18/24 Bit Mode"},
+ {TEGRA_GPIO_PBB4, GPIOF_IN, "LVDS: Output Enable"},
+ {TEGRA_GPIO_PBB5, GPIOF_IN, "LVDS: Power Down"},
+ {TEGRA_GPIO_PBB6, GPIOF_IN, "LVDS: Clock Polarity"},
+ {TEGRA_GPIO_PBB7, GPIOF_IN, "LVDS: Colour Mapping"},
+ {TEGRA_GPIO_PCC1, GPIOF_IN, "LVDS: Swing Mode"},
+ {TEGRA_GPIO_PCC2, GPIOF_IN, "LVDS: DDRclk Disable"},
+};
+
+static void apalis_t30_gpio_init(void)
+{
+ int i = 0;
+ int length = sizeof(apalis_t30_gpios) / sizeof(struct gpio);
+ int err = 0;
+
+ for (i = 0; i < length; i++) {
+ err = gpio_request_one(apalis_t30_gpios[i].gpio,
+ apalis_t30_gpios[i].flags,
+ apalis_t30_gpios[i].label);
+
+ if (err) {
+ pr_warning("gpio_request(%s) failed, err = %d",
+ apalis_t30_gpios[i].label, err);
+ } else {
+ gpio_export(apalis_t30_gpios[i].gpio, true);
+ }
+ }
+}
+
+/* I2C */
+
+/* Make sure that the pinmuxing enable the 'open drain' feature for pins used
+ for I2C */
+
+/* GEN1_I2C: I2C1_SDA/SCL on MXM3 pin 209/211 (e.g. RTC on carrier board) */
+static struct i2c_board_info apalis_t30_i2c_bus1_board_info[] __initdata = {
+ {
+ /* M41T0M6 real time clock on Iris carrier board */
+ I2C_BOARD_INFO("rtc-ds1307", 0x68),
+ .type = "m41t00",
+ },
+};
+
+static struct tegra_i2c_platform_data apalis_t30_i2c1_platform_data = {
+ .adapter_nr = 0,
+ .arb_recovery = arb_lost_recovery,
+ .bus_clk_rate = {400000, 0},
+ .bus_count = 1,
+ .scl_gpio = {I2C1_SCL, 0},
+ .sda_gpio = {I2C1_SDA, 0},
+ .slave_addr = 0x00FC,
+};
+
+/* GEN2_I2C: unused */
+
+/* DDC: I2C2_SDA/SCL on MXM3 pin 205/207 (e.g. display EDID) */
+static struct tegra_i2c_platform_data apalis_t30_i2c4_platform_data = {
+ .adapter_nr = 3,
+ .arb_recovery = arb_lost_recovery,
+ .bus_clk_rate = {10000, 10000},
+ .bus_count = 1,
+ .scl_gpio = {I2C2_SCL, 0},
+ .sda_gpio = {I2C2_SDA, 0},
+ .slave_addr = 0x00FC,
+};
+
+/* CAM_I2C: I2C3_SDA/SCL on MXM3 pin 201/203 (e.g. camera sensor on carrier
+ board) */
+static struct tegra_i2c_platform_data apalis_t30_i2c3_platform_data = {
+ .adapter_nr = 2,
+ .arb_recovery = arb_lost_recovery,
+ .bus_clk_rate = {400000, 0},
+ .bus_count = 1,
+ .scl_gpio = {I2C3_SCL, 0},
+ .sda_gpio = {I2C3_SDA, 0},
+ .slave_addr = 0x00FC,
+};
+
+/* PWR_I2C: power I2C to audio codec, PMIC, temperature sensor and touch screen
+ controller */
+
+/* STMPE811 touch screen controller */
+static struct stmpe_ts_platform_data stmpe811_ts_data = {
+ .adc_freq = 1, /* 3.25 MHz ADC clock speed */
+ .ave_ctrl = 3, /* 8 sample average control */
+ .fraction_z = 7, /* 7 length fractional part in z */
+ .i_drive = 1, /* 50 mA typical 80 mA max touchscreen
+ drivers current limit value */
+ .mod_12b = 1, /* 12-bit ADC */
+ .ref_sel = 0, /* internal ADC reference */
+ .sample_time = 4, /* ADC converstion time: 80 clocks */
+ .settling = 3, /* 1 ms panel driver settling time */
+ .touch_det_delay = 5, /* 5 ms touch detect interrupt delay */
+};
+
+static struct stmpe_platform_data stmpe811_data = {
+ .blocks = STMPE_BLOCK_TOUCHSCREEN,
+ .id = 1,
+ .irq_base = STMPE811_IRQ_BASE,
+ .irq_trigger = IRQF_TRIGGER_FALLING,
+ .ts = &stmpe811_ts_data,
+};
+
+static void lm95245_probe_callback(struct device *dev);
+
+static struct lm95245_platform_data apalis_t30_lm95245_pdata = {
+ .enable_os_pin = true,
+ .probe_callback = lm95245_probe_callback,
+};
+
+static struct i2c_board_info apalis_t30_i2c_bus5_board_info[] __initdata = {
+ {
+ /* SGTL5000 audio codec */
+ I2C_BOARD_INFO("sgtl5000", 0x0a),
+ },
+ {
+ /* STMPE811 touch screen controller */
+ I2C_BOARD_INFO("stmpe", 0x41),
+ .flags = I2C_CLIENT_WAKE,
+ .platform_data = &stmpe811_data,
+ .type = "stmpe811",
+ },
+ {
+ /* LM95245 temperature sensor
+ Note: OVERT_N directly connected to PMIC PWRDN */
+ I2C_BOARD_INFO("lm95245", 0x4c),
+ .platform_data = &apalis_t30_lm95245_pdata,
+ },
+};
+
+static struct tegra_i2c_platform_data apalis_t30_i2c5_platform_data = {
+ .adapter_nr = 4,
+ .arb_recovery = arb_lost_recovery,
+ .bus_clk_rate = {400000, 0},
+ .bus_count = 1,
+ .scl_gpio = {PWR_I2C_SCL, 0},
+ .sda_gpio = {PWR_I2C_SDA, 0},
+};
+
+static void __init apalis_t30_i2c_init(void)
+{
+ tegra_i2c_device1.dev.platform_data = &apalis_t30_i2c1_platform_data;
+ tegra_i2c_device3.dev.platform_data = &apalis_t30_i2c3_platform_data;
+ tegra_i2c_device4.dev.platform_data = &apalis_t30_i2c4_platform_data;
+ tegra_i2c_device5.dev.platform_data = &apalis_t30_i2c5_platform_data;
+
+ platform_device_register(&tegra_i2c_device1);
+ platform_device_register(&tegra_i2c_device3);
+ platform_device_register(&tegra_i2c_device4);
+ platform_device_register(&tegra_i2c_device5);
+
+ i2c_register_board_info(0, apalis_t30_i2c_bus1_board_info,
+ ARRAY_SIZE(apalis_t30_i2c_bus1_board_info));
+
+ /* enable touch interrupt GPIO */
+ gpio_request(TOUCH_PEN_INT, "TOUCH_PEN_INT");
+ gpio_direction_input(TOUCH_PEN_INT);
+
+ apalis_t30_i2c_bus5_board_info[1].irq = gpio_to_irq(TOUCH_PEN_INT);
+ i2c_register_board_info(4, apalis_t30_i2c_bus5_board_info,
+ ARRAY_SIZE(apalis_t30_i2c_bus5_board_info));
+}
+
+/* IrDA */
+
+//TODO
+
+/* Keys */
+
+//TODO
+
+/* MMC/SD */
+
+static struct tegra_sdhci_platform_data apalis_t30_emmc_platform_data = {
+ .cd_gpio = -1,
+ .ddr_clk_limit = 52000000,
+ .is_8bit = 1,
+ .mmc_data = {
+ .built_in = 1,
+ },
+ .power_gpio = -1,
+ .tap_delay = 0x0f,
+ .wp_gpio = -1,
+};
+
+static struct tegra_sdhci_platform_data apalis_t30_mmccard_platform_data = {
+ .cd_gpio = MMC1_CD_N,
+ .ddr_clk_limit = 52000000,
+ .is_8bit = 1,
+ .power_gpio = -1,
+ .tap_delay = 0x0f,
+ .wp_gpio = -1,
+};
+
+static struct tegra_sdhci_platform_data apalis_t30_sdcard_platform_data = {
+ .cd_gpio = SD1_CD_N,
+ .ddr_clk_limit = 52000000,
+ .is_8bit = 0,
+ .power_gpio = -1,
+ .tap_delay = 0x0f,
+ .wp_gpio = -1,
+};
+
+static void __init apalis_t30_sdhci_init(void)
+{
+ /* register eMMC first */
+ tegra_sdhci_device4.dev.platform_data =
+ &apalis_t30_emmc_platform_data;
+ platform_device_register(&tegra_sdhci_device4);
+
+ tegra_sdhci_device3.dev.platform_data =
+ &apalis_t30_mmccard_platform_data;
+ platform_device_register(&tegra_sdhci_device3);
+
+ tegra_sdhci_device1.dev.platform_data =
+ &apalis_t30_sdcard_platform_data;
+ platform_device_register(&tegra_sdhci_device1);
+}
+
+/* PCIe */
+
+static struct tegra_pci_platform_data apalis_t30_pci_platform_data = {
+ .port_status[0] = 1,
+ .port_status[1] = 1,
+ .port_status[2] = 1,
+ .use_dock_detect = 0,
+ .gpio = 0,
+};
+
+static void apalis_t30_pci_init(void)
+{
+ /* Reset PLX PEX 8605 PCIe Switch on Apalis Evaluation Board */
+ gpio_request(PEX_PERST_N, "PEX_PERST_N");
+ gpio_direction_output(PEX_PERST_N, 0);
+ msleep(100);
+ gpio_set_value(PEX_PERST_N, 1);
+
+ tegra_pci_device.dev.platform_data = &apalis_t30_pci_platform_data;
+ platform_device_register(&tegra_pci_device);
+}
+
+/* PWM LEDs */
+static struct led_pwm tegra_leds_pwm[] = {
+ {
+ .name = "PWM3",
+ .pwm_id = 1,
+ .max_brightness = 255,
+ .pwm_period_ns = 19600,
+ },
+ {
+ .name = "PWM2",
+ .pwm_id = 2,
+ .max_brightness = 255,
+ .pwm_period_ns = 19600,
+ },
+ {
+ .name = "PWM1",
+ .pwm_id = 3,
+ .max_brightness = 255,
+ .pwm_period_ns = 19600,
+ },
+};
+
+static struct led_pwm_platform_data tegra_leds_pwm_data = {
+ .num_leds = ARRAY_SIZE(tegra_leds_pwm),
+ .leds = tegra_leds_pwm,
+};
+
+static struct platform_device tegra_led_pwm_device = {
+ .name = "leds_pwm",
+ .id = -1,
+ .dev = {
+ .platform_data = &tegra_leds_pwm_data,
+ },
+};
+
+/* RTC */
+
+#ifdef CONFIG_RTC_DRV_TEGRA
+static struct resource tegra_rtc_resources[] = {
+ [0] = {
+ .start = TEGRA_RTC_BASE,
+ .end = TEGRA_RTC_BASE + TEGRA_RTC_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = INT_RTC,
+ .end = INT_RTC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tegra_rtc_device = {
+ .name = "tegra_rtc",
+ .id = -1,
+ .resource = tegra_rtc_resources,
+ .num_resources = ARRAY_SIZE(tegra_rtc_resources),
+};
+#endif /* CONFIG_RTC_DRV_TEGRA */
+
+/* SATA */
+
+static struct gpio_led apalis_gpio_leds[] = {
+ [0] = {
+ .name = "SATA1_ACT_N",
+ .default_trigger = "ide-disk",
+ .gpio = SATA1_ACT_N,
+ .active_low = 1,
+ .retain_state_suspended = 0,
+ },
+};
+
+static struct gpio_led_platform_data apalis_gpio_led_data = {
+ .num_leds = ARRAY_SIZE(apalis_gpio_leds),
+ .leds = apalis_gpio_leds,
+};
+
+static struct platform_device apalis_led_gpio_device = {
+ .name = "leds-gpio",
+ .dev = {
+ .platform_data = &apalis_gpio_led_data,
+ },
+};
+
+#ifdef CONFIG_SATA_AHCI_TEGRA
+static void apalis_t30_sata_init(void)
+{
+ platform_device_register(&tegra_sata_device);
+ platform_device_register(&apalis_led_gpio_device);
+}
+#else
+static void apalis_t30_sata_init(void) { }
+#endif
+
+/* SPI */
+
+#if defined(CONFIG_SPI_TEGRA) && defined(CONFIG_SPI_SPIDEV)
+static struct spi_board_info tegra_spi_devices[] __initdata = {
+ {
+ .bus_num = 0, /* SPI1: Apalis SPI1 */
+ .chip_select = 0,
+ .irq = 0,
+ .max_speed_hz = 50000000,
+ .modalias = "spidev",
+ .mode = SPI_MODE_0,
+ .platform_data = NULL,
+ },
+ {
+ .bus_num = 4, /* SPI5: Apalis SPI2 */
+ .chip_select = 2,
+ .irq = 0,
+ .max_speed_hz = 50000000,
+ .modalias = "spidev",
+ .mode = SPI_MODE_0,
+ .platform_data = NULL,
+ },
+};
+
+static void __init apalis_t30_register_spidev(void)
+{
+ spi_register_board_info(tegra_spi_devices,
+ ARRAY_SIZE(tegra_spi_devices));
+}
+#else /* CONFIG_SPI_TEGRA && CONFIG_SPI_SPIDEV */
+#define apalis_t30_register_spidev() do {} while (0)
+#endif /* CONFIG_SPI_TEGRA && CONFIG_SPI_SPIDEV */
+
+static struct platform_device *apalis_t30_spi_devices[] __initdata = {
+ &tegra_spi_device1,
+ &tegra_spi_device2,
+ &tegra_spi_device4,
+ &tegra_spi_device5,
+};
+
+static struct spi_clk_parent spi_parent_clk[] = {
+ [0] = {.name = "pll_p"},
+#ifndef CONFIG_TEGRA_PLLM_RESTRICTED
+ [1] = {.name = "pll_m"},
+ [2] = {.name = "clk_m"},
+#else /* !CONFIG_TEGRA_PLLM_RESTRICTED */
+ [1] = {.name = "clk_m"},
+#endif /* !CONFIG_TEGRA_PLLM_RESTRICTED */
+};
+
+static struct tegra_spi_platform_data apalis_t30_spi_pdata = {
+ .is_dma_based = true,
+ .max_dma_buffer = 16 * 1024,
+ .is_clkon_always = false,
+ .max_rate = 100000000,
+};
+
+static void __init apalis_t30_spi_init(void)
+{
+ int i;
+ struct clk *c;
+
+ for (i = 0; i < ARRAY_SIZE(spi_parent_clk); ++i) {
+ c = tegra_get_clock_by_name(spi_parent_clk[i].name);
+ if (IS_ERR_OR_NULL(c)) {
+ pr_err("Not able to get the clock for %s\n",
+ spi_parent_clk[i].name);
+ continue;
+ }
+ spi_parent_clk[i].parent_clk = c;
+ spi_parent_clk[i].fixed_clk_rate = clk_get_rate(c);
+ }
+ apalis_t30_spi_pdata.parent_clk_list = spi_parent_clk;
+ apalis_t30_spi_pdata.parent_clk_count = ARRAY_SIZE(spi_parent_clk);
+ tegra_spi_device1.dev.platform_data = &apalis_t30_spi_pdata;
+ platform_add_devices(apalis_t30_spi_devices,
+ ARRAY_SIZE(apalis_t30_spi_devices));
+}
+
+/* Thermal throttling */
+
+static void *apalis_t30_alert_data;
+static void (*apalis_t30_alert_func)(void *);
+static int apalis_t30_low_edge = 0;
+static int apalis_t30_low_hysteresis = 3000;
+static int apalis_t30_low_limit = 0;
+static struct device *lm95245_device = NULL;
+static int thermd_alert_irq_disabled = 0;
+struct work_struct thermd_alert_work;
+struct workqueue_struct *thermd_alert_workqueue;
+
+static struct balanced_throttle throttle_list[] = {
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+ {
+ .id = BALANCED_THROTTLE_ID_TJ,
+ .throt_tab_size = 10,
+ .throt_tab = {
+ { 0, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 760000, 1000 },
+ { 760000, 1050 },
+ {1000000, 1050 },
+ {1000000, 1100 },
+ },
+ },
+#endif /* CONFIG_TEGRA_THERMAL_THROTTLE */
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ {
+ .id = BALANCED_THROTTLE_ID_SKIN,
+ .throt_tab_size = 6,
+ .throt_tab = {
+ { 640000, 1200 },
+ { 640000, 1200 },
+ { 760000, 1200 },
+ { 760000, 1200 },
+ {1000000, 1200 },
+ {1000000, 1200 },
+ },
+ },
+#endif /* CONFIG_TEGRA_SKIN_THROTTLE */
+};
+
+/* All units are in millicelsius */
+static struct tegra_thermal_data thermal_data = {
+ .shutdown_device_id = THERMAL_DEVICE_ID_NCT_EXT,
+ .temp_shutdown = 115000,
+
+#if defined(CONFIG_TEGRA_EDP_LIMITS) || defined(CONFIG_TEGRA_THERMAL_THROTTLE)
+ .throttle_edp_device_id = THERMAL_DEVICE_ID_NCT_EXT,
+#endif
+#ifdef CONFIG_TEGRA_EDP_LIMITS
+ .edp_offset = TDIODE_OFFSET, /* edp based on tdiode */
+ .hysteresis_edp = 3000,
+#endif
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+ .temp_throttle = 85000,
+ .tc1 = 0,
+ .tc2 = 1,
+ .passive_delay = 2000,
+#endif /* CONFIG_TEGRA_THERMAL_THROTTLE */
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ .skin_device_id = THERMAL_DEVICE_ID_SKIN,
+ .temp_throttle_skin = 43000,
+ .tc1_skin = 0,
+ .tc2_skin = 1,
+ .passive_delay_skin = 5000,
+
+ .skin_temp_offset = 9793,
+ .skin_period = 1100,
+ .skin_devs_size = 2,
+ .skin_devs = {
+ {
+ THERMAL_DEVICE_ID_NCT_EXT,
+ {
+ 2, 1, 1, 1,
+ 1, 1, 1, 1,
+ 1, 1, 1, 0,
+ 1, 1, 0, 0,
+ 0, 0, -1, -7
+ }
+ },
+ {
+ THERMAL_DEVICE_ID_NCT_INT,
+ {
+ -11, -7, -5, -3,
+ -3, -2, -1, 0,
+ 0, 0, 1, 1,
+ 1, 2, 2, 3,
+ 4, 6, 11, 18
+ }
+ },
+ },
+#endif /* CONFIG_TEGRA_SKIN_THROTTLE */
+};
+
+/* Over-temperature shutdown OS aka high limit GPIO pin interrupt handler */
+static irqreturn_t thermd_alert_irq(int irq, void *data)
+{
+ disable_irq_nosync(irq);
+ thermd_alert_irq_disabled = 1;
+ queue_work(thermd_alert_workqueue, &thermd_alert_work);
+
+ return IRQ_HANDLED;
+}
+
+/* Gets both entered by THERMD_ALERT GPIO interrupt as well as re-scheduled. */
+static void thermd_alert_work_func(struct work_struct *work)
+{
+ int temp = 0;
+
+ lm95245_get_remote_temp(lm95245_device, &temp);
+
+ /* This emulates NCT1008 low limit behaviour */
+ if (!apalis_t30_low_edge && temp <= apalis_t30_low_limit) {
+ apalis_t30_alert_func(apalis_t30_alert_data);
+ apalis_t30_low_edge = 1;
+ } else if (apalis_t30_low_edge && temp > apalis_t30_low_limit +
+ apalis_t30_low_hysteresis) {
+ apalis_t30_low_edge = 0;
+ }
+
+ /* Avoid unbalanced enable for IRQ 367 */
+ if (thermd_alert_irq_disabled) {
+ apalis_t30_alert_func(apalis_t30_alert_data);
+ thermd_alert_irq_disabled = 0;
+ enable_irq(gpio_to_irq(THERMD_ALERT_N));
+ }
+
+ /* Keep re-scheduling */
+ msleep(2000);
+ queue_work(thermd_alert_workqueue, &thermd_alert_work);
+}
+
+static int lm95245_get_temp(void *_data, long *temp)
+{
+ struct device *lm95245_device = _data;
+ int lm95245_temp = 0;
+ lm95245_get_remote_temp(lm95245_device, &lm95245_temp);
+ *temp = lm95245_temp;
+ return 0;
+}
+
+static int lm95245_get_temp_low(void *_data, long *temp)
+{
+ *temp = 0;
+ return 0;
+}
+
+/* Our temperature sensor only allows triggering an interrupt on over-
+ temperature shutdown aka the high limit we therefore need to setup a
+ workqueue to catch leaving the low limit. */
+static int lm95245_set_limits(void *_data,
+ long lo_limit_milli,
+ long hi_limit_milli)
+{
+ struct device *lm95245_device = _data;
+ apalis_t30_low_limit = lo_limit_milli;
+ if (lm95245_device) lm95245_set_remote_os_limit(lm95245_device,
+ hi_limit_milli);
+ return 0;
+}
+
+static int lm95245_set_alert(void *_data,
+ void (*alert_func)(void *),
+ void *alert_data)
+{
+ lm95245_device = _data;
+ apalis_t30_alert_func = alert_func;
+ apalis_t30_alert_data = alert_data;
+ return 0;
+}
+
+static int lm95245_set_shutdown_temp(void *_data, long shutdown_temp)
+{
+ struct device *lm95245_device = _data;
+ if (lm95245_device) lm95245_set_remote_critical_limit(lm95245_device,
+ shutdown_temp);
+ return 0;
+}
+
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+/* Internal aka local board/case temp */
+static int lm95245_get_itemp(void *dev_data, long *temp)
+{
+ struct device *lm95245_device = dev_data;
+ int lm95245_temp = 0;
+ lm95245_get_local_temp(lm95245_device, &lm95245_temp);
+ *temp = lm95245_temp;
+ return 0;
+}
+#endif /* CONFIG_TEGRA_SKIN_THROTTLE */
+
+static void lm95245_probe_callback(struct device *dev)
+{
+ struct tegra_thermal_device *lm95245_remote;
+
+ lm95245_remote = kzalloc(sizeof(struct tegra_thermal_device),
+ GFP_KERNEL);
+ if (!lm95245_remote) {
+ pr_err("unable to allocate thermal device\n");
+ return;
+ }
+
+ lm95245_remote->name = "lm95245_remote";
+ lm95245_remote->id = THERMAL_DEVICE_ID_NCT_EXT;
+ lm95245_remote->data = dev;
+ lm95245_remote->offset = TDIODE_OFFSET;
+ lm95245_remote->get_temp = lm95245_get_temp;
+ lm95245_remote->get_temp_low = lm95245_get_temp_low;
+ lm95245_remote->set_limits = lm95245_set_limits;
+ lm95245_remote->set_alert = lm95245_set_alert;
+ lm95245_remote->set_shutdown_temp = lm95245_set_shutdown_temp;
+
+ tegra_thermal_device_register(lm95245_remote);
+
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ {
+ struct tegra_thermal_device *lm95245_local;
+ lm95245_local = kzalloc(sizeof(struct tegra_thermal_device),
+ GFP_KERNEL);
+ if (!lm95245_local) {
+ kfree(lm95245_local);
+ pr_err("unable to allocate thermal device\n");
+ return;
+ }
+
+ lm95245_local->name = "lm95245_local";
+ lm95245_local->id = THERMAL_DEVICE_ID_NCT_INT;
+ lm95245_local->data = dev;
+ lm95245_local->get_temp = lm95245_get_itemp;
+
+ tegra_thermal_device_register(lm95245_local);
+ }
+#endif /* CONFIG_TEGRA_SKIN_THROTTLE */
+
+ if (request_irq(gpio_to_irq(THERMD_ALERT_N), thermd_alert_irq,
+ IRQF_TRIGGER_LOW, "THERMD_ALERT_N", NULL))
+ pr_err("%s: unable to register THERMD_ALERT_N interrupt\n",
+ __func__);
+}
+
+static void apalis_t30_thermd_alert_init(void)
+{
+ gpio_request(THERMD_ALERT_N, "THERMD_ALERT_N");
+ gpio_direction_input(THERMD_ALERT_N);
+
+ thermd_alert_workqueue = create_singlethread_workqueue("THERMD_ALERT_N"
+ );
+
+ INIT_WORK(&thermd_alert_work, thermd_alert_work_func);
+}
+
+/* UART */
+
+static struct platform_device *apalis_t30_uart_devices[] __initdata = {
+ &tegra_uarta_device, /* Apalis UART1 */
+ &tegra_uartd_device, /* Apalis UART2 */
+ &tegra_uartb_device, /* Apalis UART3 */
+ &tegra_uartc_device, /* Apalis UART4 */
+};
+
+static struct uart_clk_parent uart_parent_clk[] = {
+ [0] = {.name = "clk_m"},
+ [1] = {.name = "pll_p"},
+#ifndef CONFIG_TEGRA_PLLM_RESTRICTED
+ [2] = {.name = "pll_m"},
+#endif
+};
+
+static struct tegra_uart_platform_data apalis_t30_uart_pdata;
+
+static void __init uart_debug_init(void)
+{
+ int debug_port_id;
+
+ debug_port_id = get_tegra_uart_debug_port_id();
+ if (debug_port_id < 0) {
+ debug_port_id = 0;
+ }
+
+ switch (debug_port_id) {
+ case 0:
+ /* UARTA is the debug port. */
+ pr_info("Selecting UARTA as the debug console\n");
+ apalis_t30_uart_devices[0] = &debug_uarta_device;
+ debug_uart_clk = clk_get_sys("serial8250.0", "uarta");
+ debug_uart_port_base = ((struct plat_serial8250_port *)(
+ debug_uarta_device.dev.platform_data))->mapbase;
+ break;
+
+ case 1:
+ /* UARTB is the debug port. */
+ pr_info("Selecting UARTB as the debug console\n");
+ apalis_t30_uart_devices[2] = &debug_uartb_device;
+ debug_uart_clk = clk_get_sys("serial8250.0", "uartb");
+ debug_uart_port_base = ((struct plat_serial8250_port *)(
+ debug_uartb_device.dev.platform_data))->mapbase;
+ break;
+
+ case 2:
+ /* UARTC is the debug port. */
+ pr_info("Selecting UARTC as the debug console\n");
+ apalis_t30_uart_devices[3] = &debug_uartc_device;
+ debug_uart_clk = clk_get_sys("serial8250.0", "uartc");
+ debug_uart_port_base = ((struct plat_serial8250_port *)(
+ debug_uartb_device.dev.platform_data))->mapbase;
+ break;
+
+ case 3:
+ /* UARTD is the debug port. */
+ pr_info("Selecting UARTD as the debug console\n");
+ apalis_t30_uart_devices[1] = &debug_uartd_device;
+ debug_uart_clk = clk_get_sys("serial8250.0", "uartd");
+ debug_uart_port_base = ((struct plat_serial8250_port *)(
+ debug_uartd_device.dev.platform_data))->mapbase;
+ break;
+
+ default:
+ pr_info("The debug console id %d is invalid, Assuming UARTA",
+ debug_port_id);
+ apalis_t30_uart_devices[0] = &debug_uarta_device;
+ debug_uart_clk = clk_get_sys("serial8250.0", "uarta");
+ debug_uart_port_base = ((struct plat_serial8250_port *)(
+ debug_uarta_device.dev.platform_data))->mapbase;
+ break;
+ }
+ return;
+}
+
+static void __init apalis_t30_uart_init(void)
+{
+ struct clk *c;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(uart_parent_clk); ++i) {
+ c = tegra_get_clock_by_name(uart_parent_clk[i].name);
+ if (IS_ERR_OR_NULL(c)) {
+ pr_err("Not able to get the clock for %s\n",
+ uart_parent_clk[i].name);
+ continue;
+ }
+ uart_parent_clk[i].parent_clk = c;
+ uart_parent_clk[i].fixed_clk_rate = clk_get_rate(c);
+ }
+ apalis_t30_uart_pdata.parent_clk_list = uart_parent_clk;
+ apalis_t30_uart_pdata.parent_clk_count = ARRAY_SIZE(uart_parent_clk);
+ tegra_uarta_device.dev.platform_data = &apalis_t30_uart_pdata;
+ tegra_uartb_device.dev.platform_data = &apalis_t30_uart_pdata;
+ tegra_uartc_device.dev.platform_data = &apalis_t30_uart_pdata;
+ tegra_uartd_device.dev.platform_data = &apalis_t30_uart_pdata;
+
+ /* Register low speed only if it is selected */
+ if (!is_tegra_debug_uartport_hs()) {
+ uart_debug_init();
+ /* Clock enable for the debug channel */
+ if (!IS_ERR_OR_NULL(debug_uart_clk)) {
+ pr_info("The debug console clock name is %s\n",
+ debug_uart_clk->name);
+ c = tegra_get_clock_by_name("pll_p");
+ if (IS_ERR_OR_NULL(c))
+ pr_err("Not getting the parent clock pll_p\n");
+ else
+ clk_set_parent(debug_uart_clk, c);
+
+ clk_enable(debug_uart_clk);
+ clk_set_rate(debug_uart_clk, clk_get_rate(c));
+ } else {
+ pr_err("Not getting the clock %s for debug console\n",
+ debug_uart_clk->name);
+ }
+ }
+
+ platform_add_devices(apalis_t30_uart_devices,
+ ARRAY_SIZE(apalis_t30_uart_devices));
+}
+
+/* USB */
+
+//TODO: overcurrent
+
+static struct tegra_usb_platform_data tegra_udc_pdata = {
+ .has_hostpc = true,
+ .op_mode = TEGRA_USB_OPMODE_DEVICE,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .port_otg = true,
+ .u_cfg.utmi = {
+ .elastic_limit = 16,
+ .hssync_start_delay = 0,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup = 8,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
+ },
+ .u_data.dev = {
+ .charging_supported = false,
+ .remote_wakeup_supported = false,
+ .vbus_gpio = -1,
+ .vbus_pmu_irq = 0,
+ },
+};
+
+static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = {
+ .has_hostpc = true,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .port_otg = true,
+ .u_cfg.utmi = {
+ .elastic_limit = 16,
+ .hssync_start_delay = 0,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup = 15,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
+ },
+ .u_data.host = {
+ .hot_plug = true,
+ .power_off_on_suspend = false,
+ .remote_wakeup_supported = true,
+ .vbus_gpio = USBO1_EN,
+ .vbus_gpio_inverted = 0,
+ .vbus_reg = NULL,
+ },
+};
+
+static struct tegra_usb_platform_data tegra_ehci2_utmi_pdata = {
+ .has_hostpc = true,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .port_otg = false,
+ .u_cfg.utmi = {
+ .elastic_limit = 16,
+ .hssync_start_delay = 0,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup = 15,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
+ },
+ .u_data.host = {
+ .hot_plug = true,
+ .power_off_on_suspend = false,
+ .remote_wakeup_supported = true,
+ .vbus_gpio = USBH_EN,
+ .vbus_gpio_inverted = 0,
+ .vbus_reg = NULL,
+ },
+};
+
+static struct tegra_usb_platform_data tegra_ehci3_utmi_pdata = {
+ .has_hostpc = true,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .port_otg = false,
+ .u_cfg.utmi = {
+ .elastic_limit = 16,
+ .hssync_start_delay = 0,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup = 8,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
+ },
+ .u_data.host = {
+ .hot_plug = true,
+ .power_off_on_suspend = false,
+ .remote_wakeup_supported = true,
+ /* Uses same USBH_EN as EHCI2 */
+ .vbus_gpio = -1,
+ .vbus_gpio_inverted = 0,
+ .vbus_reg = NULL,
+ },
+};
+
+static struct tegra_usb_otg_data tegra_otg_pdata = {
+ .ehci_device = &tegra_ehci1_device,
+ .ehci_pdata = &tegra_ehci1_utmi_pdata,
+};
+
+static void apalis_t30_usb_init(void)
+{
+ /* OTG should be the first to be registered
+ EHCI instance 0: USB1_DP/N -> USBO1_DP/N */
+ tegra_otg_device.dev.platform_data = &tegra_otg_pdata;
+ platform_device_register(&tegra_otg_device);
+
+ /* setup the udc platform data */
+ tegra_udc_device.dev.platform_data = &tegra_udc_pdata;
+ platform_device_register(&tegra_udc_device);
+
+ /* EHCI instance 1: USB2_DP/N -> USBH2_DP/N */
+ tegra_ehci2_device.dev.platform_data = &tegra_ehci2_utmi_pdata;
+ platform_device_register(&tegra_ehci2_device);
+
+ /* EHCI instance 2: USB3_DP/N -> USBH3_DP/N */
+ tegra_ehci3_device.dev.platform_data = &tegra_ehci3_utmi_pdata;
+ platform_device_register(&tegra_ehci3_device);
+}
+
+/* W1, aka OWR, aka OneWire */
+
+#ifdef CONFIG_W1_MASTER_TEGRA
+struct tegra_w1_timings apalis_t30_w1_timings = {
+ .tsu = 1,
+ .trelease = 0xf,
+ .trdv = 0xf,
+ .tlow0 = 0x3c,
+ .tlow1 = 1,
+ .tslot = 0x77,
+
+ .tpdl = 0x78,
+ .tpdh = 0x1e,
+ .trstl = 0x1df,
+ .trsth = 0x1df,
+ .rdsclk = 0x7,
+ .psclk = 0x50,
+};
+
+struct tegra_w1_platform_data apalis_t30_w1_platform_data = {
+ .clk_id = "tegra_w1",
+ .timings = &apalis_t30_w1_timings,
+};
+#endif /* CONFIG_W1_MASTER_TEGRA */
+
+static struct platform_device *apalis_t30_devices[] __initdata = {
+ &tegra_pmu_device,
+#if defined(CONFIG_RTC_DRV_TEGRA)
+ &tegra_rtc_device,
+#endif
+#if defined(CONFIG_TEGRA_IOVMM_SMMU) || defined(CONFIG_TEGRA_IOMMU_SMMU)
+ &tegra_smmu_device,
+#endif
+ &tegra_wdt0_device,
+ &tegra_wdt1_device,
+ &tegra_wdt2_device,
+#if defined(CONFIG_TEGRA_AVP)
+ &tegra_avp_device,
+#endif
+#ifdef CONFIG_TEGRA_CAMERA
+ &tegra_camera,
+#endif
+#if defined(CONFIG_CRYPTO_DEV_TEGRA_SE)
+ &tegra_se_device,
+#endif
+#if defined(CONFIG_CRYPTO_DEV_TEGRA_AES)
+ &tegra_aes_device,
+#endif
+
+ &tegra_ahub_device,
+ &tegra_dam_device0,
+ &tegra_dam_device1,
+ &tegra_dam_device2,
+ &tegra_i2s_device2,
+ &tegra_spdif_device,
+ &spdif_dit_device,
+ &tegra_pcm_device,
+ &apalis_t30_audio_sgtl5000_device,
+
+ &tegra_cec_device,
+#if defined(CONFIG_CRYPTO_DEV_TEGRA_AES)
+ &tegra_aes_device,
+#endif
+#ifdef CONFIG_KEYBOARD_GPIO
+// &apalis_t30_keys_device,
+#endif
+ &tegra_led_pwm_device,
+ &tegra_pwfm1_device,
+ &tegra_pwfm2_device,
+ &tegra_pwfm3_device,
+#ifdef CONFIG_W1_MASTER_TEGRA
+ &tegra_w1_device,
+#endif
+};
+
+static void __init apalis_t30_init(void)
+{
+ tegra_thermal_init(&thermal_data,
+ throttle_list,
+ ARRAY_SIZE(throttle_list));
+ tegra_clk_init_from_table(apalis_t30_clk_init_table);
+ apalis_t30_pinmux_init();
+ apalis_t30_thermd_alert_init();
+ apalis_t30_i2c_init();
+ apalis_t30_spi_init();
+ apalis_t30_usb_init();
+#ifdef CONFIG_TEGRA_EDP_LIMITS
+ apalis_t30_edp_init();
+#endif
+ apalis_t30_uart_init();
+#ifdef CONFIG_W1_MASTER_TEGRA
+ tegra_w1_device.dev.platform_data = &apalis_t30_w1_platform_data;
+#endif
+ platform_add_devices(apalis_t30_devices, ARRAY_SIZE(apalis_t30_devices)
+ );
+ tegra_ram_console_debug_init();
+ tegra_io_dpd_init();
+ apalis_t30_sdhci_init();
+ apalis_t30_regulator_init();
+ apalis_t30_suspend_init();
+ apalis_t30_panel_init();
+// apalis_t30_sensors_init();
+ apalis_t30_sata_init();
+ apalis_t30_emc_init();
+ apalis_t30_register_spidev();
+
+ tegra_release_bootloader_fb();
+ apalis_t30_pci_init();
+#ifdef CONFIG_TEGRA_WDT_RECOVERY
+ tegra_wdt_recovery_init();
+#endif
+ tegra_serial_debug_init(TEGRA_UARTD_BASE, INT_WDT_CPU, NULL, -1, -1);
+ apalis_t30_mcp2515_can_init();
+ apalis_t30_gpio_init();
+}
+
+static void __init apalis_t30_reserve(void)
+{
+#if defined(CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM)
+ /* Support 1920X1080 32bpp,double buffered on HDMI*/
+ tegra_reserve(0, SZ_8M + SZ_1M, SZ_16M);
+#else
+ tegra_reserve(SZ_128M, SZ_8M, SZ_8M);
+#endif
+ tegra_ram_console_debug_reserve(SZ_1M);
+}
+
+static const char *apalis_t30_dt_board_compat[] = {
+ "toradex,apalis_t30",
+ NULL
+};
+
+MACHINE_START(APALIS_T30, "Toradex Apalis T30")
+ .boot_params = 0x80000100,
+ .dt_compat = apalis_t30_dt_board_compat,
+ .init_early = tegra_init_early,
+ .init_irq = tegra_init_irq,
+ .init_machine = apalis_t30_init,
+ .map_io = tegra_map_common_io,
+ .reserve = apalis_t30_reserve,
+ .timer = &tegra_timer,
+MACHINE_END
diff --git a/arch/arm/mach-tegra/board-apalis_t30.h b/arch/arm/mach-tegra/board-apalis_t30.h
new file mode 100644
index 000000000000..0e68be4e4de5
--- /dev/null
+++ b/arch/arm/mach-tegra/board-apalis_t30.h
@@ -0,0 +1,151 @@
+/*
+ * arch/arm/mach-tegra/board-apalis_t30.h
+ *
+ * Copyright (c) 2013 Toradex, Inc.
+ *
+ * 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 _MACH_TEGRA_BOARD_APALIS_T30_H
+#define _MACH_TEGRA_BOARD_APALIS_T30_H
+
+#include <linux/mfd/tps6591x.h>
+
+#include <mach/gpio.h>
+#include <mach/irqs.h>
+
+/* Run framebuffer in VGA mode */
+#define TEGRA_FB_VGA
+
+/* GPIO */
+
+#define APALIS_GPIO1 TEGRA_GPIO_PS2
+#define APALIS_GPIO2 TEGRA_GPIO_PS3
+#define APALIS_GPIO3 TEGRA_GPIO_PS4
+#define APALIS_GPIO4 TEGRA_GPIO_PS5
+#define APALIS_GPIO5 TEGRA_GPIO_PS6
+#define APALIS_GPIO6 TEGRA_GPIO_PQ0
+#define APALIS_GPIO7 TEGRA_GPIO_PS7
+#define APALIS_GPIO8 TEGRA_GPIO_PQ1
+
+#define BKL1_ON TEGRA_GPIO_PV2
+#define BKL1_PWM_EN_N TEGRA_GPIO_PA1
+
+#define CAN1_INT TEGRA_GPIO_PW2
+#define CAN2_INT TEGRA_GPIO_PW3
+
+#define FAN_EN APALIS_GPIO8
+
+#define GPIO1 TEGRA_GPIO_PS2
+#define GPIO2 TEGRA_GPIO_PS3
+#define GPIO3 TEGRA_GPIO_PS4
+#define GPIO4 TEGRA_GPIO_PS5
+#define GPIO5 TEGRA_GPIO_PS6
+#define GPIO6 TEGRA_GPIO_PQ0
+#define GPIO7 TEGRA_GPIO_PS7
+#define GPIO8 TEGRA_GPIO_PQ1
+
+#define HDMI1_HPD TEGRA_GPIO_PN7
+
+#define I2C1_SCL TEGRA_GPIO_PC4
+#define I2C1_SDA TEGRA_GPIO_PC5
+
+#define I2C2_SCL TEGRA_GPIO_PV4
+#define I2C2_SDA TEGRA_GPIO_PV5
+
+#define I2C3_SCL TEGRA_GPIO_PBB1
+#define I2C3_SDA TEGRA_GPIO_PBB2
+
+#define LAN_SMB_ALERT_N TEGRA_GPIO_PZ5
+
+#define LVDS_MODE TEGRA_GPIO_PBB0
+#define LVDS_6B_8B_N TEGRA_GPIO_PBB3
+#define LVDS_OE TEGRA_GPIO_PBB4
+#define LVDS_PDWN_N TEGRA_GPIO_PBB5
+#define LVDS_R_F_N TEGRA_GPIO_PBB6
+#define LVDS_MAP TEGRA_GPIO_PBB7
+#define LVDS_RS TEGRA_GPIO_PCC1
+#define LVDS_DDR_N TEGRA_GPIO_PCC2
+
+#define MMC1_CD_N TEGRA_GPIO_PV3
+
+#define PEX_PERST_N APALIS_GPIO7
+
+#define PWR_I2C_SCL TEGRA_GPIO_PZ6
+#define PWR_I2C_SDA TEGRA_GPIO_PZ7
+
+#define RESET_MOCI_N TEGRA_GPIO_PI4
+
+#define SATA1_ACT_N TEGRA_GPIO_PDD0
+
+#define SD1_CD_N TEGRA_GPIO_PCC5
+
+#define THERMD_ALERT_N TEGRA_GPIO_PD2
+
+#define TOUCH_PEN_INT TEGRA_GPIO_PV0
+#define TOUCH_WIPER APALIS_GPIO6
+
+#define TS1 TEGRA_GPIO_PI1
+#define TS2 TEGRA_GPIO_PQ7
+#define TS3 TEGRA_GPIO_PQ5
+#define TS4 TEGRA_GPIO_PQ6
+#define TS5 TEGRA_GPIO_PS0
+#define TS6 TEGRA_GPIO_PS1
+
+#define USBH_EN TEGRA_GPIO_PDD1
+#define USBH_OC_N TEGRA_GPIO_PDD2
+#define USBO1_EN TEGRA_GPIO_PT5
+#define USBO1_OC_N TEGRA_GPIO_PT6
+
+#define WAKE1_MICO TEGRA_GPIO_PV1
+
+/* STMPE811 IRQs */
+#define STMPE811_IRQ_BASE TEGRA_NR_IRQS
+#define STMPE811_IRQ_END (STMPE811_IRQ_BASE + 22)
+
+#define TDIODE_OFFSET (10000) /* in millicelsius */
+
+/* External peripheral act as gpio */
+/* TPS6591x GPIOs */
+#define TPS6591X_GPIO_BASE TEGRA_NR_GPIOS
+#define TPS6591X_GPIO_0 (TPS6591X_GPIO_BASE + TPS6591X_GPIO_GP0)
+#define TPS6591X_GPIO_1 (TPS6591X_GPIO_BASE + TPS6591X_GPIO_GP1)
+#define TPS6591X_GPIO_2 (TPS6591X_GPIO_BASE + TPS6591X_GPIO_GP2)
+#define TPS6591X_GPIO_3 (TPS6591X_GPIO_BASE + TPS6591X_GPIO_GP3)
+#define TPS6591X_GPIO_4 (TPS6591X_GPIO_BASE + TPS6591X_GPIO_GP4)
+#define TPS6591X_GPIO_5 (TPS6591X_GPIO_BASE + TPS6591X_GPIO_GP5)
+#define TPS6591X_GPIO_6 (TPS6591X_GPIO_BASE + TPS6591X_GPIO_GP6)
+#define TPS6591X_GPIO_7 (TPS6591X_GPIO_BASE + TPS6591X_GPIO_GP7)
+#define TPS6591X_GPIO_8 (TPS6591X_GPIO_BASE + TPS6591X_GPIO_GP8)
+#define TPS6591X_GPIO_END (TPS6591X_GPIO_BASE + TPS6591X_GPIO_NR)
+
+/*****************Interrupt tables ******************/
+/* External peripheral act as interrupt controller */
+/* TPS6591x IRQs */
+#define TPS6591X_IRQ_BASE STMPE811_IRQ_END
+#define TPS6591X_IRQ_END (TPS6591X_IRQ_BASE + 18)
+
+int apalis_t30_regulator_init(void);
+int apalis_t30_suspend_init(void);
+int apalis_t30_pinmux_init(void);
+int apalis_t30_panel_init(void);
+int apalis_t30_sensors_init(void);
+int apalis_t30_gpio_switch_regulator_init(void);
+int apalis_t30_pins_state_init(void);
+int apalis_t30_emc_init(void);
+int apalis_t30_power_off_init(void);
+int apalis_t30_edp_init(void);
+
+#endif
diff --git a/arch/arm/mach-tegra/board-aruba-sdhci.c b/arch/arm/mach-tegra/board-aruba-sdhci.c
index cf29137b773f..678385f2b8bd 100644
--- a/arch/arm/mach-tegra/board-aruba-sdhci.c
+++ b/arch/arm/mach-tegra/board-aruba-sdhci.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-harmony-sdhci.c
+ * arch/arm/mach-tegra/board-aruba-sdhci.c
*
* Copyright (C) 2010 Google, Inc.
*
diff --git a/arch/arm/mach-tegra/board-cardhu-sdhci.c b/arch/arm/mach-tegra/board-cardhu-sdhci.c
index df7177fb34a7..6b8948b874ff 100644
--- a/arch/arm/mach-tegra/board-cardhu-sdhci.c
+++ b/arch/arm/mach-tegra/board-cardhu-sdhci.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-harmony-sdhci.c
+ * arch/arm/mach-tegra/board-cardhu-sdhci.c
*
* Copyright (C) 2010 Google, Inc.
* Copyright (C) 2011-2012 NVIDIA Corporation.
diff --git a/arch/arm/mach-tegra/board-colibri_t20-memory.c b/arch/arm/mach-tegra/board-colibri_t20-memory.c
new file mode 100644
index 000000000000..65b24bfa6544
--- /dev/null
+++ b/arch/arm/mach-tegra/board-colibri_t20-memory.c
@@ -0,0 +1,464 @@
+/*
+ * arch/arm/mach-tegra/board-colibri_t20-memory.c
+ *
+ * Copyright (C) 2012 Toradex, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/memblock.h>
+
+#include "board-colibri_t20.h"
+#include "board.h"
+#include "tegra2_emc.h"
+
+/* Optimised timings for Colibri T20 256 MB */
+static const struct tegra_emc_table colibri_t20_emc_tables_nanya_333Mhz[] = {
+ {
+ .rate = 83250, /* SDRAM frequency */
+ .regs = {
+ 0x00000005, /* RC */
+ 0x00000011, /* RFC */
+ 0x00000004, /* RAS */
+ 0x00000002, /* RP */
+ 0x00000004, /* R2W */
+ 0x00000004, /* W2R */
+ 0x00000001, /* R2P */
+ 0x0000000a, /* W2P */
+ 0x00000002, /* RD_RCD */
+ 0x00000002, /* WR_RCD */
+ 0x00000001, /* RRD */
+ 0x00000001, /* REXT */
+ 0x00000003, /* WDV */
+ 0x00000004, /* QUSE */
+ 0x00000003, /* QRST */
+ 0x00000009, /* QSAFE */
+ 0x0000000c, /* RDV */
+ 0x0000025f, /* REFRESH */
+ 0x00000000, /* BURST_REFRESH_NUM */
+ 0x00000003, /* PDEX2WR */
+ 0x00000003, /* PDEX2RD */
+ 0x00000002, /* PCHG2PDEN */
+ 0x00000002, /* ACT2PDEN */
+ 0x00000001, /* AR2PDEN */
+ 0x00000008, /* RW2PDEN */
+ 0x000000c8, /* TXSR */
+ 0x00000003, /* TCKE */
+ 0x00000005, /* TFAW */
+ 0x00000003, /* TRPAB */
+ 0x00000006, /* TCLKSTABLE */
+ 0x00000002, /* TCLKSTOP */
+ 0x00000000, /* TREFBW */
+ 0x00000000, /* QUSE_EXTRA */
+ 0x00000002, /* FBIO_CFG6 */
+ 0x00000000, /* ODT_WRITE */
+ 0x00000000, /* ODT_READ */
+ 0x00000083, /* FBIO_CFG5 */
+ 0x00520006, /* CFG_DIG_DLL */
+ 0x00000010, /* DLL_XFORM_DQS */
+ 0x00000008, /* DLL_XFORM_QUSE */
+ 0x00000000, /* ZCAL_REF_CNT */
+ 0x00000000, /* ZCAL_WAIT_CNT */
+ 0x00000000, /* AUTO_CAL_INTERVAL */
+ 0x00000000, /* CFG_CLKTRIM_0 */
+ 0x00000000, /* CFG_CLKTRIM_1 */
+ 0x00000000, /* CFG_CLKTRIM_2 */
+ }
+ },
+ {
+ .rate = 125000, /* SDRAM frequency */
+ .regs = {
+ 0x00000008, /* RC */
+ 0x00000010, /* RFC */
+ 0x00000006, /* RAS */
+ 0x00000002, /* RP */
+ 0x00000004, /* R2W */
+ 0x00000004, /* W2R */
+ 0x00000001, /* R2P */
+ 0x0000000a, /* W2P */
+ 0x00000002, /* RD_RCD */
+ 0x00000002, /* WR_RCD */
+ 0x00000002, /* RRD */
+ 0x00000001, /* REXT */
+ 0x00000003, /* WDV */
+ 0x00000004, /* QUSE */
+ 0x00000003, /* QRST */
+ 0x00000009, /* QSAFE */
+ 0x0000000c, /* RDV */
+ 0x0000039f, /* REFRESH */
+ 0x00000000, /* BURST_REFRESH_NUM */
+ 0x00000003, /* PDEX2WR */
+ 0x00000003, /* PDEX2RD */
+ 0x00000002, /* PCHG2PDEN */
+ 0x00000002, /* ACT2PDEN */
+ 0x00000001, /* AR2PDEN */
+ 0x00000008, /* RW2PDEN */
+ 0x000000c8, /* TXSR */
+ 0x00000003, /* TCKE */
+ 0x00000007, /* TFAW */
+ 0x00000003, /* TRPAB */
+ 0x00000006, /* TCLKSTABLE */
+ 0x00000002, /* TCLKSTOP */
+ 0x00000000, /* TREFBW */
+ 0x00000000, /* QUSE_EXTRA */
+ 0x00000002, /* FBIO_CFG6 */
+ 0x00000000, /* ODT_WRITE */
+ 0x00000000, /* ODT_READ */
+ 0x00000083, /* FBIO_CFG5 */
+ 0x00510006, /* CFG_DIG_DLL */
+ 0x00000010, /* DLL_XFORM_DQS */
+ 0x00000008, /* DLL_XFORM_QUSE */
+ 0x00000000, /* ZCAL_REF_CNT */
+ 0x00000000, /* ZCAL_WAIT_CNT */
+ 0x00000000, /* AUTO_CAL_INTERVAL */
+ 0x00000000, /* CFG_CLKTRIM_0 */
+ 0x00000000, /* CFG_CLKTRIM_1 */
+ 0x00000000, /* CFG_CLKTRIM_2 */
+ }
+ },
+ {
+ .rate = 166500, /* SDRAM frequency */
+ .regs = {
+ 0x0000000a, /* RC */
+ 0x00000016, /* RFC */
+ 0x00000008, /* RAS */
+ 0x00000003, /* RP */
+ 0x00000004, /* R2W */
+ 0x00000004, /* W2R */
+ 0x00000002, /* R2P */
+ 0x0000000a, /* W2P */
+ 0x00000003, /* RD_RCD */
+ 0x00000003, /* WR_RCD */
+ 0x00000002, /* RRD */
+ 0x00000001, /* REXT */
+ 0x00000003, /* WDV */
+ 0x00000004, /* QUSE */
+ 0x00000003, /* QRST */
+ 0x00000009, /* QSAFE */
+ 0x0000000c, /* RDV */
+ 0x000004df, /* REFRESH */
+ 0x00000000, /* BURST_REFRESH_NUM */
+ 0x00000003, /* PDEX2WR */
+ 0x00000003, /* PDEX2RD */
+ 0x00000003, /* PCHG2PDEN */
+ 0x00000003, /* ACT2PDEN */
+ 0x00000001, /* AR2PDEN */
+ 0x00000009, /* RW2PDEN */
+ 0x000000c8, /* TXSR */
+ 0x00000003, /* TCKE */
+ 0x00000009, /* TFAW */
+ 0x00000004, /* TRPAB */
+ 0x00000006, /* TCLKSTABLE */
+ 0x00000002, /* TCLKSTOP */
+ 0x00000000, /* TREFBW */
+ 0x00000000, /* QUSE_EXTRA */
+ 0x00000002, /* FBIO_CFG6 */
+ 0x00000000, /* ODT_WRITE */
+ 0x00000000, /* ODT_READ */
+ 0x00000083, /* FBIO_CFG5 */
+ 0x004f0006, /* CFG_DIG_DLL */
+ 0x00000010, /* DLL_XFORM_DQS */
+ 0x00000008, /* DLL_XFORM_QUSE */
+ 0x00000000, /* ZCAL_REF_CNT */
+ 0x00000000, /* ZCAL_WAIT_CNT */
+ 0x00000000, /* AUTO_CAL_INTERVAL */
+ 0x00000000, /* CFG_CLKTRIM_0 */
+ 0x00000000, /* CFG_CLKTRIM_1 */
+ 0x00000000, /* CFG_CLKTRIM_2 */
+ }
+ },
+ {
+ .rate = 333000, /* SDRAM frequency */
+ .regs = {
+ 0x00000014, /* RC */
+ 0x0000002b, /* RFC */
+ 0x0000000f, /* RAS */
+ 0x00000005, /* RP */
+ 0x00000004, /* R2W */
+ 0x00000005, /* W2R */
+ 0x00000003, /* R2P */
+ 0x0000000a, /* W2P */
+ 0x00000005, /* RD_RCD */
+ 0x00000005, /* WR_RCD */
+ 0x00000004, /* RRD */
+ 0x00000001, /* REXT */
+ 0x00000003, /* WDV */
+ 0x00000004, /* QUSE */
+ 0x00000003, /* QRST */
+ 0x00000009, /* QSAFE */
+ 0x0000000c, /* RDV */
+ 0x000009ff, /* REFRESH */
+ 0x00000000, /* BURST_REFRESH_NUM */
+ 0x00000003, /* PDEX2WR */
+ 0x00000003, /* PDEX2RD */
+ 0x00000005, /* PCHG2PDEN */
+ 0x00000005, /* ACT2PDEN */
+ 0x00000001, /* AR2PDEN */
+ 0x0000000e, /* RW2PDEN */
+ 0x000000c8, /* TXSR */
+ 0x00000003, /* TCKE */
+ 0x00000011, /* TFAW */
+ 0x00000006, /* TRPAB */
+ 0x00000006, /* TCLKSTABLE */
+ 0x00000002, /* TCLKSTOP */
+ 0x00000000, /* TREFBW */
+ 0x00000000, /* QUSE_EXTRA */
+ 0x00000002, /* FBIO_CFG6 */
+ 0x00000000, /* ODT_WRITE */
+ 0x00000000, /* ODT_READ */
+ 0x00000083, /* FBIO_CFG5 */
+ 0x00380006, /* CFG_DIG_DLL */
+ 0x00000010, /* DLL_XFORM_DQS */
+ 0x00000008, /* DLL_XFORM_QUSE */
+ 0x00000000, /* ZCAL_REF_CNT */
+ 0x00000000, /* ZCAL_WAIT_CNT */
+ 0x00000000, /* AUTO_CAL_INTERVAL */
+ 0x00000000, /* CFG_CLKTRIM_0 */
+ 0x00000000, /* CFG_CLKTRIM_1 */
+ 0x00000000, /* CFG_CLKTRIM_2 */
+ }
+ },
+};
+
+/* Standard timings for Colibri T20 512 MB */
+static const struct tegra_emc_table colibri_t20_emc_tables_memphis_333Mhz[] = {
+ {
+ .rate = 83250, /* SDRAM frequency */
+ .regs = {
+ 0x00000005, /* RC */
+ 0x00000011, /* RFC */
+ 0x00000004, /* RAS */
+ 0x00000002, /* RP */
+ 0x00000004, /* R2W */
+ 0x00000004, /* W2R */
+ 0x00000001, /* R2P */
+ 0x0000000a, /* W2P */
+ 0x00000002, /* RD_RCD */
+ 0x00000002, /* WR_RCD */
+ 0x00000001, /* RRD */
+ 0x00000001, /* REXT */
+ 0x00000003, /* WDV */
+ 0x00000004, /* QUSE */
+ 0x00000003, /* QRST */
+ 0x00000009, /* QSAFE */
+ 0x0000000c, /* RDV */
+ 0x0000025f, /* REFRESH */
+ 0x00000000, /* BURST_REFRESH_NUM */
+ 0x00000003, /* PDEX2WR */
+ 0x00000003, /* PDEX2RD */
+ 0x00000002, /* PCHG2PDEN */
+ 0x00000002, /* ACT2PDEN */
+ 0x00000001, /* AR2PDEN */
+ 0x00000008, /* RW2PDEN */
+ 0x000000c8, /* TXSR */
+ 0x00000003, /* TCKE */
+ 0x00000005, /* TFAW */
+ 0x00000003, /* TRPAB */
+ 0x0000000c, /* TCLKSTABLE */
+ 0x00000002, /* TCLKSTOP */
+ 0x00000000, /* TREFBW */
+ 0x00000000, /* QUSE_EXTRA */
+ 0x00000002, /* FBIO_CFG6 */
+ 0x00000000, /* ODT_WRITE */
+ 0x00000000, /* ODT_READ */
+ 0x00000083, /* FBIO_CFG5 */
+ 0x00520006, /* CFG_DIG_DLL */
+ 0x00000010, /* DLL_XFORM_DQS */
+ 0x00000008, /* DLL_XFORM_QUSE */
+ 0x00000000, /* ZCAL_REF_CNT */
+ 0x00000000, /* ZCAL_WAIT_CNT */
+ 0x00000000, /* AUTO_CAL_INTERVAL */
+ 0x00000000, /* CFG_CLKTRIM_0 */
+ 0x00000000, /* CFG_CLKTRIM_1 */
+ 0x00000000, /* CFG_CLKTRIM_2 */
+ }
+ },
+ {
+ .rate = 125000, /* SDRAM frequency */
+ .regs = {
+ 0x00000008, /* RC */
+ 0x00000019, /* RFC */
+ 0x00000006, /* RAS */
+ 0x00000002, /* RP */
+ 0x00000004, /* R2W */
+ 0x00000004, /* W2R */
+ 0x00000001, /* R2P */
+ 0x0000000a, /* W2P */
+ 0x00000002, /* RD_RCD */
+ 0x00000002, /* WR_RCD */
+ 0x00000002, /* RRD */
+ 0x00000001, /* REXT */
+ 0x00000003, /* WDV */
+ 0x00000004, /* QUSE */
+ 0x00000003, /* QRST */
+ 0x00000009, /* QSAFE */
+ 0x0000000c, /* RDV */
+ 0x0000039f, /* REFRESH */
+ 0x00000000, /* BURST_REFRESH_NUM */
+ 0x00000003, /* PDEX2WR */
+ 0x00000003, /* PDEX2RD */
+ 0x00000002, /* PCHG2PDEN */
+ 0x00000002, /* ACT2PDEN */
+ 0x00000001, /* AR2PDEN */
+ 0x00000008, /* RW2PDEN */
+ 0x000000c8, /* TXSR */
+ 0x00000003, /* TCKE */
+ 0x00000007, /* TFAW */
+ 0x00000003, /* TRPAB */
+ 0x0000000c, /* TCLKSTABLE */
+ 0x00000002, /* TCLKSTOP */
+ 0x00000000, /* TREFBW */
+ 0x00000000, /* QUSE_EXTRA */
+ 0x00000002, /* FBIO_CFG6 */
+ 0x00000000, /* ODT_WRITE */
+ 0x00000000, /* ODT_READ */
+ 0x00000083, /* FBIO_CFG5 */
+ 0x00510006, /* CFG_DIG_DLL */
+ 0x00000010, /* DLL_XFORM_DQS */
+ 0x00000008, /* DLL_XFORM_QUSE */
+ 0x00000000, /* ZCAL_REF_CNT */
+ 0x00000000, /* ZCAL_WAIT_CNT */
+ 0x00000000, /* AUTO_CAL_INTERVAL */
+ 0x00000000, /* CFG_CLKTRIM_0 */
+ 0x00000000, /* CFG_CLKTRIM_1 */
+ 0x00000000, /* CFG_CLKTRIM_2 */
+ }
+ },
+ {
+ .rate = 166500, /* SDRAM frequency */
+ .regs = {
+ 0x0000000a, /* RC */
+ 0x00000021, /* RFC */
+ 0x00000008, /* RAS */
+ 0x00000003, /* RP */
+ 0x00000004, /* R2W */
+ 0x00000004, /* W2R */
+ 0x00000002, /* R2P */
+ 0x0000000a, /* W2P */
+ 0x00000003, /* RD_RCD */
+ 0x00000003, /* WR_RCD */
+ 0x00000002, /* RRD */
+ 0x00000001, /* REXT */
+ 0x00000003, /* WDV */
+ 0x00000004, /* QUSE */
+ 0x00000003, /* QRST */
+ 0x00000009, /* QSAFE */
+ 0x0000000c, /* RDV */
+ 0x000004df, /* REFRESH */
+ 0x00000000, /* BURST_REFRESH_NUM */
+ 0x00000003, /* PDEX2WR */
+ 0x00000003, /* PDEX2RD */
+ 0x00000003, /* PCHG2PDEN */
+ 0x00000003, /* ACT2PDEN */
+ 0x00000001, /* AR2PDEN */
+ 0x00000009, /* RW2PDEN */
+ 0x000000c8, /* TXSR */
+ 0x00000003, /* TCKE */
+ 0x00000009, /* TFAW */
+ 0x00000004, /* TRPAB */
+ 0x0000000c, /* TCLKSTABLE */
+ 0x00000002, /* TCLKSTOP */
+ 0x00000000, /* TREFBW */
+ 0x00000000, /* QUSE_EXTRA */
+ 0x00000002, /* FBIO_CFG6 */
+ 0x00000000, /* ODT_WRITE */
+ 0x00000000, /* ODT_READ */
+ 0x00000083, /* FBIO_CFG5 */
+ 0x004f0006, /* CFG_DIG_DLL */
+ 0x00000010, /* DLL_XFORM_DQS */
+ 0x00000008, /* DLL_XFORM_QUSE */
+ 0x00000000, /* ZCAL_REF_CNT */
+ 0x00000000, /* ZCAL_WAIT_CNT */
+ 0x00000000, /* AUTO_CAL_INTERVAL */
+ 0x00000000, /* CFG_CLKTRIM_0 */
+ 0x00000000, /* CFG_CLKTRIM_1 */
+ 0x00000000, /* CFG_CLKTRIM_2 */
+ }
+ },
+ {
+ .rate = 333000, /* SDRAM frequency */
+ .regs = {
+ 0x00000014, /* RC */
+ 0x00000041, /* RFC */
+ 0x0000000f, /* RAS */
+ 0x00000005, /* RP */
+ 0x00000004, /* R2W */
+ 0x00000005, /* W2R */
+ 0x00000003, /* R2P */
+ 0x0000000a, /* W2P */
+ 0x00000005, /* RD_RCD */
+ 0x00000005, /* WR_RCD */
+ 0x00000004, /* RRD */
+ 0x00000001, /* REXT */
+ 0x00000003, /* WDV */
+ 0x00000004, /* QUSE */
+ 0x00000003, /* QRST */
+ 0x00000009, /* QSAFE */
+ 0x0000000c, /* RDV */
+ 0x000009ff, /* REFRESH */
+ 0x00000000, /* BURST_REFRESH_NUM */
+ 0x00000003, /* PDEX2WR */
+ 0x00000003, /* PDEX2RD */
+ 0x00000005, /* PCHG2PDEN */
+ 0x00000005, /* ACT2PDEN */
+ 0x00000001, /* AR2PDEN */
+ 0x0000000e, /* RW2PDEN */
+ 0x000000c8, /* TXSR */
+ 0x00000003, /* TCKE */
+ 0x00000011, /* TFAW */
+ 0x00000006, /* TRPAB */
+ 0x0000000c, /* TCLKSTABLE */
+ 0x00000002, /* TCLKSTOP */
+ 0x00000000, /* TREFBW */
+ 0x00000000, /* QUSE_EXTRA */
+ 0x00000002, /* FBIO_CFG6 */
+ 0x00000000, /* ODT_WRITE */
+ 0x00000000, /* ODT_READ */
+ 0x00000083, /* FBIO_CFG5 */
+ 0x00380006, /* CFG_DIG_DLL */
+ 0x00000010, /* DLL_XFORM_DQS */
+ 0x00000008, /* DLL_XFORM_QUSE */
+ 0x00000000, /* ZCAL_REF_CNT */
+ 0x00000000, /* ZCAL_WAIT_CNT */
+ 0x00000000, /* AUTO_CAL_INTERVAL */
+ 0x00000000, /* CFG_CLKTRIM_0 */
+ 0x00000000, /* CFG_CLKTRIM_1 */
+ 0x00000000, /* CFG_CLKTRIM_2 */
+ }
+ },
+};
+
+static const struct tegra_emc_chip colibri_t20_emc_chips[] = {
+ {
+ .description = "Nanya NT5TU64M16GG 333MHz",
+ .table = colibri_t20_emc_tables_nanya_333Mhz,
+ .table_size = ARRAY_SIZE(colibri_t20_emc_tables_nanya_333Mhz)
+ },
+ {
+ .description = "MEMPHIS MEM2G16D2DABG 333MHz",
+ .table = colibri_t20_emc_tables_memphis_333Mhz,
+ .table_size = ARRAY_SIZE(colibri_t20_emc_tables_memphis_333Mhz)
+ },
+};
+
+int colibri_t20_emc_init(void)
+{
+ /* Assume less than 256 MB of kernel memory (e.g. physical memory minus
+ carveout and framebuffers) means we are running on a 256 MB module */
+ if (memblock_end_of_DRAM() < 256 * 1024 * 1024)
+ tegra_init_emc(&colibri_t20_emc_chips[0], 1);
+ else
+ tegra_init_emc(&colibri_t20_emc_chips[1], 1);
+
+ return 0;
+}
diff --git a/arch/arm/mach-tegra/board-colibri_t20-panel.c b/arch/arm/mach-tegra/board-colibri_t20-panel.c
new file mode 100644
index 000000000000..53e604838d72
--- /dev/null
+++ b/arch/arm/mach-tegra/board-colibri_t20-panel.c
@@ -0,0 +1,715 @@
+/*
+ * arch/arm/mach-tegra/board-colibri_t20-panel.c
+ *
+ * Copyright (c) 2012, Toradex, Inc.
+ *
+ * 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.
+ */
+
+#include <asm/mach-types.h>
+
+#include <linux/delay.h>
+#include <linux/earlysuspend.h>
+#include <linux/gpio.h>
+#include <linux/nvhost.h>
+#include <linux/nvmap.h>
+#include <linux/platform_device.h>
+#include <linux/pwm_backlight.h>
+#include <linux/regulator/consumer.h>
+#include <linux/resource.h>
+
+#include <mach/dc.h>
+#include <mach/fb.h>
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+
+#include "board.h"
+#include "board-colibri_t20.h"
+#include "devices.h"
+#include "gpio-names.h"
+#include "tegra2_host1x_devices.h"
+
+#ifndef COLIBRI_T20_VI
+#define colibri_t20_bl_enb TEGRA_GPIO_PT4 /* BL_ON */
+#endif
+#define colibri_t20_hdmi_hpd TEGRA_GPIO_PN7 /* HOTPLUG_DETECT */
+#ifdef IRIS
+#define iris_dac_psave TEGRA_GPIO_PA0 /* DAC_PSAVE# */
+#endif
+
+#ifdef CONFIG_TEGRA_DC
+static struct regulator *colibri_t20_hdmi_reg = NULL;
+static struct regulator *colibri_t20_hdmi_pll = NULL;
+#endif
+
+#ifndef COLIBRI_T20_VI
+static int colibri_t20_backlight_init(struct device *dev) {
+ int ret;
+
+ ret = gpio_request(colibri_t20_bl_enb, "BL_ON");
+ if (ret < 0)
+ return ret;
+
+ ret = gpio_direction_output(colibri_t20_bl_enb, 1);
+ if (ret < 0)
+ gpio_free(colibri_t20_bl_enb);
+
+ return ret;
+};
+
+static void colibri_t20_backlight_exit(struct device *dev) {
+ gpio_set_value(colibri_t20_bl_enb, 0);
+ gpio_free(colibri_t20_bl_enb);
+}
+
+static int colibri_t20_backlight_notify(struct device *dev, int brightness)
+{
+ struct platform_pwm_backlight_data *pdata = dev->platform_data;
+
+ gpio_set_value(colibri_t20_bl_enb, !!brightness);
+
+ /* Unified TFT interface displays (e.g. EDT ET070080DH6) LEDCTRL pin
+ with inverted behaviour (e.g. 0V brightest vs. 3.3V darkest)
+ Note: brightness polarity display model specific */
+ if (brightness) return pdata->max_brightness - brightness;
+ else return brightness;
+}
+
+static int colibri_t20_disp1_check_fb(struct device *dev, struct fb_info *info);
+
+static struct platform_pwm_backlight_data colibri_t20_backlight_data = {
+#ifndef MECS_TELLURIUM
+ .pwm_id = 0, /* PWM<A> (PMFM_PWM0) */
+#else
+ .pwm_id = 2, /* PWM<C> (PMFM_PWM2) */
+#endif
+ .max_brightness = 255,
+ .dft_brightness = 127,
+ .pwm_period_ns = 1000000, /* 1 kHz */
+ .init = colibri_t20_backlight_init,
+ .exit = colibri_t20_backlight_exit,
+ .notify = colibri_t20_backlight_notify,
+ /* Only toggle backlight on fb blank notifications for disp1 */
+ .check_fb = colibri_t20_disp1_check_fb,
+};
+
+static struct platform_device colibri_t20_backlight_device = {
+ .name = "pwm-backlight",
+ .id = -1,
+ .dev = {
+ .platform_data = &colibri_t20_backlight_data,
+ },
+};
+#endif /* !COLIBRI_T20_VI */
+
+#ifdef CONFIG_TEGRA_DC
+static int colibri_t20_panel_enable(void)
+{
+#ifdef IRIS
+ gpio_set_value(iris_dac_psave, 1);
+#endif
+ return 0;
+}
+
+static int colibri_t20_panel_disable(void)
+{
+#ifdef IRIS
+ gpio_set_value(iris_dac_psave, 0);
+#endif
+ return 0;
+}
+
+static int colibri_t20_hdmi_enable(void)
+{
+ if (!colibri_t20_hdmi_reg) {
+ colibri_t20_hdmi_reg = regulator_get(NULL, "avdd_hdmi"); /* LD07 */
+ if (IS_ERR_OR_NULL(colibri_t20_hdmi_reg)) {
+ pr_err("hdmi: couldn't get regulator avdd_hdmi\n");
+ colibri_t20_hdmi_reg = NULL;
+ return PTR_ERR(colibri_t20_hdmi_reg);
+ }
+ }
+ regulator_enable(colibri_t20_hdmi_reg);
+
+ if (!colibri_t20_hdmi_pll) {
+ colibri_t20_hdmi_pll = regulator_get(NULL, "avdd_hdmi_pll"); /* LD08 */
+ if (IS_ERR_OR_NULL(colibri_t20_hdmi_pll)) {
+ pr_err("hdmi: couldn't get regulator avdd_hdmi_pll\n");
+ colibri_t20_hdmi_pll = NULL;
+ regulator_disable(colibri_t20_hdmi_reg);
+ colibri_t20_hdmi_reg = NULL;
+ return PTR_ERR(colibri_t20_hdmi_pll);
+ }
+ }
+ regulator_enable(colibri_t20_hdmi_pll);
+ return 0;
+}
+
+static int colibri_t20_hdmi_disable(void)
+{
+ regulator_disable(colibri_t20_hdmi_reg);
+ regulator_disable(colibri_t20_hdmi_pll);
+ return 0;
+}
+
+static struct resource colibri_t20_disp1_resources[] = {
+ {
+ .name = "irq",
+ .start = INT_DISPLAY_GENERAL,
+ .end = INT_DISPLAY_GENERAL,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "regs",
+ .start = TEGRA_DISPLAY_BASE,
+ .end = TEGRA_DISPLAY_BASE + TEGRA_DISPLAY_SIZE-1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "fbmem",
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct resource colibri_t20_disp2_resources[] = {
+ {
+ .name = "irq",
+ .start = INT_DISPLAY_B_GENERAL,
+ .end = INT_DISPLAY_B_GENERAL,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "regs",
+ .start = TEGRA_DISPLAY2_BASE,
+ .end = TEGRA_DISPLAY2_BASE + TEGRA_DISPLAY2_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "fbmem",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "hdmi_regs",
+ .start = TEGRA_HDMI_BASE,
+ .end = TEGRA_HDMI_BASE + TEGRA_HDMI_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct tegra_dc_mode colibri_t20_panel_modes[] = {
+#ifdef TEGRA_FB_VGA
+ {
+ /* 640x480p 60hz: EIA/CEA-861-B Format 1 */
+ .pclk = 25175000, /* pixclock */
+ .h_ref_to_sync = 8,
+ .v_ref_to_sync = 2,
+ .h_sync_width = 96, /* hsync_len */
+ .v_sync_width = 2, /* vsync_len */
+ .h_back_porch = 48, /* left_margin */
+ .v_back_porch = 33, /* upper_margin */
+ .h_active = 640,
+ .v_active = 480,
+ .h_front_porch = 16, /* right_margin */
+ .v_front_porch = 10, /* lower_margin */
+ },
+#else /* TEGRA_FB_VGA */
+#ifndef CONFIG_ANDROID
+ {
+ /* 800x480@60 (e.g. EDT ET070080DH6) */
+ .pclk = 32460000,
+ .h_ref_to_sync = 1,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 64,
+ .v_sync_width = 3,
+ .h_back_porch = 128,
+ .v_back_porch = 22,
+ .h_active = 800,
+ .v_active = 480,
+ .h_front_porch = 64,
+ .v_front_porch = 20,
+ },
+ {
+ /* 800x600@60 */
+ .pclk = 39272727,
+ .h_sync_width = 80,
+ .v_sync_width = 2,
+ .h_back_porch = 160,
+ .v_back_porch = 21,
+ .h_active = 800,
+ .v_active = 600,
+ .h_front_porch = 16,
+ .v_front_porch = 1,
+ },
+ {
+ /* TouchRevolution Fusion 10 aka Chunghwa Picture Tubes
+ CLAA101NC05 10.1 inch 1024x600 single channel LVDS panel */
+ .pclk = 48000000,
+ .h_sync_width = 5,
+ .v_sync_width = 5,
+ .h_back_porch = 104,
+ .v_back_porch = 24,
+ .h_active = 1024,
+ .v_active = 600,
+ .h_front_porch = 43,
+ .v_front_porch = 20,
+ },
+ {
+ /* 1024x768@60 */
+//pll_c 76Hz
+ .pclk = 78800000,
+ .h_sync_width = 96,
+ .v_sync_width = 3,
+ .h_back_porch = 176,
+ .v_back_porch = 28,
+ .h_active = 1024,
+ .v_active = 768,
+ .h_front_porch = 16,
+ .v_front_porch = 1,
+ },
+ {
+ /* 1024x768@75 */
+ .pclk = 82000000,
+ .h_sync_width = 104,
+ .v_sync_width = 4,
+ .h_back_porch = 168,
+ .v_back_porch = 34,
+ .h_active = 1024,
+ .v_active = 768,
+ .h_front_porch = 64,
+ .v_front_porch = 3,
+ },
+#endif /* CONFIG_ANDROID */
+ {
+ /* 1280x720@70 */
+ .pclk = 86400000,
+ .h_ref_to_sync = 1,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 40,
+ .v_sync_width = 5,
+ .h_back_porch = 220,
+ .v_back_porch = 20,
+ .h_active = 1280,
+ .v_active = 720,
+ .h_front_porch = 110,
+ .v_front_porch = 5,
+//high active sync polarities
+ },
+ {
+ /* 1280x1024@60 */
+ .pclk = 108000000,
+// .h_ref_to_sync = 1,
+// .v_ref_to_sync = 1,
+ .h_sync_width = 144,
+ .v_sync_width = 3,
+ .h_back_porch = 248,
+ .v_back_porch = 38,
+ .h_active = 1280,
+ .v_active = 1024,
+ .h_front_porch = 16,
+ .v_front_porch = 1,
+//high active sync polarities
+ },
+ {
+ /* 1366x768@60 */
+ .pclk = 72072000,
+ .h_ref_to_sync = 11,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 58,
+ .v_sync_width = 4,
+ .h_back_porch = 58,
+ .v_back_porch = 4,
+ .h_active = 1366,
+ .v_active = 768,
+ .h_front_porch = 58,
+ .v_front_porch = 4,
+ },
+ {
+ /* 1600x1200@60 */
+ .pclk = 144000000,
+//[ 1.423072] tegradc tegradc.0: can't divide 216000000 clock to 162000000 -1/+9% 144000000 160380000 176580000
+// .pclk = 162000000,
+// .h_ref_to_sync = 1,
+// .v_ref_to_sync = 1,
+ .h_sync_width = 192,
+ .v_sync_width = 3,
+ .h_back_porch = 304,
+ .v_back_porch = 46,
+ .h_active = 1600,
+ .v_active = 1200,
+ .h_front_porch = 64,
+ .v_front_porch = 1,
+//high active sync polarities
+ },
+ {
+ /* 1680x1050@60 */
+ .pclk = 144000000,
+//[ 1.423139] tegradc tegradc.0: can't divide 216000000 clock to 147140000 -1/+9% 144000000 145668600 160382600
+// .pclk = 147140000,
+// .h_ref_to_sync = 1,
+// .v_ref_to_sync = 1,
+ .h_sync_width = 184,
+ .v_sync_width = 3,
+ .h_back_porch = 288,
+ .v_back_porch = 33,
+ .h_active = 1680,
+ .v_active = 1050,
+ .h_front_porch = 104,
+ .v_front_porch = 1,
+//high active vertical sync polarity
+ },
+ {
+ /* 1920x1080p 59.94/60hz EIA/CEA-861-B Format 16 */
+ .pclk = 144000000,
+//[ 3.361002] tegradc tegradc.0: can't divide 216000000 clock to 148500000 -1/+9% 144000000 147015000 161865000
+// .pclk = 148500000,
+ .h_ref_to_sync = 11,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 44,
+ .v_sync_width = 5,
+ .h_back_porch = 148,
+ .v_back_porch = 36,
+ .h_active = 1920,
+ .v_active = 1080,
+ .h_front_porch = 88,
+ .v_front_porch = 4,
+//high active sync polarities
+ },
+ {
+ .pclk = 144000000,
+//[ 3.371657] tegradc tegradc.0: can't divide 216000000 clock to 154000000 -1/+9% 144000000 152460000 167860000
+// .pclk = 154000000,
+ .h_ref_to_sync = 11,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 32,
+ .v_sync_width = 6,
+ .h_back_porch = 80,
+ .v_back_porch = 26,
+ .h_active = 1920,
+ .v_active = 1200,
+ .h_front_porch = 48,
+ .v_front_porch = 3,
+ },
+
+ /* portrait modes */
+
+ {
+ .pclk = 18000000,
+ .h_ref_to_sync = 8,
+ .v_ref_to_sync = 2,
+ .h_sync_width = 4,
+ .v_sync_width = 1,
+ .h_back_porch = 20,
+ .v_back_porch = 7,
+ .h_active = 480,
+ .v_active = 640,
+ .h_front_porch = 8,
+ .v_front_porch = 8,
+ },
+ {
+ .pclk = 10000000,
+ .h_ref_to_sync = 4,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 16,
+ .v_sync_width = 1,
+ .h_back_porch = 32,
+ .v_back_porch = 1,
+ .h_active = 540,
+ .v_active = 960,
+ .h_front_porch = 32,
+ .v_front_porch = 2,
+ },
+ {
+ .pclk = 61417000,
+ .h_ref_to_sync = 2,
+ .v_ref_to_sync = 2,
+ .h_sync_width = 4,
+ .v_sync_width = 4,
+ .h_back_porch = 100,
+ .v_back_porch = 14,
+ .h_active = 720,
+ .v_active = 1280,
+ .h_front_porch = 4,
+ .v_front_porch = 4,
+ },
+#endif /* TEGRA_FB_VGA */
+};
+
+static struct tegra_fb_data colibri_t20_fb_data = {
+ .win = 0,
+#ifdef TEGRA_FB_VGA
+ .xres = 640,
+ .yres = 480,
+#else /* TEGRA_FB_VGA */
+#ifndef CONFIG_ANDROID
+ .xres = 800,
+ .yres = 480,
+#else /* CONFIG_ANDROID */
+ .xres = 1280,
+ .yres = 720,
+#endif /* CONFIG_ANDROID */
+#endif /* TEGRA_FB_VGA */
+ .bits_per_pixel = 16,
+ .flags = TEGRA_FB_FLIP_ON_PROBE,
+};
+
+static struct tegra_fb_data colibri_t20_hdmi_fb_data = {
+ .win = 0,
+ .xres = 640,
+ .yres = 480,
+ .bits_per_pixel = 16,
+ .flags = TEGRA_FB_FLIP_ON_PROBE,
+};
+
+static struct tegra_dc_out_pin colibri_t20_dc_out_pins[] = {
+ {
+ .name = TEGRA_DC_OUT_PIN_H_SYNC,
+ .pol = TEGRA_DC_OUT_PIN_POL_LOW,
+ },
+ {
+ .name = TEGRA_DC_OUT_PIN_V_SYNC,
+ .pol = TEGRA_DC_OUT_PIN_POL_LOW,
+ },
+ {
+ .name = TEGRA_DC_OUT_PIN_PIXEL_CLOCK,
+ .pol = TEGRA_DC_OUT_PIN_POL_LOW,
+ },
+};
+
+static struct tegra_dc_out colibri_t20_disp1_out = {
+ .type = TEGRA_DC_OUT_RGB,
+// .parent_clk = "pll_c",
+
+ .max_pixclock = KHZ2PICOS(162000),
+
+ .align = TEGRA_DC_ALIGN_MSB,
+ .order = TEGRA_DC_ORDER_RED_BLUE,
+ .depth = 18,
+ .dither = TEGRA_DC_ORDERED_DITHER,
+
+ .modes = colibri_t20_panel_modes,
+ .n_modes = ARRAY_SIZE(colibri_t20_panel_modes),
+
+ .out_pins = colibri_t20_dc_out_pins,
+ .n_out_pins = ARRAY_SIZE(colibri_t20_dc_out_pins),
+
+ .enable = colibri_t20_panel_enable,
+ .disable = colibri_t20_panel_disable,
+};
+
+static struct tegra_dc_out colibri_t20_disp2_out = {
+ .type = TEGRA_DC_OUT_HDMI,
+ .flags = TEGRA_DC_OUT_HOTPLUG_HIGH,
+
+ .dcc_bus = 1,
+ .hotplug_gpio = colibri_t20_hdmi_hpd,
+
+ .max_pixclock = KHZ2PICOS(148500),
+
+ .align = TEGRA_DC_ALIGN_MSB,
+ .order = TEGRA_DC_ORDER_RED_BLUE,
+
+ .enable = colibri_t20_hdmi_enable,
+ .disable = colibri_t20_hdmi_disable,
+
+// .dither = TEGRA_DC_ORDERED_DITHER,
+};
+
+static struct tegra_dc_platform_data colibri_t20_disp1_pdata = {
+ .flags = TEGRA_DC_FLAG_ENABLED,
+ .default_out = &colibri_t20_disp1_out,
+ .fb = &colibri_t20_fb_data,
+};
+
+static struct tegra_dc_platform_data colibri_t20_disp2_pdata = {
+ .flags = TEGRA_DC_FLAG_ENABLED,
+ .default_out = &colibri_t20_disp2_out,
+ .fb = &colibri_t20_hdmi_fb_data,
+};
+
+static struct nvhost_device colibri_t20_disp1_device = {
+ .name = "tegradc",
+ .id = 0,
+ .resource = colibri_t20_disp1_resources,
+ .num_resources = ARRAY_SIZE(colibri_t20_disp1_resources),
+ .dev = {
+ .platform_data = &colibri_t20_disp1_pdata,
+ },
+};
+
+#ifndef COLIBRI_T20_VI
+static int colibri_t20_disp1_check_fb(struct device *dev, struct fb_info *info)
+{
+ return info->device == &colibri_t20_disp1_device.dev;
+}
+#endif /* !COLIBRI_T20_VI */
+
+static struct nvhost_device colibri_t20_disp2_device = {
+ .name = "tegradc",
+ .id = 1,
+ .resource = colibri_t20_disp2_resources,
+ .num_resources = ARRAY_SIZE(colibri_t20_disp2_resources),
+ .dev = {
+ .platform_data = &colibri_t20_disp2_pdata,
+ },
+};
+#else /* CONFIG_TEGRA_DC */
+static int colibri_t20_disp1_check_fb(struct device *dev, struct fb_info *info)
+{
+ return 0;
+}
+#endif /* CONFIG_TEGRA_DC */
+
+#if defined(CONFIG_TEGRA_NVMAP)
+static struct nvmap_platform_carveout colibri_t20_carveouts[] = {
+ [0] = NVMAP_HEAP_CARVEOUT_IRAM_INIT,
+ [1] = {
+ .name = "generic-0",
+ .usage_mask = NVMAP_HEAP_CARVEOUT_GENERIC,
+ .buddy_size = SZ_32K,
+ },
+};
+
+static struct nvmap_platform_data colibri_t20_nvmap_data = {
+ .carveouts = colibri_t20_carveouts,
+ .nr_carveouts = ARRAY_SIZE(colibri_t20_carveouts),
+};
+
+static struct platform_device colibri_t20_nvmap_device = {
+ .name = "tegra-nvmap",
+ .id = -1,
+ .dev = {
+ .platform_data = &colibri_t20_nvmap_data,
+ },
+};
+#endif /* CONFIG_TEGRA_NVMAP */
+
+static struct platform_device *colibri_t20_gfx_devices[] __initdata = {
+#if defined(CONFIG_TEGRA_NVMAP)
+ &colibri_t20_nvmap_device,
+#endif
+#ifndef COLIBRI_T20_VI
+#ifndef MECS_TELLURIUM
+ &tegra_pwfm0_device,
+#else
+ &tegra_pwfm2_device,
+#endif
+ &colibri_t20_backlight_device,
+#endif /* !COLIBRI_T20_VI */
+};
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+/* put early_suspend/late_resume handlers here for the display in order
+ * to keep the code out of the display driver, keeping it closer to upstream
+ */
+struct early_suspend colibri_t20_panel_early_suspender;
+
+static void colibri_t20_panel_early_suspend(struct early_suspend *h)
+{
+ /* power down LCD, add use a black screen for HDMI */
+ if (num_registered_fb > 0)
+ fb_blank(registered_fb[0], FB_BLANK_POWERDOWN);
+ if (num_registered_fb > 1)
+ fb_blank(registered_fb[1], FB_BLANK_NORMAL);
+#ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND
+ cpufreq_store_default_gov();
+ cpufreq_change_gov(cpufreq_conservative_gov);
+#endif
+}
+
+static void colibri_t20_panel_late_resume(struct early_suspend *h)
+{
+ unsigned i;
+#ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND
+ cpufreq_restore_default_gov();
+#endif
+ for (i = 0; i < num_registered_fb; i++)
+ fb_blank(registered_fb[i], FB_BLANK_UNBLANK);
+}
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+int __init colibri_t20_panel_init(void)
+{
+ int err;
+ struct resource __maybe_unused *res;
+ void __iomem *to_io;
+
+#ifdef IRIS
+ gpio_request(iris_dac_psave, "Iris DAC_PSAVE#");
+ gpio_direction_output(iris_dac_psave, 1);
+#endif /* IRIS */
+
+ /* enable hdmi hotplug gpio for hotplug detection */
+ gpio_request(colibri_t20_hdmi_hpd, "hdmi_hpd");
+ gpio_direction_input(colibri_t20_hdmi_hpd);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ colibri_t20_panel_early_suspender.suspend = colibri_t20_panel_early_suspend;
+ colibri_t20_panel_early_suspender.resume = colibri_t20_panel_late_resume;
+ colibri_t20_panel_early_suspender.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
+ register_early_suspend(&colibri_t20_panel_early_suspender);
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+#if defined(CONFIG_TEGRA_NVMAP)
+ colibri_t20_carveouts[1].base = tegra_carveout_start;
+ colibri_t20_carveouts[1].size = tegra_carveout_size;
+#endif /* CONFIG_TEGRA_NVMAP */
+
+#ifdef CONFIG_TEGRA_GRHOST
+ err = tegra2_register_host1x_devices();
+ if (err)
+ return err;
+#endif /* CONFIG_TEGRA_NVMAP */
+
+ err = platform_add_devices(colibri_t20_gfx_devices,
+ ARRAY_SIZE(colibri_t20_gfx_devices));
+
+#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC)
+ res = nvhost_get_resource_byname(&colibri_t20_disp1_device,
+ IORESOURCE_MEM, "fbmem");
+ res->start = tegra_fb_start;
+ res->end = tegra_fb_start + tegra_fb_size - 1;
+
+ res = nvhost_get_resource_byname(&colibri_t20_disp2_device,
+ IORESOURCE_MEM, "fbmem");
+ res->start = tegra_fb2_start;
+ res->end = tegra_fb2_start + tegra_fb2_size - 1;
+#endif /* CONFIG_TEGRA_GRHOST & CONFIG_TEGRA_DC */
+
+ /* Make sure LVDS framebuffer is cleared. */
+ to_io = ioremap(tegra_fb_start, tegra_fb_size);
+ if (to_io) {
+ memset(to_io, 0, tegra_fb_size);
+ iounmap(to_io);
+ } else pr_err("%s: Failed to map LVDS framebuffer\n", __func__);
+
+ /* Make sure HDMI framebuffer is cleared.
+ Note: this seems to fix a tegradc.1 initialisation race in case of
+ framebuffer console as well. */
+ to_io = ioremap(tegra_fb2_start, tegra_fb2_size);
+ if (to_io) {
+ memset(to_io, 0, tegra_fb2_size);
+ iounmap(to_io);
+ } else pr_err("%s: Failed to map HDMI framebuffer\n", __func__);
+
+#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC)
+ if (!err)
+ err = nvhost_device_register(&colibri_t20_disp1_device);
+
+ if (!err)
+ err = nvhost_device_register(&colibri_t20_disp2_device);
+#endif /* CONFIG_TEGRA_GRHOST & CONFIG_TEGRA_DC */
+
+ return err;
+}
diff --git a/arch/arm/mach-tegra/board-colibri_t20-pinmux.c b/arch/arm/mach-tegra/board-colibri_t20-pinmux.c
new file mode 100644
index 000000000000..1383f7d55459
--- /dev/null
+++ b/arch/arm/mach-tegra/board-colibri_t20-pinmux.c
@@ -0,0 +1,381 @@
+/*
+ * arch/arm/mach-tegra/board-colibri_t20-pinmux.c
+ *
+ * Copyright (C) 2011 Toradex, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <mach/pinmux.h>
+
+#include "board-colibri_t20.h"
+#include "gpio-names.h"
+
+#define DEFAULT_DRIVE(_name) \
+ { \
+ .pingroup = TEGRA_DRIVE_PINGROUP_##_name, \
+ .hsm = TEGRA_HSM_DISABLE, \
+ .schmitt = TEGRA_SCHMITT_ENABLE, \
+ .drive = TEGRA_DRIVE_DIV_1, \
+ .pull_down = TEGRA_PULL_31, \
+ .pull_up = TEGRA_PULL_31, \
+ .slew_rising = TEGRA_SLEW_SLOWEST, \
+ .slew_falling = TEGRA_SLEW_SLOWEST, \
+ }
+
+#define SET_DRIVE(_name, _hsm, _schmitt, _drive, _pulldn_drive, _pullup_drive, _pulldn_slew, _pullup_slew) \
+ { \
+ .pingroup = TEGRA_DRIVE_PINGROUP_##_name, \
+ .hsm = TEGRA_HSM_##_hsm, \
+ .schmitt = TEGRA_SCHMITT_##_schmitt, \
+ .drive = TEGRA_DRIVE_##_drive, \
+ .pull_down = TEGRA_PULL_##_pulldn_drive, \
+ .pull_up = TEGRA_PULL_##_pullup_drive, \
+ .slew_rising = TEGRA_SLEW_##_pulldn_slew, \
+ .slew_falling = TEGRA_SLEW_##_pullup_slew, \
+ }
+
+static __initdata struct tegra_drive_pingroup_config colibri_t20_drive_pinmux[] = {
+ DEFAULT_DRIVE(SDIO1),
+ DEFAULT_DRIVE(VI1),
+
+ SET_DRIVE(AO1, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+ SET_DRIVE(AT1, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+ SET_DRIVE(DBG, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+ SET_DRIVE(DDC, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+ SET_DRIVE(VI2, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+};
+
+static __initdata int colibri_t20_gpio_input_pinmux[] = {
+ /* SODIMM pin 152 tri-stating GMI_CLK as OWR can not be tri-stated */
+//currently reserved during board platform GPIO handling
+// TEGRA_GPIO_PK1, /* GMI_CLK multiplexed OWR */
+
+ /* Camera interface aka video input */
+#ifdef COLIBRI_T20_VI
+ TEGRA_GPIO_PA7, /* SDIO3_CMD multiplexed VI_D6 */
+ TEGRA_GPIO_PB4, /* SDIO3_DAT3 multiplexed VI_D7 */
+#else /* COLIBRI_T20_VI */
+ TEGRA_GPIO_PL4, /* VI_D6 multiplexed SDIO3_CMD */
+ TEGRA_GPIO_PL5, /* VI_D7 multiplexed SDIO3_DAT3 */
+#endif /* COLIBRI_T20_VI */
+
+ /* SODIMM pin 93 RDnWR */
+#if 1
+ TEGRA_GPIO_PW0, /* gated GMI_WR_N multiplexed LCD_CS1_N */
+#endif
+
+ /* SODIMM pin 44 L_BIAS configured as LCD data enable */
+#if 0
+ TEGRA_GPIO_PJ1, /* LCD_M1 multiplexed LCD_DE */
+#else
+ TEGRA_GPIO_PW1, /* LCD_DE multiplexed LCD_M1 */
+#endif
+
+ /* SODIMM pin 95 RDY */
+#if 1
+ TEGRA_GPIO_PI7, /* GMI_IORDY multiplexed GMI_WAIT */
+#else
+ TEGRA_GPIO_PI5, /* GMI_WAIT multiplexed GMI_IORDY */
+#endif
+
+ /* SODIMM pin 99 nPWE */
+#if 0
+ TEGRA_GPIO_PZ3, /* gated GMI_WR_N multiplexed LCD_WR_N */
+#endif
+
+ /* 24-bit LCD lines */
+#if 0
+ TEGRA_GPIO_PM2, /* SPI2_CS0_N multiplexed LCD_D18 */
+ TEGRA_GPIO_PM3, /* SPI2_SCK multiplexed LCD_D19 */
+ TEGRA_GPIO_PM4, /* SPI2_MISO multiplexed LCD_D20 */
+ TEGRA_GPIO_PM5, /* SPI2_MOSI multiplexed LCD_D21 */
+ TEGRA_GPIO_PM6, /* DAP2_DOUT multiplexed LCD_D22 */
+ TEGRA_GPIO_PM7, /* DAP2_DIN multiplexed LCD_D23 */
+#else
+ TEGRA_GPIO_PX3, /* LCD_D18 multiplexed SPI2_CS0_N */
+ TEGRA_GPIO_PX2, /* LCD_D19 multiplexed SPI2_SCK */
+ TEGRA_GPIO_PX1, /* LCD_D20 multiplexed SPI2_MISO */
+ TEGRA_GPIO_PX0, /* LCD_D21 multiplexed SPI2_MOSI */
+ TEGRA_GPIO_PA5, /* LCD_D22 multiplexed DAP2_DOUT */
+ TEGRA_GPIO_PA4, /* LCD_D23 multiplexed DAP2_DIN */
+#endif
+};
+
+static __initdata struct tegra_pingroup_config colibri_t20_pinmux[] = {
+/* tegra_pingroup tegra_mux_func tegra_pullupdown tegra_tristate
+ TRISTATE here means output driver is tri-stated, even configuring GPIO function won't override this.
+ Tristating would significantly reduce I/O power consumption. */
+ /* nRESET_OUT de-asserted further down below, GPIO I3, I4 and I6 */
+ {TEGRA_PINGROUP_ATA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_ATB, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* nCSx, AD0, AD1, AD2, AD3, AD4, AD5, AD6 and AD7, nWR, nOE, GPIO K0, K1, K2, K3 and K4 */
+ {TEGRA_PINGROUP_ATC, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* AD8, AD9, AD10 and AD11 */
+ {TEGRA_PINGROUP_ATD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* AD12, AD13, AD14 and AD15 */
+ {TEGRA_PINGROUP_ATE, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* WM9715L XTL_IN */
+//audio sync clk could be either AC97 or PLLA_OUT0
+//SYNC_CLK_DOUBLER_ENB: Enable audio sync clk doubler.
+// {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_AUDIO_SYNC, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_PLLA_OUT, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* USB3340 REFCLK */
+ {TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* CLK_32K_IN pin pull-up/down control only */
+ {TEGRA_PINGROUP_CK32, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_CRTP, TEGRA_MUX_CRT, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_CSUS, TEGRA_MUX_VI_SENSOR_CLK,TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* GPIO N0, N1, N2, N3 and USBC_DET */
+ {TEGRA_PINGROUP_DAP1, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* GPIO A2 and A3 */
+ {TEGRA_PINGROUP_DAP2, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* A13, A14, A15 and A16, GPIO P4, P5, P6 and P7 */
+ {TEGRA_PINGROUP_DAP4, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* DDC pins pulled up to avoid issues if no FFC cable is connected to X3 */
+ {TEGRA_PINGROUP_DDC, TEGRA_MUX_I2C2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
+ /* Pull-up/down control only */
+ {TEGRA_PINGROUP_DDRC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* GPIO D5 */
+ {TEGRA_PINGROUP_DTA, TEGRA_MUX_VI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* GPIO T2 and T3 as KEY_FIND */
+#ifdef CONFIG_KEYBOARD_GPIO
+ {TEGRA_PINGROUP_DTB, TEGRA_MUX_VI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
+#else
+ {TEGRA_PINGROUP_DTB, TEGRA_MUX_VI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+#endif
+ {TEGRA_PINGROUP_DTC, TEGRA_MUX_VI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* GPIO L0, L1, L2, L3, L6 and L7
+ GPIO L4 and L5 multiplexed with PWM<A> and PWM<D> */
+ {TEGRA_PINGROUP_DTD, TEGRA_MUX_VI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* AX88772B V_BUS, WM9715L PENDOWN, GPIO A0, BB4 as KEY_VOLUMEUP and BB5 as KEY_VOLUMEDOWN */
+#ifdef CONFIG_KEYBOARD_GPIO
+ {TEGRA_PINGROUP_DTE, TEGRA_MUX_RSVD, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
+#else
+ {TEGRA_PINGROUP_DTE, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+#endif
+ /* GPIO BB2 as KEY_BACK and BB3 as KEY_HOME */
+#ifdef CONFIG_KEYBOARD_GPIO
+ {TEGRA_PINGROUP_DTF, TEGRA_MUX_I2C3, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
+#else
+ {TEGRA_PINGROUP_DTF, TEGRA_MUX_I2C3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+#endif
+ {TEGRA_PINGROUP_GMA, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* MM_CD */
+ {TEGRA_PINGROUP_GMB, TEGRA_MUX_GMI_INT, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* BT_TXD, BT_RXD, BT_CTS and BT_RTS, GPIO K7 */
+ {TEGRA_PINGROUP_GMC, TEGRA_MUX_UARTD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_GMD, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* GPIO AA4, AA5, AA6 and AA7 */
+#ifndef SDHCI_8BIT
+ {TEGRA_PINGROUP_GME, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+#else
+ {TEGRA_PINGROUP_GME, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+#endif
+ /* A6, A7, A8, A9, A10, A11 and A12, GPIO U6 */
+ {TEGRA_PINGROUP_GPU, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_GPU7, TEGRA_MUX_RTCK, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* AX88772B RESET_N and EXTWAKEUP_N */
+ {TEGRA_PINGROUP_GPV, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* HDMI HOTPLUG_DETECT */
+ {TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_I2CP, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* A0 */
+ {TEGRA_PINGROUP_IRRX, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* A1 */
+ {TEGRA_PINGROUP_IRTX, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_KBCA, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_KBCB, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_KBCC, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_KBCD, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_KBCE, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_KBCF, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* GPIO N4 */
+ {TEGRA_PINGROUP_LCSN, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LD0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LD1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LD10, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LD11, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LD12, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LD13, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LD14, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LD15, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LD16, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LD17, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LD2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LD3, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LD4, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LD5, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LD6, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LD7, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LD8, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LD9, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* GPIO N6 */
+ {TEGRA_PINGROUP_LDC, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LDI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LHP0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LHP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LHP2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LHS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* Multiplexed RDnWR */
+ {TEGRA_PINGROUP_LM0, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LM1, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LPP, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* GPIO B2 */
+ {TEGRA_PINGROUP_LPW0, TEGRA_MUX_DISPLAYB, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LPW1, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LPW2, TEGRA_MUX_DISPLAYB, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LSC0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* Multiplexed gated nPWE */
+ {TEGRA_PINGROUP_LSC1, TEGRA_MUX_DISPLAYB, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* GPIO Z4 */
+ {TEGRA_PINGROUP_LSCK, TEGRA_MUX_DISPLAYB, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* GPIO N5 */
+ {TEGRA_PINGROUP_LSDA, TEGRA_MUX_DISPLAYB, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* GPIO Z2 */
+ {TEGRA_PINGROUP_LSDI, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LSPI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* THERMD_ALERT */
+ {TEGRA_PINGROUP_LVP0, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LVP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LVS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* OWR multiplexed with GMI_CLK */
+ {TEGRA_PINGROUP_OWC, TEGRA_MUX_OWR, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_PMC, TEGRA_MUX_PWR_ON, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+
+ /* Following five are for specific PMC pin pull-up/down control only */
+ /* CLK_32K_OUT */
+ {TEGRA_PINGROUP_PMCA, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* SYS_CLK_REQ */
+ {TEGRA_PINGROUP_PMCB, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* CORE_PWR_REQ */
+ {TEGRA_PINGROUP_PMCC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* CPU_PWR_REQ */
+ {TEGRA_PINGROUP_PMCD, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* PWR_INT_N pulled up */
+ {TEGRA_PINGROUP_PMCE, TEGRA_MUX_NONE, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
+
+ /* Gating RDnWR, nPWE through GPIOs further down below */
+ {TEGRA_PINGROUP_PTA, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_RM, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* PWM3 */
+ /* PWM<D> multiplexed with CIF_DD<6> */
+ {TEGRA_PINGROUP_SDB, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* GPIO B6 and B7, PWM0 and PWM1 */
+ /* PWM<A> multiplexed with CIF_DD<7> */
+ {TEGRA_PINGROUP_SDC, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* PWM2 */
+ {TEGRA_PINGROUP_SDD, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_SDIO1, TEGRA_MUX_UARTA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+
+ /* SPI4 */
+ {TEGRA_PINGROUP_SLXA, TEGRA_MUX_SPI4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_SLXC, TEGRA_MUX_SPI4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_SLXD, TEGRA_MUX_SPI4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_SLXK, TEGRA_MUX_SPI4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+
+ /* GPIO K6 as KEY_MENU multiplexed ACC1_DETECT */
+#ifdef CONFIG_KEYBOARD_GPIO
+ {TEGRA_PINGROUP_SPDI, TEGRA_MUX_RSVD, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
+#else
+ {TEGRA_PINGROUP_SPDI, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+#endif
+ /* GPIO K5 multiplexed USB1_VBUS */
+ {TEGRA_PINGROUP_SPDO, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+
+ /* X0, X1, X2, X3, X4, X5, X6 and X7 */
+ {TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_SPIB, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_SPID, TEGRA_MUX_SPI1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_SPIE, TEGRA_MUX_SPI1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_SPIF, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+
+ /* USBH_PEN */
+ {TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* USBH_OC */
+ {TEGRA_PINGROUP_SPIH, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+
+ /* ULPI data pins pulled up like on NVIDIA's Ventana reference platform */
+ {TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_UAB, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
+
+ /* WM9715L RESET#, USB3340 RESETB, WM9715L GENIRQ and GPIO V3 as KEY_POWER */
+#ifdef CONFIG_KEYBOARD_GPIO
+ {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+#else
+ {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+#endif
+ /* STD_TXD and STD_RXD */
+ {TEGRA_PINGROUP_UAD, TEGRA_MUX_IRDA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* A2 and A3 */
+ {TEGRA_PINGROUP_UCA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* A4 and A5 */
+ {TEGRA_PINGROUP_UCB, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_UDA, TEGRA_MUX_ULPI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+
+ /* Following two are for specific DDR pin pull-up/down control only */
+ {TEGRA_PINGROUP_XM2C, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+};
+
+#if 0
+/* 32-bit wide data and 28-bit wide address bus, more chip selects */
+static __initdata struct tegra_pingroup_config colibri_t20_widebus_pinmux[] = {
+ /* D28, D29, D30 and D31 */
+ {TEGRA_PINGROUP_DAP1, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* AD20, AD21, AD22 and AD23 */
+ {TEGRA_PINGROUP_GMA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* AD16, AD17, AD18 and AD19 */
+ {TEGRA_PINGROUP_GMC, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ /* nCS0 and nCS1 */
+ {TEGRA_PINGROUP_GMD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+#ifndef SDHCI_8BIT
+ /* AD24, AD25, AD26 and AD27 */
+ {TEGRA_PINGROUP_GME, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+#endif
+};
+#endif
+
+int __init colibri_t20_pinmux_init(void)
+{
+ int i;
+
+ tegra_pinmux_config_table(colibri_t20_pinmux, ARRAY_SIZE(colibri_t20_pinmux));
+ tegra_drive_pinmux_config_table(colibri_t20_drive_pinmux,
+ ARRAY_SIZE(colibri_t20_drive_pinmux));
+
+ /* configure GPIO inputs on multiplexed balls to tri-state specific functions
+ instead of tri-stating whole groups */
+ for(i = 0; i < ARRAY_SIZE(colibri_t20_gpio_input_pinmux); i++) {
+ gpio_request(colibri_t20_gpio_input_pinmux[i], "function tri-stated");
+ gpio_direction_input(colibri_t20_gpio_input_pinmux[i]);
+ }
+
+ /* un-resetting external devices via SODIMM pin 87 nRESET_OUT */
+ gpio_request(TEGRA_GPIO_PI4, "SODIMM 87 nRESET_OUT");
+ gpio_direction_output(TEGRA_GPIO_PI4, 1);
+
+ /* tri-stating GMI_WR_N on SODIMM pin 99 nPWE */
+ gpio_request(TEGRA_GPIO_PT5, "no GMI_WR_N on 99");
+ gpio_direction_output(TEGRA_GPIO_PT5, 1);
+
+ /* not tri-stating GMI_WR_N on SODIMM pin 93 RDnWR */
+ gpio_request(TEGRA_GPIO_PT6, "GMI_WR_N on 93 RDnWR");
+ gpio_direction_output(TEGRA_GPIO_PT6, 0);
+
+ return 0;
+}
diff --git a/arch/arm/mach-tegra/board-colibri_t20-power.c b/arch/arm/mach-tegra/board-colibri_t20-power.c
new file mode 100644
index 000000000000..fb6e8e8e1bf3
--- /dev/null
+++ b/arch/arm/mach-tegra/board-colibri_t20-power.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2011 Toradex, Inc.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/mfd/tps6586x.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/machine.h>
+
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+
+#include "board-colibri_t20.h"
+#include "board.h"
+#include "fuse.h"
+#include "gpio-names.h"
+#include "pm.h"
+
+#define PMC_CTRL 0x0
+#define PMC_CTRL_INTR_LOW (1 << 17)
+
+/* VDD_CORE_1.2V */
+static struct regulator_consumer_supply tps658621_sm0_supply[] = {
+ REGULATOR_SUPPLY("vdd_core", NULL),
+};
+
+/* VDD_CPU_1.0V */
+static struct regulator_consumer_supply tps658621_sm1_supply[] = {
+ REGULATOR_SUPPLY("vdd_cpu", NULL),
+};
+
+/* VDD_DDR2_1.8V, LAN AX88772B VCC18A_ and NAND K9K8G08U0B VCC */
+static struct regulator_consumer_supply tps658621_sm2_supply[] = {
+ REGULATOR_SUPPLY("vdd_sm2", NULL),
+};
+
+/* unused */
+static struct regulator_consumer_supply tps658621_ldo0_supply[] = {
+ REGULATOR_SUPPLY("vdd_ldo0", NULL),
+};
+
+/* AVDD_PLL_1.1V and +3.3V_ENABLE_N switching via FET: AVDD_AUDIO_S and +3.3V:
+SMSC USB3340 VBAT, VDDIO
+VCC_LAN
+VDDIO_AUDIO
+VDDIO_BB
+VDDIO_LCD
+VDDIO_NAND
+VDDIO_SDIO
+VDDIO_UART
+VDDIO_VI */
+static struct regulator_consumer_supply tps658621_ldo1_supply[] = {
+ REGULATOR_SUPPLY("vdd_ldo1", NULL),
+ REGULATOR_SUPPLY("avdd_pll", NULL),
+};
+
+/* VDD_RTC_1.2V */
+static struct regulator_consumer_supply tps658621_ldo2_supply[] = {
+ REGULATOR_SUPPLY("vdd_ldo2", NULL),
+ REGULATOR_SUPPLY("vdd_rtc", NULL),
+ REGULATOR_SUPPLY("vdd_aon", NULL),
+};
+
+/* unused */
+static struct regulator_consumer_supply tps658621_ldo3_supply[] = {
+ REGULATOR_SUPPLY("vdd_ldo3", NULL),
+};
+
+/* VDDIO_SYS_1.8V and VDDIO_PMIC */
+static struct regulator_consumer_supply tps658621_ldo4_supply[] = {
+ REGULATOR_SUPPLY("vdd_ldo4", NULL),
+ REGULATOR_SUPPLY("avdd_osc", NULL),
+};
+
+/* +3.3V_USB switched via FET: AVDD_USB,
+ +3.3V_FUSE switched via FET on FUSE_EN# (PMIC GPIO3)*/
+static struct regulator_consumer_supply tps658621_ldo5_supply[] = {
+ REGULATOR_SUPPLY("vdd_ldo5", NULL),
+ REGULATOR_SUPPLY("avdd_usb", NULL),
+ REGULATOR_SUPPLY("avdd_usb_pll", NULL),
+ /* fuse via separate GPIO FET (FUSE_ENABLE_N) */
+ REGULATOR_SUPPLY("vdd_fuse", NULL),
+};
+
+/* AVDD_VDAC_2.85V */
+static struct regulator_consumer_supply tps658621_ldo6_supply[] = {
+ /* Off after boot, needs to be explicitly turned on! */
+ REGULATOR_SUPPLY("vdd_ldo6", NULL),
+ REGULATOR_SUPPLY("avdd_vdac", NULL),
+};
+
+/* AVDD_HDMI_3.3V */
+static struct regulator_consumer_supply tps658621_ldo7_supply[] = {
+ REGULATOR_SUPPLY("vdd_ldo7", NULL),
+ REGULATOR_SUPPLY("avdd_hdmi", NULL),
+};
+
+/* AVDD_HDMI_PLL_1.8V */
+static struct regulator_consumer_supply tps658621_ldo8_supply[] = {
+ REGULATOR_SUPPLY("vdd_ldo8", NULL),
+ REGULATOR_SUPPLY("avdd_hdmi_pll", NULL),
+};
+
+/* VDDIO_RX_DDR_2.85V */
+static struct regulator_consumer_supply tps658621_ldo9_supply[] = {
+ REGULATOR_SUPPLY("vdd_ldo9", NULL),
+ REGULATOR_SUPPLY("vdd_ddr_rx", NULL),
+};
+
+static struct tps6586x_settings sm0_config = {
+ .sm_pwm_mode = PWM_DEFAULT_VALUE,
+ .slew_rate = SLEW_RATE_3520UV_PER_SEC,
+};
+
+static struct tps6586x_settings sm1_config = {
+ /*
+ * Current TPS6586x is known for having a voltage glitch if current load
+ * changes from low to high in auto PWM/PFM mode for CPU's Vdd line.
+ */
+ .sm_pwm_mode = PWM_ONLY,
+ .slew_rate = SLEW_RATE_3520UV_PER_SEC,
+};
+
+#define REGULATOR_INIT(_id, _minmv, _maxmv, on, config) \
+ { \
+ .constraints = { \
+ .min_uV = (_minmv)*1000, \
+ .max_uV = (_maxmv)*1000, \
+ .valid_modes_mask = (REGULATOR_MODE_NORMAL | \
+ REGULATOR_MODE_STANDBY), \
+ .valid_ops_mask = (REGULATOR_CHANGE_MODE | \
+ REGULATOR_CHANGE_STATUS | \
+ REGULATOR_CHANGE_VOLTAGE), \
+ .always_on = on, \
+ .apply_uV = 1, \
+ }, \
+ .num_consumer_supplies = ARRAY_SIZE(tps658621_##_id##_supply),\
+ .consumer_supplies = tps658621_##_id##_supply, \
+ .driver_data = config, \
+ }
+
+#define ON 1
+#define OFF 0
+
+static struct regulator_init_data sm0_data = REGULATOR_INIT(sm0, 725, 1500, ON, &sm0_config);
+static struct regulator_init_data sm1_data = REGULATOR_INIT(sm1, 725, 1500, ON, &sm1_config);
+static struct regulator_init_data sm2_data = REGULATOR_INIT(sm2, 1700, 2475, ON, NULL);
+static struct regulator_init_data ldo0_data = REGULATOR_INIT(ldo0, 1200, 3300, OFF, NULL);
+static struct regulator_init_data ldo1_data = REGULATOR_INIT(ldo1, 725, 1500, ON, NULL);
+static struct regulator_init_data ldo2_data = REGULATOR_INIT(ldo2, 725, 1500, OFF, NULL);
+static struct regulator_init_data ldo3_data = REGULATOR_INIT(ldo3, 1250, 3300, OFF, NULL);
+static struct regulator_init_data ldo4_data = REGULATOR_INIT(ldo4, 1700, 2475, ON, NULL);
+static struct regulator_init_data ldo5_data = REGULATOR_INIT(ldo5, 1250, 3300, ON, NULL);
+static struct regulator_init_data ldo6_data = REGULATOR_INIT(ldo6, 2850, 2850, OFF, NULL);
+static struct regulator_init_data ldo7_data = REGULATOR_INIT(ldo7, 3300, 3300, OFF, NULL);
+static struct regulator_init_data ldo8_data = REGULATOR_INIT(ldo8, 1800, 1800, OFF, NULL);
+static struct regulator_init_data ldo9_data = REGULATOR_INIT(ldo9, 1250, 3300, OFF, NULL);
+
+static struct tps6586x_rtc_platform_data rtc_data = {
+ .irq = TEGRA_NR_IRQS + TPS6586X_INT_RTC_ALM1,
+ .start = {
+ .year = 2009,
+ .month = 1,
+ .day = 1,
+ },
+ .cl_sel = TPS6586X_RTC_CL_SEL_1_5PF /* use lowest (external 20pF cap) */
+};
+
+#define TPS_REG(_id, _data) \
+ { \
+ .id = TPS6586X_ID_##_id, \
+ .name = "tps6586x-regulator", \
+ .platform_data = _data, \
+ }
+
+static struct tps6586x_subdev_info tps_devs[] = {
+ TPS_REG(SM_0, &sm0_data),
+ TPS_REG(SM_1, &sm1_data),
+ TPS_REG(SM_2, &sm2_data),
+ TPS_REG(LDO_0, &ldo0_data),
+ TPS_REG(LDO_1, &ldo1_data),
+ TPS_REG(LDO_2, &ldo2_data),
+ TPS_REG(LDO_3, &ldo3_data),
+ TPS_REG(LDO_4, &ldo4_data),
+ TPS_REG(LDO_5, &ldo5_data),
+ TPS_REG(LDO_6, &ldo6_data),
+ TPS_REG(LDO_7, &ldo7_data),
+ TPS_REG(LDO_8, &ldo8_data),
+ TPS_REG(LDO_9, &ldo9_data),
+ {
+ .id = 0,
+ .name = "tps6586x-rtc",
+ .platform_data = &rtc_data,
+ },
+};
+
+static struct tps6586x_platform_data tps_platform = {
+ .irq_base = TPS6586X_INT_BASE,
+ .num_subdevs = ARRAY_SIZE(tps_devs),
+ .subdevs = tps_devs,
+ .gpio_base = TPS6586X_GPIO_BASE,
+ /* full PMIC power off decreases power consumption
+ but reset won't force a re-boot anymore */
+ .use_power_off = true,
+};
+
+static struct i2c_board_info __initdata colibri_t20_regulators[] = {
+ {
+ I2C_BOARD_INFO("tps6586x", 0x34),
+ .irq = INT_EXTERNAL_PMU,
+ .platform_data = &tps_platform,
+ },
+};
+
+static void colibri_t20_board_suspend(int lp_state, enum suspend_stage stg)
+{
+ if ((lp_state == TEGRA_SUSPEND_LP1) && (stg == TEGRA_SUSPEND_BEFORE_CPU))
+ tegra_console_uart_suspend();
+}
+
+static void colibri_t20_board_resume(int lp_state, enum resume_stage stg)
+{
+ if ((lp_state == TEGRA_SUSPEND_LP1) && (stg == TEGRA_RESUME_AFTER_CPU))
+ tegra_console_uart_resume();
+}
+
+static struct tegra_suspend_platform_data colibri_t20_suspend_data = {
+ /*
+ * Check power on time and crystal oscillator start time
+ * for appropriate settings.
+ */
+ .cpu_timer = 2000,
+ .cpu_off_timer = 100,
+ .suspend_mode = TEGRA_SUSPEND_LP1,
+ .core_timer = 0x7e7e,
+ .core_off_timer = 0xf,
+ .corereq_high = false,
+ .sysclkreq_high = true,
+ .board_suspend = colibri_t20_board_suspend,
+ .board_resume = colibri_t20_board_resume,
+};
+
+int __init colibri_t20_regulator_init(void)
+{
+ void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
+ u32 pmc_ctrl;
+#if 0
+//currently LP0 is anyway not supported
+ void __iomem *chip_id = IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804;
+ u32 minor;
+
+ minor = (readl(chip_id) >> 16) & 0xf;
+ /* A03 (but not A03p) chips do not support LP0 */
+ if (minor == 3 && !(tegra_spare_fuse(18) || tegra_spare_fuse(19)))
+ colibri_t20_suspend_data.suspend_mode = TEGRA_SUSPEND_LP1;
+#endif
+
+ /* configure the power management controller to trigger PMU
+ * interrupts when low */
+ pmc_ctrl = readl(pmc + PMC_CTRL);
+ writel(pmc_ctrl | PMC_CTRL_INTR_LOW, pmc + PMC_CTRL);
+
+ i2c_register_board_info(4, colibri_t20_regulators, ARRAY_SIZE(colibri_t20_regulators));
+
+//none of the Tegra 2 boards currently do this
+// regulator_has_full_constraints();
+
+ tegra_init_suspend(&colibri_t20_suspend_data);
+
+ return 0;
+}
diff --git a/arch/arm/mach-tegra/board-colibri_t20.c b/arch/arm/mach-tegra/board-colibri_t20.c
new file mode 100644
index 000000000000..6f2c91852b12
--- /dev/null
+++ b/arch/arm/mach-tegra/board-colibri_t20.c
@@ -0,0 +1,1346 @@
+/*
+ * arch/arm/mach-tegra/board-colibri_t20.c
+ *
+ * Copyright (c) 2011-2013 Toradex, Inc.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <linux/clk.h>
+#include <linux/colibri_usb.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/gpio_keys.h>
+#include <linux/i2c.h>
+#include <linux/i2c-tegra.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/leds_pwm.h>
+#include <linux/lm95245.h>
+#include <linux/memblock.h>
+#include <linux/platform_data/tegra_usb.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <linux/serial_8250.h>
+#include <linux/spi/spi.h>
+#include <linux/tegra_uart.h>
+#include <linux/wm97xx.h>
+
+#include <mach/gpio.h>
+#include <mach/nand.h>
+#include <mach/sdhci.h>
+#include <mach/usb_phy.h>
+#include <mach/w1.h>
+
+#include "board-colibri_t20.h"
+#include "board.h"
+#include "clock.h"
+#include "cpu-tegra.h"
+#include "devices.h"
+#include "gpio-names.h"
+#include "pm.h"
+#include "wakeups-t2.h"
+
+/* ADC */
+
+static struct wm97xx_batt_pdata colibri_t20_adc_pdata = {
+ .batt_aux = WM97XX_AUX_ID1, /* AD0 - ANALOG_IN0 */
+ .temp_aux = WM97XX_AUX_ID2, /* AD1 - ANALOG_IN1 */
+ .charge_gpio = -1,
+ .batt_div = 1,
+ .batt_mult = 1,
+ .temp_div = 1,
+ .temp_mult = 1,
+ .batt_name = "colibri_t20-analog_inputs",
+};
+
+static struct wm97xx_pdata colibri_t20_wm97xx_pdata = {
+ .batt_pdata = &colibri_t20_adc_pdata,
+};
+
+/* Audio */
+
+static struct platform_device colibri_t20_audio_device = {
+ .name = "colibri_t20-snd-wm9715l",
+ .id = 0,
+};
+
+void *get_colibri_t20_audio_platform_data(void)
+{
+ return &colibri_t20_wm97xx_pdata;
+}
+EXPORT_SYMBOL(get_colibri_t20_audio_platform_data);
+
+#ifdef CONFIG_TEGRA_CAMERA
+/* Camera */
+static struct platform_device tegra_camera = {
+ .name = "tegra_camera",
+ .id = -1,
+};
+#endif /* CONFIG_TEGRA_CAMERA */
+
+/* Clocks */
+static struct tegra_clk_init_table colibri_t20_clk_init_table[] __initdata = {
+ /* name parent rate enabled */
+ {"blink", "clk_32k", 32768, false},
+ /* SMSC3340 REFCLK 24 MHz */
+ {"pll_p_out4", "pll_p", 24000000, true},
+ {"pwm", "clk_m", 0, false},
+ {"spdif_out", "pll_a_out0", 0, false},
+
+//required otherwise getting disabled by "Disabling clocks left on by
+//bootloader" stage
+ {"uarta", "pll_p", 216000000, true},
+
+//required otherwise uses pll_p_out4 as parent and changing its rate to 72 MHz
+ {"sclk", "pll_p_out3", 108000000, true},
+
+ /* AC97 incl. touch (note: unfortunately no clk source mux exists) */
+ {"ac97", "pll_a_out0", 24576000, true},
+
+ /* WM9715L XTL_IN 24.576 MHz */
+//[ 0.372722] Unable to set parent pll_a_out0 of clock cdev1: -38
+// {"cdev1", "pll_a_out0", 24576000, true},
+// {"pll_a_out0", "pll_a", 24576000, true},
+
+ {"vde", "pll_c", 240000000, false},
+
+ {"ndflash", "pll_p", 108000000, false},
+
+//[ 2.284308] kernel BUG at drivers/spi/spi-tegra.c:254!
+//[ 2.289454] Unable to handle kernel NULL pointer dereference at virtual
+// address 00000000
+ {"sbc4", "pll_p", 12000000, false},
+
+ {NULL, NULL, 0, 0},
+};
+
+/* GPIO */
+
+static struct gpio colibri_t20_gpios[] = {
+//conflicts with CAN interrupt on Colibri Evaluation Board and MECS Tellurium
+//xPOD1 CAN
+//conflicts with DAC_PSAVE# on Iris
+#ifndef IRIS
+ {TEGRA_GPIO_PA0, GPIOF_IN, "SODIMM pin 73"},
+#endif
+ {TEGRA_GPIO_PA2, GPIOF_IN, "SODIMM pin 186"},
+ {TEGRA_GPIO_PA3, GPIOF_IN, "SODIMM pin 184"},
+//multiplexed VI_D6
+ {TEGRA_GPIO_PA7, GPIOF_IN, "SODIMM pin 67"},
+ {TEGRA_GPIO_PB2, GPIOF_IN, "SODIMM pin 154"},
+//multiplexed VI_D7
+ {TEGRA_GPIO_PB4, GPIOF_IN, "SODIMM pin 59"},
+//conflicts with MECS Tellurium xPOD2 SSPCLK2
+ {TEGRA_GPIO_PB6, GPIOF_IN, "SODIMM pin 55"},
+//conflicts with MECS Tellurium xPOD2 SSPFRM2
+ {TEGRA_GPIO_PB7, GPIOF_IN, "SODIMM pin 63"},
+#ifndef COLIBRI_T20_VI
+ {TEGRA_GPIO_PD5, GPIOF_IN, "SODI-98, Iris X16-13"},
+ {TEGRA_GPIO_PD6, GPIOF_IN, "SODIMM pin 81"},
+ {TEGRA_GPIO_PD7, GPIOF_IN, "SODIMM pin 94"},
+#endif
+ {TEGRA_GPIO_PI3, GPIOF_IN, "SODIMM pin 130"},
+ {TEGRA_GPIO_PI6, GPIOF_IN, "SODIMM pin 132"},
+ {TEGRA_GPIO_PK0, GPIOF_IN, "SODIMM pin 150"},
+//multiplexed OWR
+ {TEGRA_GPIO_PK1, GPIOF_IN, "SODIMM pin 152"},
+//conflicts with CAN reset on MECS Tellurium xPOD1 CAN
+ {TEGRA_GPIO_PK4, GPIOF_IN, "SODIMM pin 106"},
+// {TEGRA_GPIO_PK5, GPIOF_IN, "USBC_DET"},
+#ifndef CONFIG_KEYBOARD_GPIO
+//conflicts with menu key
+ {TEGRA_GPIO_PK6, GPIOF_IN, "SODIMM pin 135"},
+#endif
+#ifndef COLIBRI_T20_VI
+#ifndef CONFIG_TOUCHSCREEN_FUSION_F0710A
+ {TEGRA_GPIO_PL0, GPIOF_IN, "SOD-101, Iris X16-16"},
+ {TEGRA_GPIO_PL1, GPIOF_IN, "SOD-103, Iris X16-15"},
+#endif /* !CONFIG_TOUCHSCREEN_FUSION_F0710A */
+//conflicts with Ethernet interrupt on Protea
+ {TEGRA_GPIO_PL2, GPIOF_IN, "SODI-79, Iris X16-19"},
+ {TEGRA_GPIO_PL3, GPIOF_IN, "SODI-97, Iris X16-17"},
+ {TEGRA_GPIO_PL6, GPIOF_IN, "SODI-85, Iris X16-18"},
+ {TEGRA_GPIO_PL7, GPIOF_IN, "SODIMM pin 65"},
+#endif
+
+//multiplexed SPI2_CS0_N, SPI2_MISO, SPI2_MOSI and SPI2_SCK
+ {TEGRA_GPIO_PM2, GPIOF_IN, "SODIMM pin 136"},
+ {TEGRA_GPIO_PM3, GPIOF_IN, "SODIMM pin 138"},
+ {TEGRA_GPIO_PM4, GPIOF_IN, "SODIMM pin 140"},
+ {TEGRA_GPIO_PM5, GPIOF_IN, "SODIMM pin 142"},
+
+ {TEGRA_GPIO_PN0, GPIOF_IN, "SODIMM pin 174"},
+ {TEGRA_GPIO_PN1, GPIOF_IN, "SODIMM pin 176"},
+ {TEGRA_GPIO_PN2, GPIOF_IN, "SODIMM pin 178"},
+ {TEGRA_GPIO_PN3, GPIOF_IN, "SODIMM pin 180"},
+ {TEGRA_GPIO_PN4, GPIOF_IN, "SODIMM pin 160"},
+ {TEGRA_GPIO_PN5, GPIOF_IN, "SODIMM pin 158"},
+ {TEGRA_GPIO_PN6, GPIOF_IN, "SODIMM pin 162"},
+//conflicts with ADDRESS13
+ {TEGRA_GPIO_PP4, GPIOF_IN, "SODIMM pin 120"},
+//conflicts with ADDRESS14
+ {TEGRA_GPIO_PP5, GPIOF_IN, "SODIMM pin 122"},
+//conflicts with ADDRESS15
+ {TEGRA_GPIO_PP6, GPIOF_IN, "SODIMM pin 124"},
+ {TEGRA_GPIO_PP7, GPIOF_IN, "SODIMM pin 188"},
+#ifndef COLIBRI_T20_VI
+ {TEGRA_GPIO_PT0, GPIOF_IN, "SODIMM pin 96"},
+ {TEGRA_GPIO_PT1, GPIOF_IN, "SODIMM pin 75"},
+#endif
+ {TEGRA_GPIO_PT2, GPIOF_IN, "SODIMM pin 69"},
+#ifndef CONFIG_KEYBOARD_GPIO
+//conflicts with find key
+ {TEGRA_GPIO_PT3, GPIOF_IN, "SODIMM pin 77"},
+#endif
+//conflicts with BL_ON
+// {TEGRA_GPIO_PT4, GPIOF_IN, "SODIMM pin 71"},
+//conflicts with ADDRESS12
+ {TEGRA_GPIO_PU6, GPIOF_IN, "SODIMM pin 118"},
+#ifndef CONFIG_KEYBOARD_GPIO
+//conflicts with power key (WAKE1)
+ {TEGRA_GPIO_PV3, GPIOF_IN, "SODI-45, Iris X16-20"},
+#endif
+
+ {TEGRA_GPIO_PX4, GPIOF_IN, "SODIMM pin 134"},
+ {TEGRA_GPIO_PX6, GPIOF_IN, "102, I X13 ForceOFF#"},
+ {TEGRA_GPIO_PX7, GPIOF_IN, "104, I X14 ForceOFF#"},
+ {TEGRA_GPIO_PZ2, GPIOF_IN, "SODIMM pin 156"},
+ {TEGRA_GPIO_PZ4, GPIOF_IN, "SODIMM pin 164"},
+#ifndef SDHCI_8BIT
+ {TEGRA_GPIO_PAA4, GPIOF_IN, "SODIMM pin 166"},
+ {TEGRA_GPIO_PAA5, GPIOF_IN, "SODIMM pin 168"},
+ {TEGRA_GPIO_PAA6, GPIOF_IN, "SODIMM pin 170"},
+ {TEGRA_GPIO_PAA7, GPIOF_IN, "SODIMM pin 172"},
+#endif
+#ifndef CONFIG_KEYBOARD_GPIO
+//conflicts with back key
+ {TEGRA_GPIO_PBB2, GPIOF_IN, "SOD-133, Iris X16-14"},
+//conflicts with home key
+ {TEGRA_GPIO_PBB3, GPIOF_IN, "SODIMM pin 127"},
+//conflicts with volume up key
+ {TEGRA_GPIO_PBB4, GPIOF_IN, "SODIMM pin 22"},
+//conflicts with volume down key
+ {TEGRA_GPIO_PBB5, GPIOF_IN, "SODIMM pin 24"},
+#endif
+};
+
+static void colibri_t20_gpio_init(void)
+{
+ int i = 0;
+ int length = sizeof(colibri_t20_gpios) / sizeof(struct gpio);
+ int err = 0;
+
+ for (i = 0; i < length; i++) {
+ err = gpio_request_one(colibri_t20_gpios[i].gpio,
+ colibri_t20_gpios[i].flags,
+ colibri_t20_gpios[i].label);
+
+ if (err) {
+ pr_warning("gpio_request(%s) failed, err = %d",
+ colibri_t20_gpios[i].label, err);
+ } else {
+ gpio_export(colibri_t20_gpios[i].gpio, true);
+ }
+ }
+}
+
+/* I2C */
+
+/* GEN1_I2C: I2C_SDA/SCL on SODIMM pin 194/196 (e.g. RTC on carrier board) */
+static struct i2c_board_info colibri_t20_i2c_bus1_board_info[] __initdata = {
+ {
+ /* M41T0M6 real time clock on Iris carrier board */
+ I2C_BOARD_INFO("rtc-ds1307", 0x68),
+ .type = "m41t00",
+ },
+#ifdef CONFIG_TOUCHSCREEN_FUSION_F0710A
+ {
+ /* TouchRevolution Fusion 7 and 10 multi-touch controller */
+ I2C_BOARD_INFO("fusion_F0710A", 0x10),
+ },
+#endif /* CONFIG_TOUCHSCREEN_FUSION_F0710A */
+#ifdef CONFIG_VIDEO_ADV7180
+ {
+ I2C_BOARD_INFO("adv7180", 0x21),
+ },
+#endif /* CONFIG_VIDEO_ADV7180 */
+#ifdef CONFIG_VIDEO_MT9V111
+ {
+ I2C_BOARD_INFO("mt9v111", 0x5c),
+ .platform_data = (void *)&camera_mt9v111_data,
+ },
+#endif /* CONFIG_VIDEO_MT9V111 */
+};
+
+static struct tegra_i2c_platform_data colibri_t20_i2c1_platform_data = {
+ .adapter_nr = 0,
+ .arb_recovery = arb_lost_recovery,
+ .bus_clk_rate = {400000, 0},
+ .bus_count = 1,
+ .scl_gpio = {I2C_SCL, 0},
+ .sda_gpio = {I2C_SDA, 0},
+ .slave_addr = 0x00FC,
+};
+
+/* GEN2_I2C: unused */
+
+/* DDC_CLOCK/DATA on X3 pin 15/16 (e.g. display EDID) */
+static const struct tegra_pingroup_config i2c2_ddc = {
+ .pingroup = TEGRA_PINGROUP_DDC,
+ .func = TEGRA_MUX_I2C2,
+};
+
+static struct tegra_i2c_platform_data colibri_t20_i2c2_platform_data = {
+ .adapter_nr = 1,
+ .arb_recovery = arb_lost_recovery,
+ .bus_clk_rate = {10000, 10000},
+ .bus_count = 1,
+ .slave_addr = 0x00FC,
+};
+
+/* PWR_I2C: power I2C to PMIC and temperature sensor */
+
+static void lm95245_probe_callback(struct device *dev);
+
+static struct lm95245_platform_data colibri_t20_lm95245_pdata = {
+ .enable_os_pin = true,
+ .probe_callback = lm95245_probe_callback,
+};
+
+static struct i2c_board_info colibri_t20_i2c_bus4_board_info[] __initdata = {
+ {
+ /* LM95245 temperature sensor */
+ I2C_BOARD_INFO("lm95245", 0x4c),
+ .platform_data = &colibri_t20_lm95245_pdata,
+ },
+};
+
+static struct tegra_i2c_platform_data colibri_t20_dvc_platform_data = {
+ .adapter_nr = 4,
+ .arb_recovery = arb_lost_recovery,
+ .bus_clk_rate = {400000, 0},
+ .bus_count = 1,
+ .is_dvc = true,
+ .scl_gpio = {PWR_I2C_SCL, 0},
+ .sda_gpio = {PWR_I2C_SDA, 0},
+};
+
+static void colibri_t20_i2c_init(void)
+{
+ tegra_i2c_device1.dev.platform_data = &colibri_t20_i2c1_platform_data;
+ tegra_i2c_device2.dev.platform_data = &colibri_t20_i2c2_platform_data;
+ tegra_i2c_device4.dev.platform_data = &colibri_t20_dvc_platform_data;
+
+ platform_device_register(&tegra_i2c_device1);
+ platform_device_register(&tegra_i2c_device2);
+ platform_device_register(&tegra_i2c_device4);
+
+#ifdef CONFIG_TOUCHSCREEN_FUSION_F0710A
+ if ((gpio_request(FUSION_PEN_DOWN, "103, Iris X16-15 Pen") == 0) &&
+ (gpio_direction_input(FUSION_PEN_DOWN) == 0)) {
+ gpio_export(FUSION_PEN_DOWN, 0);
+ } else {
+ printk(KERN_ERR "Could not obtain GPIO for Fusion pen down\n");
+ return;
+ }
+
+ if ((gpio_request(FUSION_RESET, "101, Iris X16-16 RST") == 0) &&
+ (gpio_direction_output(FUSION_RESET, 1) == 0)) {
+ gpio_direction_output(FUSION_RESET, 0);
+ mdelay(10);
+ gpio_direction_output(FUSION_RESET, 1);
+ } else {
+ printk(KERN_ERR "Could not obtain GPIO for Fusion reset\n");
+ return;
+ }
+
+ colibri_t20_i2c_bus1_board_info[1].irq = gpio_to_irq(FUSION_PEN_DOWN);
+#endif /* CONFIG_TOUCHSCREEN_FUSION_F0710A */
+
+ i2c_register_board_info(0, colibri_t20_i2c_bus1_board_info,
+ ARRAY_SIZE(colibri_t20_i2c_bus1_board_info));
+ i2c_register_board_info(4, colibri_t20_i2c_bus4_board_info,
+ ARRAY_SIZE(colibri_t20_i2c_bus4_board_info));
+}
+
+/* Keys
+ Note: active-low means pull-ups required on carrier board resp. via
+ pin-muxing
+ Note2: power-key active-high due to EvalBoard v3.1a having 100 K pull-down
+ on SODIMM pin 45 */
+
+#ifdef CONFIG_KEYBOARD_GPIO
+#define GPIO_KEY(_id, _gpio, _lowactive, _iswake) \
+ { \
+ .code = _id, \
+ .gpio = TEGRA_GPIO_##_gpio, \
+ .active_low = _lowactive, \
+ .desc = #_id, \
+ .type = EV_KEY, \
+ .wakeup = _iswake, \
+ .debounce_interval = 10, \
+ }
+
+static struct gpio_keys_button colibri_t20_keys[] = {
+ [0] = GPIO_KEY(KEY_FIND, PT3, 1, 0), /* SODIMM pin 77 */
+ [1] = GPIO_KEY(KEY_HOME, PBB3, 1, 0), /* SODIMM pin 127 */
+ [2] = GPIO_KEY(KEY_BACK, PBB2, 1, 0), /* SODIMM pin 133,
+ Iris X16-14 */
+ [3] = GPIO_KEY(KEY_VOLUMEUP, PBB4, 1, 0), /* SODIMM pin 22 */
+ [4] = GPIO_KEY(KEY_VOLUMEDOWN, PBB5, 1, 0), /* SODIMM pin 24 */
+ [5] = GPIO_KEY(KEY_POWER, PV3, 0, 1), /* SODIMM pin 45,
+ Iris X16-20 */
+ [6] = GPIO_KEY(KEY_MENU, PK6, 1, 0), /* SODIMM pin 135 */
+};
+
+#define PMC_WAKE_STATUS 0x14
+
+static int colibri_t20_wakeup_key(void)
+{
+ unsigned long status =
+ readl(IO_ADDRESS(TEGRA_PMC_BASE) + PMC_WAKE_STATUS);
+
+ return (status & (1 << TEGRA_WAKE_GPIO_PV3)) ?
+ KEY_POWER : KEY_RESERVED;
+}
+
+static struct gpio_keys_platform_data colibri_t20_keys_platform_data = {
+ .buttons = colibri_t20_keys,
+ .nbuttons = ARRAY_SIZE(colibri_t20_keys),
+ .wakeup_key = colibri_t20_wakeup_key,
+};
+
+static struct platform_device colibri_t20_keys_device = {
+ .name = "gpio-keys",
+ .id = 0,
+ .dev = {
+ .platform_data = &colibri_t20_keys_platform_data,
+ },
+};
+#endif /* CONFIG_KEYBOARD_GPIO */
+
+/* MMC/SD */
+
+static struct tegra_sdhci_platform_data colibri_t20_sdhci_platform_data = {
+ .cd_gpio = MMC_CD,
+#ifndef SDHCI_8BIT
+ .is_8bit = 0,
+#else
+ .is_8bit = 1,
+#endif
+ .power_gpio = -1,
+ .wp_gpio = -1,
+};
+
+int __init colibri_t20_sdhci_init(void)
+{
+ tegra_sdhci_device4.dev.platform_data =
+ &colibri_t20_sdhci_platform_data;
+ platform_device_register(&tegra_sdhci_device4);
+
+ return 0;
+}
+
+/* NAND */
+
+static struct tegra_nand_chip_parms nand_chip_parms[] = {
+ /* Micron MT29F4G08ABBDAH4 */
+ [0] = {
+ .vendor_id = 0x2C,
+ .device_id = 0xAC,
+ .read_id_fourth_byte = 0x15,
+ .capacity = 512,
+ .timing = {
+ .trp = 12,
+ .trh = 10, /* tREH */
+ .twp = 12,
+ .twh = 10,
+ .tcs = 20, /* Max(tCS, tCH, tALS, tALH) */
+ .twhr = 80,
+ .tcr_tar_trr = 20, /* Max(tCR, tAR, tRR) */
+ .twb = 100,
+ .trp_resp = 12, /* tRP */
+ .tadl = 70,
+ },
+ },
+ /* Micron MT29F4G08ABBEAH4 */
+ [1] = {
+ .vendor_id = 0x2C,
+ .device_id = 0xAC,
+ .read_id_fourth_byte = 0x26,
+ .capacity = 512,
+ .timing = {
+ .trp = 15,
+ .trh = 10, /* tREH */
+ .twp = 15,
+ .twh = 10,
+ .tcs = 25, /* Max(tCS, tCH, tALS, tALH) */
+ .twhr = 80,
+ .tcr_tar_trr = 20, /* Max(tCR, tAR, tRR) */
+ .twb = 100,
+ .trp_resp = 15, /* tRP */
+ .tadl = 100,
+ },
+ },
+ /* Micron MT29F8G08ABCBB on Colibri T20 before V1.2 */
+ [2] = {
+ .vendor_id = 0x2C,
+ .device_id = 0x38,
+ .read_id_fourth_byte = 0x26,
+ .capacity = 1024,
+ .timing = {
+ /* timing mode 4 */
+ .trp = 12,
+ .trh = 10, /* tREH */
+ .twp = 12,
+ .twh = 10,
+ .tcs = 20, /* Max(tCS, tCH, tALS, tALH) */
+ .twhr = 60,
+ .tcr_tar_trr = 20, /* Max(tCR, tAR, tRR) */
+ .twb = 100,
+ .trp_resp = 12, /* tRP */
+ .tadl = 70,
+ },
+ },
+ /* Micron MT29F8G08ADBDAH4 */
+ [3] = {
+ .vendor_id = 0x2C,
+ .device_id = 0xA3,
+ .read_id_fourth_byte = 0x15,
+ .capacity = 1024,
+ .timing = {
+ .trp = 12,
+ .trh = 10, /* tREH */
+ .twp = 12,
+ .twh = 10,
+ .tcs = 20, /* Max(tCS, tCH, tALS, tALH) */
+ .twhr = 80,
+ .tcr_tar_trr = 20, /* Max(tCR, tAR, tRR) */
+ .twb = 100,
+ .trp_resp = 12, /* tRP */
+ .tadl = 70,
+ },
+ },
+ /* Micron MT29F8G08ABBCA */
+ [4] = {
+ .vendor_id = 0x2C,
+ .device_id = 0xA3,
+ .read_id_fourth_byte = 0x26,
+ .capacity = 1024,
+ .timing = {
+ .trp = 15,
+ .trh = 10, /* tREH */
+ .twp = 15,
+ .twh = 10,
+ .tcs = 25, /* Max(tCS, tCH, tALS, tALH) */
+ .twhr = 80,
+ .tcr_tar_trr = 20, /* Max(tCR, tAR, tRR) */
+ .twb = 100,
+ .trp_resp = 15, /* tRP */
+ .tadl = 100,
+ },
+ },
+ /* Samsung K9K8G08U0B */
+ [5] = {
+ .vendor_id = 0xec,
+ .device_id = 0xd3,
+ .read_id_fourth_byte = 0x95,
+ .capacity = 1024,
+ .timing = {
+ .trp = 12, /* tRP, ND_nRE pulse width */
+ .trh = 100, /* tRHZ, ND_nRE high
+ duration */
+ .twp = 12, /* tWP, ND_nWE pulse time */
+ .twh = 10, /* tWH, ND_nWE high duration */
+ .tcs = 20, /* Max(tCS, tCH, tALS, tALH) */
+ .twhr = 60, /* tWHR, ND_nWE high to ND_nRE
+ low delay for status read */
+ .tcr_tar_trr = 20, /* Max(tCR, tAR, tRR) */
+ .twb = 100,
+ .trp_resp = 12, /* tRP */
+ .tadl = 70,
+ },
+ },
+};
+
+struct tegra_nand_platform colibri_t20_nand_data = {
+ .max_chips = 8,
+ .chip_parms = nand_chip_parms,
+ .nr_chip_parms = ARRAY_SIZE(nand_chip_parms),
+ .wp_gpio = NAND_WP_N,
+};
+
+static struct resource resources_nand[] = {
+ [0] = {
+ .start = INT_NANDFLASH,
+ .end = INT_NANDFLASH,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tegra_nand_device = {
+ .name = "tegra_nand",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(resources_nand),
+ .resource = resources_nand,
+ .dev = {
+ .platform_data = &colibri_t20_nand_data,
+ },
+};
+
+/* PWM LEDs */
+static struct led_pwm tegra_leds_pwm[] = {
+#ifdef MECS_TELLURIUM
+ {
+ .name = "PWM<A>",
+ .pwm_id = 0,
+ .max_brightness = 255,
+ .pwm_period_ns = 19600,
+ },
+#endif /* MECS_TELLURIUM */
+ {
+ .name = "PWM<B>",
+ .pwm_id = 1,
+ .max_brightness = 255,
+ .pwm_period_ns = 19600,
+ },
+#ifndef MECS_TELLURIUM
+ {
+ .name = "PWM<C>",
+ .pwm_id = 2,
+ .max_brightness = 255,
+ .pwm_period_ns = 19600,
+ },
+#endif /* !MECS_TELLURIUM */
+ {
+ .name = "PWM<D>",
+ .pwm_id = 3,
+ .max_brightness = 255,
+ .pwm_period_ns = 19600,
+ },
+};
+
+static struct led_pwm_platform_data tegra_leds_pwm_data = {
+ .num_leds = ARRAY_SIZE(tegra_leds_pwm),
+ .leds = tegra_leds_pwm,
+};
+
+static struct platform_device tegra_led_pwm_device = {
+ .name = "leds_pwm",
+ .id = -1,
+ .dev = {
+ .platform_data = &tegra_leds_pwm_data,
+ },
+};
+
+/* RTC */
+
+#ifdef CONFIG_RTC_DRV_TEGRA
+static struct resource tegra_rtc_resources[] = {
+ [0] = {
+ .start = TEGRA_RTC_BASE,
+ .end = TEGRA_RTC_BASE + TEGRA_RTC_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = INT_RTC,
+ .end = INT_RTC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tegra_rtc_device = {
+ .name = "tegra_rtc",
+ .id = -1,
+ .resource = tegra_rtc_resources,
+ .num_resources = ARRAY_SIZE(tegra_rtc_resources),
+};
+#endif /* CONFIG_RTC_DRV_TEGRA */
+
+/* SPI */
+
+#if defined(CONFIG_SPI_TEGRA) && defined(CONFIG_SPI_SPIDEV)
+static struct spi_board_info tegra_spi_devices[] __initdata = {
+ {
+ .bus_num = 3, /* SPI4: Colibri SSP */
+ .chip_select = 0,
+ .irq = 0,
+ .max_speed_hz = 50000000,
+ .modalias = "spidev",
+ .mode = SPI_MODE_0,
+ .platform_data = NULL,
+ },
+};
+
+static void __init colibri_t20_register_spidev(void)
+{
+ spi_register_board_info(tegra_spi_devices,
+ ARRAY_SIZE(tegra_spi_devices));
+}
+#else /* CONFIG_SPI_TEGRA & CONFIG_SPI_SPIDEV */
+#define colibri_t20_register_spidev() do {} while (0)
+#endif /* CONFIG_SPI_TEGRA & CONFIG_SPI_SPIDEV */
+
+/* Thermal throttling
+ Note: As our hardware only allows triggering an interrupt on
+ over-temperature shutdown we first use it to catch entering throttle
+ and only then set it up to catch an actual over-temperature shutdown.
+ While throttling we setup a workqueue to catch leaving it again. */
+
+static int colibri_t20_shutdown_temp = 115000;
+static int colibri_t20_throttle_hysteresis = 3000;
+static int colibri_t20_throttle_temp = 90000;
+static struct device *lm95245_device = NULL;
+static int thermd_alert_irq_disabled = 0;
+struct work_struct thermd_alert_work;
+struct workqueue_struct *thermd_alert_workqueue;
+
+/* Over-temperature shutdown OS pin GPIO interrupt handler */
+static irqreturn_t thermd_alert_irq(int irq, void *data)
+{
+ disable_irq_nosync(irq);
+ thermd_alert_irq_disabled = 1;
+ queue_work(thermd_alert_workqueue, &thermd_alert_work);
+
+ return IRQ_HANDLED;
+}
+
+/* Gets both entered by THERMD_ALERT GPIO interrupt as well as re-scheduled
+ while throttling. */
+static void thermd_alert_work_func(struct work_struct *work)
+{
+ int temp = 0;
+
+ lm95245_get_remote_temp(lm95245_device, &temp);
+
+ if (temp > colibri_t20_shutdown_temp) {
+ /* First check for hardware over-temperature condition mandating
+ immediate shutdown */
+ pr_err("over-temperature condition %d degC reached, initiating "
+ "immediate shutdown", temp);
+ kernel_power_off();
+ } else if (temp < colibri_t20_throttle_temp -
+ colibri_t20_throttle_hysteresis) {
+ /* Make sure throttling gets disabled again */
+ if (tegra_is_throttling()) {
+ tegra_throttling_enable(false);
+ lm95245_set_remote_os_limit(lm95245_device,
+ colibri_t20_throttle_temp);
+ }
+ } else if (temp < colibri_t20_throttle_temp) {
+ /* Operating within hysteresis so keep re-scheduling to catch
+ leaving below throttle again */
+ if (tegra_is_throttling()) {
+ msleep(100);
+ queue_work(thermd_alert_workqueue, &thermd_alert_work);
+ }
+ } else if (temp >= colibri_t20_throttle_temp) {
+ /* Make sure throttling gets enabled and set shutdown limit */
+ if (!tegra_is_throttling()) {
+ tegra_throttling_enable(true);
+ lm95245_set_remote_os_limit(lm95245_device,
+ colibri_t20_shutdown_temp);
+ }
+ /* And re-schedule again */
+ msleep(100);
+ queue_work(thermd_alert_workqueue, &thermd_alert_work);
+ }
+
+ /* Avoid unbalanced enable for IRQ 367 */
+ if (thermd_alert_irq_disabled) {
+ thermd_alert_irq_disabled = 0;
+ enable_irq(gpio_to_irq(THERMD_ALERT));
+ }
+}
+
+static void colibri_t20_thermd_alert_init(void)
+{
+ gpio_request(THERMD_ALERT, "THERMD_ALERT");
+ gpio_direction_input(THERMD_ALERT);
+
+ thermd_alert_workqueue = create_singlethread_workqueue("THERMD_ALERT");
+
+ INIT_WORK(&thermd_alert_work, thermd_alert_work_func);
+}
+
+static void lm95245_probe_callback(struct device *dev)
+{
+ lm95245_device = dev;
+
+ lm95245_set_remote_os_limit(lm95245_device, colibri_t20_throttle_temp);
+
+ if (request_irq(gpio_to_irq(THERMD_ALERT), thermd_alert_irq,
+ IRQF_TRIGGER_LOW, "THERMD_ALERT", NULL))
+ pr_err("%s: unable to register THERMD_ALERT interrupt\n",
+ __func__);
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int colibri_t20_thermal_get_throttle_temp(void *data, u64 *val)
+{
+ *val = (u64)colibri_t20_throttle_temp;
+ return 0;
+}
+
+static int colibri_t20_thermal_set_throttle_temp(void *data, u64 val)
+{
+ colibri_t20_throttle_temp = val;
+ if (!tegra_is_throttling() && lm95245_device)
+ lm95245_set_remote_os_limit(lm95245_device,
+ colibri_t20_throttle_temp);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(throttle_fops,
+ colibri_t20_thermal_get_throttle_temp,
+ colibri_t20_thermal_set_throttle_temp,
+ "%llu\n");
+
+static int colibri_t20_thermal_get_shutdown_temp(void *data, u64 *val)
+{
+ *val = (u64)colibri_t20_shutdown_temp;
+ return 0;
+}
+
+static int colibri_t20_thermal_set_shutdown_temp(void *data, u64 val)
+{
+ colibri_t20_shutdown_temp = val;
+ if (tegra_is_throttling() && lm95245_device)
+ lm95245_set_remote_os_limit(lm95245_device,
+ colibri_t20_shutdown_temp);
+
+ /* Carefull as we can only actively monitor one temperatur limit and
+ assumption is throttling is lower than shutdown one. */
+ if (colibri_t20_shutdown_temp < colibri_t20_throttle_temp)
+ colibri_t20_thermal_set_throttle_temp(NULL,
+ colibri_t20_shutdown_temp);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(shutdown_fops,
+ colibri_t20_thermal_get_shutdown_temp,
+ colibri_t20_thermal_set_shutdown_temp,
+ "%llu\n");
+
+static int __init colibri_t20_thermal_debug_init(void)
+{
+ struct dentry *thermal_debugfs_root;
+
+ thermal_debugfs_root = debugfs_create_dir("thermal", 0);
+
+ if (!debugfs_create_file("throttle", 0644, thermal_debugfs_root,
+ NULL, &throttle_fops))
+ return -ENOMEM;
+
+ if (!debugfs_create_file("shutdown", 0644, thermal_debugfs_root,
+ NULL, &shutdown_fops))
+ return -ENOMEM;
+
+ return 0;
+}
+late_initcall(colibri_t20_thermal_debug_init);
+#endif /* CONFIG_DEBUG_FS */
+
+/* UART */
+
+static struct platform_device *colibri_t20_uart_devices[] __initdata = {
+ &tegra_uarta_device, /* Colibri FFUART */
+ &tegra_uartd_device, /* Colibri BTUART */
+ &tegra_uartb_device, /* Colibri STDUART */
+};
+
+static struct uart_clk_parent uart_parent_clk[] = {
+ [0] = {.name = "pll_p"},
+ [1] = {.name = "pll_m"},
+ [2] = {.name = "clk_m"},
+};
+
+static struct tegra_uart_platform_data colibri_t20_uart_pdata;
+
+static void __init uart_debug_init(void)
+{
+ unsigned long rate;
+ struct clk *c;
+
+ /* UARTA is the debug port. */
+ pr_info("Selecting UARTA as the debug console\n");
+ colibri_t20_uart_devices[0] = &debug_uarta_device;
+ debug_uart_port_base = ((struct plat_serial8250_port *)(
+ debug_uarta_device.dev.platform_data))->mapbase;
+ debug_uart_clk = clk_get_sys("serial8250.0", "uarta");
+
+ /* Clock enable for the debug channel */
+ if (!IS_ERR_OR_NULL(debug_uart_clk)) {
+ rate = ((struct plat_serial8250_port *)(
+ debug_uarta_device.dev.platform_data))->uartclk;
+ pr_info("The debug console clock name is %s\n",
+ debug_uart_clk->name);
+ c = tegra_get_clock_by_name("pll_p");
+ if (IS_ERR_OR_NULL(c))
+ pr_err("Not getting the parent clock pll_p\n");
+ else
+ clk_set_parent(debug_uart_clk, c);
+
+ clk_enable(debug_uart_clk);
+ clk_set_rate(debug_uart_clk, rate);
+ } else {
+ pr_err("Not getting the clock %s for debug console\n",
+ debug_uart_clk->name);
+ }
+}
+
+static void __init colibri_t20_uart_init(void)
+{
+ int i;
+ struct clk *c;
+
+ for (i = 0; i < ARRAY_SIZE(uart_parent_clk); ++i) {
+ c = tegra_get_clock_by_name(uart_parent_clk[i].name);
+ if (IS_ERR_OR_NULL(c)) {
+ pr_err("Not able to get the clock for %s\n",
+ uart_parent_clk[i].name);
+ continue;
+ }
+ uart_parent_clk[i].parent_clk = c;
+ uart_parent_clk[i].fixed_clk_rate = clk_get_rate(c);
+ }
+ colibri_t20_uart_pdata.parent_clk_list = uart_parent_clk;
+ colibri_t20_uart_pdata.parent_clk_count = ARRAY_SIZE(uart_parent_clk);
+ tegra_uarta_device.dev.platform_data = &colibri_t20_uart_pdata;
+ tegra_uartb_device.dev.platform_data = &colibri_t20_uart_pdata;
+ tegra_uartd_device.dev.platform_data = &colibri_t20_uart_pdata;
+
+ /* Register low speed only if it is selected */
+ if (!is_tegra_debug_uartport_hs())
+ uart_debug_init();
+
+ platform_add_devices(colibri_t20_uart_devices,
+ ARRAY_SIZE(colibri_t20_uart_devices));
+}
+
+/* USB */
+
+//TODO: overcurrent
+
+static struct tegra_usb_platform_data tegra_udc_pdata = {
+ .has_hostpc = false,
+ .op_mode = TEGRA_USB_OPMODE_DEVICE,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .port_otg = true,
+ .u_cfg.utmi = {
+ .elastic_limit = 16,
+ .hssync_start_delay = 0,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup = 8,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
+ },
+ .u_data.dev = {
+ .charging_supported = false,
+ .remote_wakeup_supported = false,
+ .vbus_gpio = -1,
+ .vbus_pmu_irq = 0,
+ },
+};
+
+static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = {
+ .has_hostpc = false,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .port_otg = true,
+ .u_cfg.utmi = {
+ .elastic_limit = 16,
+ .hssync_start_delay = 9,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup = 8,
+ },
+ .u_data.host = {
+ .hot_plug = true,
+ .power_off_on_suspend = false,
+ .remote_wakeup_supported = false,
+ .vbus_gpio = -1,
+ .vbus_reg = NULL,
+ },
+};
+
+static void ulpi_link_platform_open(void)
+{
+ int reset_gpio = USB3340_RESETB;
+
+ gpio_request(reset_gpio, "ulpi_phy_reset");
+ gpio_direction_output(reset_gpio, 0);
+ msleep(5);
+ gpio_direction_output(reset_gpio, 1);
+}
+
+static void ulpi_link_platform_post_phy_on(void)
+{
+ /* enable VBUS */
+ gpio_set_value(LAN_V_BUS, 1);
+
+ /* reset */
+ gpio_set_value(LAN_RESET, 0);
+
+ udelay(5);
+
+ /* unreset */
+ gpio_set_value(LAN_RESET, 1);
+}
+
+static void ulpi_link_platform_pre_phy_off(void)
+{
+ /* disable VBUS */
+ gpio_set_value(LAN_V_BUS, 0);
+}
+
+static struct tegra_usb_phy_platform_ops ulpi_link_plat_ops = {
+ .open = ulpi_link_platform_open,
+ .post_phy_on = ulpi_link_platform_post_phy_on,
+ .pre_phy_off = ulpi_link_platform_pre_phy_off,
+};
+
+static struct tegra_usb_platform_data tegra_ehci2_ulpi_link_pdata = {
+ .has_hostpc = false,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .ops = &ulpi_link_plat_ops,
+ .phy_intf = TEGRA_USB_PHY_INTF_ULPI_LINK,
+ .port_otg = false,
+ .u_cfg.ulpi = {
+ .clk = "cdev2",
+ .clock_out_delay = 1,
+ .data_trimmer = 4,
+ .dir_trimmer = 4,
+ .shadow_clk_delay = 10,
+ .stpdirnxt_trimmer = 4,
+ },
+ .u_data.host = {
+ .hot_plug = false,
+ .power_off_on_suspend = true,
+ .remote_wakeup_supported = false,
+ .vbus_gpio = -1,
+ .vbus_reg = NULL,
+ },
+};
+
+static struct tegra_usb_platform_data tegra_ehci3_utmi_pdata = {
+ .has_hostpc = false,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .port_otg = false,
+ .u_cfg.utmi = {
+ .elastic_limit = 16,
+ .hssync_start_delay = 9,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup = 8,
+ },
+ .u_data.host = {
+ .hot_plug = true,
+ .power_off_on_suspend = false,
+ .remote_wakeup_supported = false,
+ .vbus_gpio = USBH_PEN,
+ .vbus_gpio_inverted = 1,
+ .vbus_reg = NULL,
+ },
+};
+
+#ifndef CONFIG_USB_TEGRA_OTG
+static struct platform_device *tegra_usb_otg_host_register(void)
+{
+ struct platform_device *pdev;
+ void *platform_data;
+ int val;
+
+ pdev = platform_device_alloc(tegra_ehci1_device.name,
+ tegra_ehci1_device.id);
+ if (!pdev)
+ return NULL;
+
+ val = platform_device_add_resources(pdev, tegra_ehci1_device.resource,
+ tegra_ehci1_device.num_resources);
+ if (val)
+ goto error;
+
+ pdev->dev.dma_mask = tegra_ehci1_device.dev.dma_mask;
+ pdev->dev.coherent_dma_mask = tegra_ehci1_device.dev.coherent_dma_mask;
+
+ platform_data = kmalloc(sizeof(struct tegra_usb_platform_data),
+ GFP_KERNEL);
+ if (!platform_data)
+ goto error;
+
+ memcpy(platform_data, &tegra_ehci1_utmi_pdata,
+ sizeof(struct tegra_usb_platform_data));
+ pdev->dev.platform_data = platform_data;
+
+ val = platform_device_add(pdev);
+ if (val)
+ goto error_add;
+
+ return pdev;
+
+error_add:
+ kfree(platform_data);
+error:
+ pr_err("%s: failed to add the host controller device\n", __func__);
+ platform_device_put(pdev);
+ return NULL;
+}
+
+static void tegra_usb_otg_host_unregister(struct platform_device *pdev)
+{
+ kfree(pdev->dev.platform_data);
+ pdev->dev.platform_data = NULL;
+ platform_device_unregister(pdev);
+}
+
+static struct colibri_otg_platform_data colibri_otg_pdata = {
+ .cable_detect_gpio = USBC_DET,
+ .host_register = &tegra_usb_otg_host_register,
+ .host_unregister = &tegra_usb_otg_host_unregister,
+};
+#else /* !CONFIG_USB_TEGRA_OTG */
+static struct tegra_usb_otg_data tegra_otg_pdata = {
+ .ehci_device = &tegra_ehci1_device,
+ .ehci_pdata = &tegra_ehci1_utmi_pdata,
+};
+#endif /* !CONFIG_USB_TEGRA_OTG */
+
+#ifndef CONFIG_USB_TEGRA_OTG
+struct platform_device colibri_otg_device = {
+ .name = "colibri-otg",
+ .id = -1,
+ .dev = {
+ .platform_data = &colibri_otg_pdata,
+ },
+};
+#endif /* !CONFIG_USB_TEGRA_OTG */
+
+static void colibri_t20_usb_init(void)
+{
+ gpio_request(LAN_V_BUS, "LAN_V_BUS");
+ gpio_direction_output(LAN_V_BUS, 0);
+ gpio_export(LAN_V_BUS, false);
+
+ gpio_request(LAN_RESET, "LAN_RESET");
+ gpio_direction_output(LAN_RESET, 0);
+ gpio_export(LAN_RESET, false);
+
+ /* OTG should be the first to be registered
+ EHCI instance 0: USB1_DP/N -> USBOTG_P/N */
+#ifndef CONFIG_USB_TEGRA_OTG
+ platform_device_register(&colibri_otg_device);
+#else /* !CONFIG_USB_TEGRA_OTG */
+ tegra_otg_device.dev.platform_data = &tegra_otg_pdata;
+ platform_device_register(&tegra_otg_device);
+#endif /* !CONFIG_USB_TEGRA_OTG */
+
+ /* setup the udc platform data */
+ tegra_udc_device.dev.platform_data = &tegra_udc_pdata;
+ platform_device_register(&tegra_udc_device);
+
+ /* EHCI instance 1: ULPI PHY -> ASIX ETH */
+ tegra_ehci2_device.dev.platform_data = &tegra_ehci2_ulpi_link_pdata;
+ platform_device_register(&tegra_ehci2_device);
+
+ /* EHCI instance 2: USB3_DP/N -> USBH1_P/N */
+ tegra_ehci3_device.dev.platform_data = &tegra_ehci3_utmi_pdata;
+ platform_device_register(&tegra_ehci3_device);
+
+#ifdef MECS_TELLURIUM
+//SD card multiplexing: pull GPIO_PT2 and GPIO_PBB2 low
+//working even without any modifications
+ {
+ int gpio_status;
+ unsigned int i2c_scl = I2C_SCL;
+ unsigned int i2c_sda = I2C_SDA;
+ unsigned int tellurium_usb_hub_reset = MECS_USB_HUB_RESET;
+
+ printk("MECS Tellurium USB Hub Initialisation\n");
+
+ /* configure USB hub reset line as output and pull low into
+ reset */
+ gpio_status = gpio_request(tellurium_usb_hub_reset,
+ "USB_HUB_RESET");
+ if (gpio_status < 0)
+ pr_warning("USB_HUB_RESET request GPIO FAILED\n");
+ gpio_status = gpio_direction_output(tellurium_usb_hub_reset,
+ 0);
+ if (gpio_status < 0)
+ pr_warning("USB_HUB_RESET request GPIO DIRECTION "
+ "FAILED\n");
+
+ /* configure I2C pins as outputs and pull low */
+ gpio_status = gpio_direction_output(i2c_scl, 0);
+ if (gpio_status < 0)
+ pr_warning("I2C_SCL request GPIO DIRECTION FAILED\n");
+ gpio_status = gpio_direction_output(i2c_sda, 0);
+ if (gpio_status < 0)
+ pr_warning("I2C_SDA request GPIO DIRECTION FAILED\n");
+
+ /* pull USB hub out of reset */
+ gpio_set_value(tellurium_usb_hub_reset, 1);
+
+ /* release I2C pins again */
+ tegra_gpio_disable(i2c_scl);
+ tegra_gpio_disable(i2c_sda);
+ }
+#endif /* MECS_TELLURIUM */
+}
+
+/* W1, aka OWR, aka OneWire */
+
+#ifdef CONFIG_W1_MASTER_TEGRA
+struct tegra_w1_timings colibri_t20_w1_timings = {
+ .tsu = 1,
+ .trelease = 0xf,
+ .trdv = 0xf,
+ .tlow0 = 0x3c,
+ .tlow1 = 1,
+ .tslot = 0x77,
+
+ .tpdl = 0x78,
+ .tpdh = 0x1e,
+ .trstl = 0x1df,
+ .trsth = 0x1df,
+ .rdsclk = 0x7,
+ .psclk = 0x50,
+};
+
+struct tegra_w1_platform_data colibri_t20_w1_platform_data = {
+ .clk_id = "tegra_w1",
+ .timings = &colibri_t20_w1_timings,
+};
+#endif /* CONFIG_W1_MASTER_TEGRA */
+
+static struct platform_device *colibri_t20_devices[] __initdata = {
+#ifdef CONFIG_RTC_DRV_TEGRA
+ &tegra_rtc_device,
+#endif
+ &tegra_nand_device,
+
+ &tegra_pmu_device,
+ &tegra_gart_device,
+ &tegra_aes_device,
+#ifdef CONFIG_KEYBOARD_GPIO
+ &colibri_t20_keys_device,
+#endif
+ &tegra_wdt_device,
+ &tegra_avp_device,
+#ifdef CONFIG_TEGRA_CAMERA
+ &tegra_camera,
+#endif
+ &tegra_ac97_device,
+ &tegra_spdif_device,
+ &tegra_das_device,
+ &spdif_dit_device,
+//bluetooth
+ &tegra_pcm_device,
+ &colibri_t20_audio_device,
+ &tegra_spi_device4,
+ &tegra_led_pwm_device,
+ &tegra_pwfm1_device,
+#ifndef MECS_TELLURIUM
+ &tegra_pwfm2_device,
+#else
+ &tegra_pwfm0_device,
+#endif
+ &tegra_pwfm3_device,
+#ifdef CONFIG_W1_MASTER_TEGRA
+ &tegra_w1_device,
+#endif
+};
+
+static void __init colibri_t20_init(void)
+{
+ tegra_clk_init_from_table(colibri_t20_clk_init_table);
+ colibri_t20_pinmux_init();
+ colibri_t20_thermd_alert_init();
+ colibri_t20_i2c_init();
+ colibri_t20_uart_init();
+//
+ tegra_ac97_device.dev.platform_data = &colibri_t20_wm97xx_pdata;
+//
+#ifdef CONFIG_W1_MASTER_TEGRA
+ tegra_w1_device.dev.platform_data = &colibri_t20_w1_platform_data;
+#endif
+ platform_add_devices(colibri_t20_devices,
+ ARRAY_SIZE(colibri_t20_devices));
+ tegra_ram_console_debug_init();
+ colibri_t20_sdhci_init();
+ colibri_t20_regulator_init();
+
+// tegra_das_device.dev.platform_data = &tegra_das_pdata;
+// tegra_ac97_device.dev.platform_data = &tegra_audio_pdata;
+// tegra_spdif_input_device.name = "spdif";
+// tegra_spdif_input_device.dev.platform_data = &tegra_spdif_audio_pdata;
+
+ colibri_t20_usb_init();
+ colibri_t20_panel_init();
+//sensors
+
+ /* Note: V1.1c modules require proper BCT setting 666 rather than
+ 721.5 MHz EMC clock */
+ colibri_t20_emc_init();
+
+ colibri_t20_gpio_init();
+ colibri_t20_register_spidev();
+
+ tegra_release_bootloader_fb();
+}
+
+int __init tegra_colibri_t20_protected_aperture_init(void)
+{
+ if (!machine_is_colibri_t20())
+ return 0;
+
+ tegra_protected_aperture_init(tegra_grhost_aperture);
+ return 0;
+}
+late_initcall(tegra_colibri_t20_protected_aperture_init);
+
+void __init colibri_t20_reserve(void)
+{
+ if (memblock_reserve(0x0, 4096) < 0)
+ pr_warn("Cannot reserve first 4K of memory for safety\n");
+
+ /* we specify zero for special handling due to already reserved
+ fbmem/nvmem (U-Boot 2011.06 compatibility from our V1.x images) */
+ tegra_reserve(0, SZ_8M + SZ_1M, SZ_16M);
+ tegra_ram_console_debug_reserve(SZ_1M);
+}
+
+static const char *colibri_t20_dt_board_compat[] = {
+ "toradex,colibri_t20",
+ NULL
+};
+
+#ifdef CONFIG_ANDROID
+MACHINE_START(COLIBRI_T20, "ventana")
+#else
+MACHINE_START(COLIBRI_T20, "Toradex Colibri T20")
+#endif
+ .boot_params = 0x00000100,
+ .dt_compat = colibri_t20_dt_board_compat,
+ .init_early = tegra_init_early,
+ .init_irq = tegra_init_irq,
+ .init_machine = colibri_t20_init,
+ .map_io = tegra_map_common_io,
+ .reserve = colibri_t20_reserve,
+ .timer = &tegra_timer,
+MACHINE_END
diff --git a/arch/arm/mach-tegra/board-colibri_t20.h b/arch/arm/mach-tegra/board-colibri_t20.h
new file mode 100644
index 000000000000..09d5c3175b7f
--- /dev/null
+++ b/arch/arm/mach-tegra/board-colibri_t20.h
@@ -0,0 +1,89 @@
+/*
+ * arch/arm/mach-tegra/board-colibri_t20.h
+ *
+ * Copyright (C) 2011 Toradex, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _MACH_TEGRA_BOARD_COLIBRI_T20_H
+#define _MACH_TEGRA_BOARD_COLIBRI_T20_H
+
+/* Uncomment for camera interface support on Colibri Evaluation carrier
+ board */
+#ifdef CONFIG_TEGRA_CAMERA
+#define COLIBRI_T20_VI
+#endif
+
+/* Run framebuffer in VGA mode */
+#ifndef CONFIG_ANDROID
+#define TEGRA_FB_VGA
+#endif
+
+/* GPIO */
+
+#define FF_DCD TEGRA_GPIO_PC6 /* SODIMM 31 */
+#define FF_DSR TEGRA_GPIO_PC1 /* SODIMM 29 */
+
+#define FUSION_PEN_DOWN TEGRA_GPIO_PL1 /* SODIMM 103 */
+#define FUSION_RESET TEGRA_GPIO_PL0 /* SODIMM 101 */
+
+#define I2C_SCL TEGRA_GPIO_PC4 /* SODIMM 196 */
+#define I2C_SDA TEGRA_GPIO_PC5 /* SODIMM 194 */
+
+#define LAN_EXT_WAKEUP TEGRA GPIO_PV5
+#define LAN_PME TEGRA_GPIO_PV6
+#define LAN_RESET TEGRA_GPIO_PV4
+#define LAN_V_BUS TEGRA_GPIO_PBB1
+
+#define MECS_USB_HUB_RESET TEGRA_GPIO_PBB3 /* SODIMM 127 */
+
+#define MMC_CD TEGRA_GPIO_PC7 /* SODIMM 43 */
+
+#define NAND_WP_N TEGRA_GPIO_PS0
+
+#define PWR_I2C_SCL TEGRA_GPIO_PZ6
+#define PWR_I2C_SDA TEGRA_GPIO_PZ7
+
+#define THERMD_ALERT TEGRA_GPIO_PV7
+
+#define TOUCH_PEN_INT TEGRA_GPIO_PV2
+
+#define USB3340_RESETB TEGRA_GPIO_PV1
+//conflicts with MECS Tellurium xPOD2 SSPTXD2
+#define USBC_DET TEGRA_GPIO_PK5 /* SODIMM 137 */
+#define USBH_OC TEGRA_GPIO_PW3 /* SODIMM 131 */
+#define USBH_PEN TEGRA_GPIO_PW2 /* SODIMM 129 */
+
+/* Use SODIMM pin 73 as DAC power save on Iris carrier board */
+#define IRIS
+
+/* Uncomment for back light and USB hub support on MECS Tellurium carrier
+ board */
+//#define MECS_TELLURIUM
+
+/* Uncomment for 8-bit SDHCI on HSMMC controller (requires custom carrier
+ board) */
+//#define SDHCI_8BIT
+
+/* TPS6586X gpios */
+#define TPS6586X_GPIO_BASE TEGRA_NR_GPIOS
+
+/* Interrupt numbers from external peripherals */
+#define TPS6586X_INT_BASE TEGRA_NR_IRQS
+#define TPS6586X_INT_END (TPS6586X_INT_BASE + 32)
+
+int colibri_t20_emc_init(void);
+int colibri_t20_panel_init(void);
+int colibri_t20_pinmux_init(void);
+int colibri_t20_regulator_init(void);
+
+#endif
diff --git a/arch/arm/mach-tegra/board-colibri_t30-memory.c b/arch/arm/mach-tegra/board-colibri_t30-memory.c
new file mode 100644
index 000000000000..c264cd7b0a24
--- /dev/null
+++ b/arch/arm/mach-tegra/board-colibri_t30-memory.c
@@ -0,0 +1,525 @@
+/*
+ * Copyright (C) 2012 Toradex, Inc.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include "board.h"
+#include "board-colibri_t30.h"
+#include "tegra3_emc.h"
+#include "fuse.h"
+
+static const struct tegra_emc_table colibri_t30_emc_tables_mt41k256m16re_15e[] = {
+ {
+ 0x32, /* Rev 3.2 */
+//ToDo: dblcheck with Max
+#if 1
+ 30000, /* SDRAM frequency [kHz] */
+#else
+ 200000, /* SDRAM frequency [kHz] */
+#endif
+ {
+ 0x0000000a, /* EmcRc */
+ 0x00000033, /* EmcRfc */
+ 0x00000007, /* EmcRas */
+ 0x00000002, /* EmcRp */
+ 0x00000003, /* EmcR2w */
+ 0x00000009, /* EmcW2r */
+ 0x00000005, /* EmcR2p */
+ 0x0000000a, /* EmcW2p */
+ 0x00000002, /* EmcRdRcd */
+ 0x00000002, /* EmcWrRcd */
+ 0x00000003, /* EmcRrd */
+ 0x00000001, /* EmcRext */
+ 0x00000000, /* EmcWext */
+ 0x00000004, /* EmcWdv */
+ 0x00000005, /* EmcQUse */
+ 0x00000004, /* EmcQRst */
+ 0x00000009, /* EmcQSafe */
+ 0x0000000b, /* EmcRdv */
+ 0x000005e9, /* EmcRefresh */
+ 0x00000000, /* EmcBurstRefreshNum */
+ 0x0000017a, /* EmcPreRefreshReqCnt */
+ 0x00000002, /* EmcPdEx2Wr */
+ 0x00000002, /* EmcPdEx2Rd */
+ 0x00000001, /* EmcPChg2Pden */
+ 0x00000000, /* EmcAct2Pden */
+ 0x00000007, /* EmcAr2Pden */
+ 0x0000000e, /* EmcRw2Pden */
+ 0x00000036, /* EmcTxsr */
+ 0x00000134, /* EmcTxsrDll */
+ 0x00000004, /* EmcTcke */
+ 0x0000000a, /* EmcTfaw */
+ 0x00000000, /* EmcTrpab */
+ 0x00000004, /* EmcTClkStable */
+ 0x00000005, /* EmcTClkStop */
+ 0x00000618, /* EmcTRefBw */
+ 0x00000006, /* EmcQUseExtra */
+ 0x00000004, /* EmcFbioCfg6 */
+ 0x00000000, /* EmcOdtWrite */
+ 0x00000000, /* EmcOdtRead */
+ 0x00004288, /* EmcFbioCfg5 */
+ 0x004600a4, /* EmcCfgDigDll */
+ 0x00008000, /* EmcCfgDigDllPeriod */
+ 0x00080000, /* EmcDllXformDqs0 */
+ 0x00080000, /* EmcDllXformDqs1 */
+ 0x00080000, /* EmcDllXformDqs2 */
+ 0x00080000, /* EmcDllXformDqs3 */
+ 0x00080000, /* EmcDllXformDqs4 */
+ 0x00080000, /* EmcDllXformDqs5 */
+ 0x00080000, /* EmcDllXformDqs6 */
+ 0x00080000, /* EmcDllXformDqs7 */
+ 0x00000000, /* EmcDllXformQUse0 */
+ 0x00000000, /* EmcDllXformQUse1 */
+ 0x00000000, /* EmcDllXformQUse2 */
+ 0x00000000, /* EmcDllXformQUse3 */
+ 0x00000000, /* EmcDllXformQUse4 */
+ 0x00000000, /* EmcDllXformQUse5 */
+ 0x00000000, /* EmcDllXformQUse6 */
+ 0x00000000, /* EmcDllXformQUse7 */
+ 0x00000000, /* EmcDliTrimTxDqs0 */
+ 0x00000000, /* EmcDliTrimTxDqs1 */
+ 0x00000000, /* EmcDliTrimTxDqs2 */
+ 0x00000000, /* EmcDliTrimTxDqs3 */
+ 0x00000000, /* EmcDliTrimTxDqs4 */
+ 0x00000000, /* EmcDliTrimTxDqs5 */
+ 0x00000000, /* EmcDliTrimTxDqs6 */
+ 0x00000000, /* EmcDliTrimTxDqs7 */
+ 0x00080000, /* EmcDllXformDq0 */
+ 0x00080000, /* EmcDllXformDq1 */
+ 0x00080000, /* EmcDllXformDq2 */
+ 0x00080000, /* EmcDllXformDq3 */
+ 0x000002a0, /* EmcXm2CmdPadCtrl */
+ 0x0800211c, /* EmcXm2DqsPadCtrl2 */
+ 0x00000000, /* EmcXm2DqPadCtrl2 */
+ 0x77fff884, /* EmcXm2ClkPadCtrl */
+ 0x01f1f108, /* EmcXm2CompPadCtrl */
+ 0x05057404, /* EmcXm2VttGenPadCtrl */
+ 0x54000007, /* EmcXm2VttGenPadCtrl2 */
+ 0x08000168, /* EmcXm2QUsePadCtrl */
+ 0x08000000, /* EmcXm2DqsPadCtrl3 */
+ 0x00000802, /* EmcCttTermCtrl */
+ 0x00020000, /* EmcZcalInterval */
+ 0x00000040, /* EmcZcalWaitCnt */
+ 0x000c000c, /* EmcMrsWaitCnt */
+ 0x001fffff, /* EmcAutoCalInterval */
+ 0x00000000, /* EmcCtt */
+ 0x00000000, /* EmcCttDuration */
+ 0x80000ce6, /* EmcDynSelfRefControl */
+ 0x00000003, /* McEmemArbCfg */
+ 0xc0000024, /* McEmemArbOutstandingReq */
+ 0x00000001, /* McEmemArbTimingRcd */
+ 0x00000001, /* McEmemArbTimingRp */
+ 0x00000005, /* McEmemArbTimingRc */
+ 0x00000002, /* McEmemArbTimingRas */
+ 0x00000004, /* McEmemArbTimingFaw */
+ 0x00000001, /* McEmemArbTimingRrd */
+ 0x00000003, /* McEmemArbTimingRap2Pre */
+ 0x00000007, /* McEmemArbTimingWap2Pre */
+ 0x00000002, /* McEmemArbTimingR2R */
+ 0x00000001, /* McEmemArbTimingW2W */
+ 0x00000003, /* McEmemArbTimingR2W */
+ 0x00000006, /* McEmemArbTimingW2R */
+ 0x06030102, /* McEmemArbDaTurns */
+ 0x00090505, /* McEmemArbDaCovers */
+ 0x76a30906, /* McEmemArbMisc0 */
+ 0x001f0000, /* McEmemArbRing1Throttle */
+ 0xe8000000, /* EmcFbioSpare */
+ 0xff00ff00, /* EmcCfgRsv */
+ },
+ 0x00000040, /* EmcZcalWaitCnt */
+ 0x00020000, /* EmcZcalInterval */
+ 0x00000001, /* EmcCfg bit 27PERIODIC_QRST */
+ 0x80001221, /* EmcMrs */
+ 0x80100003, /* EmcEmrs */
+ 0x00000000, /* EmcMrw1 */
+ 0x00000001, /* EmcCfg bit 28 DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 300000, /* SDRAM frequency [kHz] */
+ {
+ 0x00000010, /* EmcRc */
+ 0x0000004d, /* EmcRfc */
+ 0x0000000b, /* EmcRas */
+ 0x00000003, /* EmcRp */
+ 0x00000002, /* EmcR2w */
+ 0x00000008, /* EmcW2r */
+ 0x00000003, /* EmcR2p */
+ 0x00000009, /* EmcW2p */
+ 0x00000003, /* EmcRdRcd */
+ 0x00000002, /* EmcWrRcd */
+ 0x00000002, /* EmcRrd */
+ 0x00000001, /* EmcRext */
+ 0x00000000, /* EmcWext */
+ 0x00000004, /* EmcWdv */
+ 0x00000006, /* EmcQUse */
+ 0x00000004, /* EmcQRst */
+ 0x0000000a, /* EmcQSafe */
+ 0x0000000c, /* EmcRdv */
+ 0x000008e6, /* EmcRefresh */
+ 0x00000000, /* EmcBurstRefreshNum */
+ 0x00000240, /* EmcPreRefreshReqCnt */
+ 0x0000000a, /* EmcPdEx2Wr */
+ 0x00000008, /* EmcPdEx2Rd */
+ 0x00000007, /* EmcPChg2Pden */
+ 0x00000000, /* EmcAct2Pden */
+ 0x00000007, /* EmcAr2Pden */
+ 0x0000000e, /* EmcRw2Pden */
+ 0x000000b4, /* EmcTxsr */
+ 0x00000200, /* EmcTxsrDll */
+ 0x00000004, /* EmcTcke */
+ 0x00000010, /* EmcTfaw */
+ 0x00000000, /* EmcTrpab */
+ 0x00000004, /* EmcTClkStable */
+ 0x00000005, /* EmcTClkStop */
+ 0x00000927, /* EmcTRefBw */
+ 0x00000007, /* EmcQUseExtra */
+ 0x00000004, /* EmcFbioCfg6 */
+ 0x00000000, /* EmcOdtWrite */
+ 0x00000000, /* EmcOdtRead */
+ 0x00005288, /* EmcFbioCfg5 */
+ 0x002b00a4, /* EmcCfgDigDll */
+ 0x00008000, /* EmcCfgDigDllPeriod */
+ 0x00014000, /* EmcDllXformDqs0 */
+ 0x00014000, /* EmcDllXformDqs1 */
+ 0x00014000, /* EmcDllXformDqs2 */
+ 0x00014000, /* EmcDllXformDqs3 */
+ 0x00014000, /* EmcDllXformDqs4 */
+ 0x00014000, /* EmcDllXformDqs5 */
+ 0x00014000, /* EmcDllXformDqs6 */
+ 0x00014000, /* EmcDllXformDqs7 */
+ 0x00000000, /* EmcDllXformQUse0 */
+ 0x00000000, /* EmcDllXformQUse1 */
+ 0x00000000, /* EmcDllXformQUse2 */
+ 0x00000000, /* EmcDllXformQUse3 */
+ 0x00000000, /* EmcDllXformQUse4 */
+ 0x00000000, /* EmcDllXformQUse5 */
+ 0x00000000, /* EmcDllXformQUse6 */
+ 0x00000000, /* EmcDllXformQUse7 */
+ 0x00000000, /* EmcDliTrimTxDqs0 */
+ 0x00000000, /* EmcDliTrimTxDqs1 */
+ 0x00000000, /* EmcDliTrimTxDqs2 */
+ 0x00000000, /* EmcDliTrimTxDqs3 */
+ 0x00000000, /* EmcDliTrimTxDqs4 */
+ 0x00000000, /* EmcDliTrimTxDqs5 */
+ 0x00000000, /* EmcDliTrimTxDqs6 */
+ 0x00000000, /* EmcDliTrimTxDqs7 */
+ 0x00020000, /* EmcDllXformDq0 */
+ 0x00020000, /* EmcDllXformDq1 */
+ 0x00020000, /* EmcDllXformDq2 */
+ 0x00020000, /* EmcDllXformDq3 */
+ 0x000002a0, /* EmcXm2CmdPadCtrl */
+ 0x0800211c, /* EmcXm2DqsPadCtrl2 */
+ 0x00000000, /* EmcXm2DqPadCtrl2 */
+ 0x77fff884, /* EmcXm2ClkPadCtrl */
+ 0x01f1f508, /* EmcXm2CompPadCtrl */
+ 0x05057404, /* EmcXm2VttGenPadCtrl */
+ 0x54000007, /* EmcXm2VttGenPadCtrl2 */
+ 0x08000168, /* EmcXm2QUsePadCtrl */
+ 0x08000000, /* EmcXm2DqsPadCtrl3 */
+ 0x00000802, /* EmcCttTermCtrl */
+ 0x00020000, /* EmcZcalInterval */
+ 0x00000040, /* EmcZcalWaitCnt */
+ 0x0172000c, /* EmcMrsWaitCnt */
+ 0x001fffff, /* EmcAutoCalInterval */
+ 0x00000000, /* EmcCtt */
+ 0x00000000, /* EmcCttDuration */
+ 0x800012db, /* EmcDynSelfRefControl */
+ 0x00000004, /* McEmemArbCfg */
+ 0x80000037, /* McEmemArbOutstandingReq */
+ 0x00000001, /* McEmemArbTimingRcd */
+ 0x00000001, /* McEmemArbTimingRp */
+ 0x00000007, /* McEmemArbTimingRc */
+ 0x00000004, /* McEmemArbTimingRas */
+ 0x00000007, /* McEmemArbTimingFaw */
+ 0x00000001, /* McEmemArbTimingRrd */
+ 0x00000002, /* McEmemArbTimingRap2Pre */
+ 0x00000007, /* McEmemArbTimingWap2Pre */
+ 0x00000002, /* McEmemArbTimingR2R */
+ 0x00000002, /* McEmemArbTimingW2W */
+ 0x00000005, /* McEmemArbTimingR2W */
+ 0x00000006, /* McEmemArbTimingW2R */
+ 0x06030202, /* McEmemArbDaTurns */
+ 0x000a0507, /* McEmemArbDaCovers */
+ 0x70850e08, /* McEmemArbMisc0 */
+ 0x001f0000, /* McEmemArbRing1Throttle */
+ 0xe8000000, /* EmcFbioSpare */
+ 0xff00ff88, /* EmcCfgRsv */
+ },
+ 0x00000040, /* EmcZcalWaitCnt */
+ 0x00020000, /* EmcZcalInterval */
+ 0x00000001, /* EmcCfg bit 27PERIODIC_QRST */
+ 0x80000321, /* EmcMrs */
+ 0x80100002, /* EmcEmrs */
+ 0x00000000, /* EmcMrw1 */
+ 0x00000000, /* EmcCfg bit 28 DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 333000, /* SDRAM frequency [kHz] */
+ {
+ 0x00000010, /* EmcRc */
+ 0x00000055, /* EmcRfc */
+ 0x0000000c, /* EmcRas */
+ 0x00000004, /* EmcRp */
+ 0x00000006, /* EmcR2w */
+ 0x00000008, /* EmcW2r */
+ 0x00000003, /* EmcR2p */
+ 0x00000009, /* EmcW2p */
+ 0x00000004, /* EmcRdRcd */
+ 0x00000003, /* EmcWrRcd */
+ 0x00000002, /* EmcRrd */
+ 0x00000001, /* EmcRext */
+ 0x00000000, /* EmcWext */
+ 0x00000004, /* EmcWdv */
+ 0x00000006, /* EmcQUse */
+ 0x00000004, /* EmcQRst */
+ 0x0000000a, /* EmcQSafe */
+ 0x0000000c, /* EmcRdv */
+ 0x000009e8, /* EmcRefresh */
+ 0x00000000, /* EmcBurstRefreshNum */
+ 0x0000027e, /* EmcPreRefreshReqCnt */
+ 0x0000000a, /* EmcPdEx2Wr */
+ 0x00000008, /* EmcPdEx2Rd */
+ 0x00000007, /* EmcPChg2Pden */
+ 0x00000000, /* EmcAct2Pden */
+ 0x00000007, /* EmcAr2Pden */
+ 0x0000000e, /* EmcRw2Pden */
+ 0x000000b4, /* EmcTxsr */
+ 0x00000200, /* EmcTxsrDll */
+ 0x00000004, /* EmcTcke */
+ 0x00000015, /* EmcTfaw */
+ 0x00000000, /* EmcTrpab */
+ 0x00000004, /* EmcTClkStable */
+ 0x00000005, /* EmcTClkStop */
+ 0x00000a28, /* EmcTRefBw */
+ 0x00000000, /* EmcQUseExtra */
+ 0x00000006, /* EmcFbioCfg6 */
+ 0x00000000, /* EmcOdtWrite */
+ 0x00000000, /* EmcOdtRead */
+ 0x00007088, /* EmcFbioCfg5 */
+ 0x002600a4, /* EmcCfgDigDll */
+ 0x00008000, /* EmcCfgDigDllPeriod */
+ 0x00014000, /* EmcDllXformDqs0 */
+ 0x00014000, /* EmcDllXformDqs1 */
+ 0x00014000, /* EmcDllXformDqs2 */
+ 0x00014000, /* EmcDllXformDqs3 */
+ 0x00014000, /* EmcDllXformDqs4 */
+ 0x00014000, /* EmcDllXformDqs5 */
+ 0x00014000, /* EmcDllXformDqs6 */
+ 0x00014000, /* EmcDllXformDqs7 */
+ 0x00000000, /* EmcDllXformQUse0 */
+ 0x00000000, /* EmcDllXformQUse1 */
+ 0x00000000, /* EmcDllXformQUse2 */
+ 0x00000000, /* EmcDllXformQUse3 */
+ 0x00000000, /* EmcDllXformQUse4 */
+ 0x00000000, /* EmcDllXformQUse5 */
+ 0x00000000, /* EmcDllXformQUse6 */
+ 0x00000000, /* EmcDllXformQUse7 */
+ 0x00000000, /* EmcDliTrimTxDqs0 */
+ 0x00000000, /* EmcDliTrimTxDqs1 */
+ 0x00000000, /* EmcDliTrimTxDqs2 */
+ 0x00000000, /* EmcDliTrimTxDqs3 */
+ 0x00000000, /* EmcDliTrimTxDqs4 */
+ 0x00000000, /* EmcDliTrimTxDqs5 */
+ 0x00000000, /* EmcDliTrimTxDqs6 */
+ 0x00000000, /* EmcDliTrimTxDqs7 */
+ 0x00020000, /* EmcDllXformDq0 */
+ 0x00020000, /* EmcDllXformDq1 */
+ 0x00020000, /* EmcDllXformDq2 */
+ 0x00020000, /* EmcDllXformDq3 */
+ 0x000002a0, /* EmcXm2CmdPadCtrl */
+ 0x0800013d, /* EmcXm2DqsPadCtrl2 */
+ 0x00000000, /* EmcXm2DqPadCtrl2 */
+ 0x77fff884, /* EmcXm2ClkPadCtrl */
+ 0x01f1f508, /* EmcXm2CompPadCtrl */
+ 0x05057404, /* EmcXm2VttGenPadCtrl */
+ 0x54000007, /* EmcXm2VttGenPadCtrl2 */
+ 0x080001e8, /* EmcXm2QUsePadCtrl */
+ 0x08000021, /* EmcXm2DqsPadCtrl3 */
+ 0x00000802, /* EmcCttTermCtrl */
+ 0x00020000, /* EmcZcalInterval */
+ 0x00000040, /* EmcZcalWaitCnt */
+ 0x016a000c, /* EmcMrsWaitCnt */
+ 0x001fffff, /* EmcAutoCalInterval */
+ 0x00000000, /* EmcCtt */
+ 0x00000000, /* EmcCttDuration */
+ 0x800014d2, /* EmcDynSelfRefControl */
+ 0x00000005, /* McEmemArbCfg */
+ 0x8000003c, /* McEmemArbOutstandingReq */
+ 0x00000001, /* McEmemArbTimingRcd */
+ 0x00000002, /* McEmemArbTimingRp */
+ 0x00000008, /* McEmemArbTimingRc */
+ 0x00000005, /* McEmemArbTimingRas */
+ 0x0000000a, /* McEmemArbTimingFaw */
+ 0x00000001, /* McEmemArbTimingRrd */
+ 0x00000002, /* McEmemArbTimingRap2Pre */
+ 0x00000007, /* McEmemArbTimingWap2Pre */
+ 0x00000002, /* McEmemArbTimingR2R */
+ 0x00000002, /* McEmemArbTimingW2W */
+ 0x00000005, /* McEmemArbTimingR2W */
+ 0x00000006, /* McEmemArbTimingW2R */
+ 0x06030202, /* McEmemArbDaTurns */
+ 0x000b0608, /* McEmemArbDaCovers */
+ 0x70850f09, /* McEmemArbMisc0 */
+ 0x001f0000, /* McEmemArbRing1Throttle */
+ 0xe8000000, /* EmcFbioSpare */
+ 0xff00ff88, /* EmcCfgRsv */
+ },
+ 0x00000040, /* EmcZcalWaitCnt */
+ 0x00020000, /* EmcZcalInterval */
+ 0x00000000, /* EmcCfg bit 27PERIODIC_QRST */
+ 0x80000321, /* EmcMrs */
+ 0x80100002, /* EmcEmrs */
+ 0x00000000, /* EmcMrw1 */
+ 0x00000000, /* EmcCfg bit 28 DYN_SELF_REF */
+ },
+//copy of 333 MHz
+ {
+ 0x32, /* Rev 3.2 */
+ 408000, /* SDRAM frequency [kHz] */
+ {
+ 0x00000010, /* EmcRc */
+ 0x00000055, /* EmcRfc */
+ 0x0000000c, /* EmcRas */
+ 0x00000004, /* EmcRp */
+ 0x00000006, /* EmcR2w */
+ 0x00000008, /* EmcW2r */
+ 0x00000003, /* EmcR2p */
+ 0x00000009, /* EmcW2p */
+ 0x00000004, /* EmcRdRcd */
+ 0x00000003, /* EmcWrRcd */
+ 0x00000002, /* EmcRrd */
+ 0x00000001, /* EmcRext */
+ 0x00000000, /* EmcWext */
+ 0x00000004, /* EmcWdv */
+ 0x00000006, /* EmcQUse */
+ 0x00000004, /* EmcQRst */
+ 0x0000000a, /* EmcQSafe */
+ 0x0000000c, /* EmcRdv */
+ 0x000009e8, /* EmcRefresh */
+ 0x00000000, /* EmcBurstRefreshNum */
+ 0x0000027e, /* EmcPreRefreshReqCnt */
+ 0x0000000a, /* EmcPdEx2Wr */
+ 0x00000008, /* EmcPdEx2Rd */
+ 0x00000007, /* EmcPChg2Pden */
+ 0x00000000, /* EmcAct2Pden */
+ 0x00000007, /* EmcAr2Pden */
+ 0x0000000e, /* EmcRw2Pden */
+ 0x000000b4, /* EmcTxsr */
+ 0x00000200, /* EmcTxsrDll */
+ 0x00000004, /* EmcTcke */
+ 0x00000015, /* EmcTfaw */
+ 0x00000000, /* EmcTrpab */
+ 0x00000004, /* EmcTClkStable */
+ 0x00000005, /* EmcTClkStop */
+ 0x00000a28, /* EmcTRefBw */
+ 0x00000000, /* EmcQUseExtra */
+ 0x00000006, /* EmcFbioCfg6 */
+ 0x00000000, /* EmcOdtWrite */
+ 0x00000000, /* EmcOdtRead */
+ 0x00007088, /* EmcFbioCfg5 */
+ 0x002600a4, /* EmcCfgDigDll */
+ 0x00008000, /* EmcCfgDigDllPeriod */
+ 0x00014000, /* EmcDllXformDqs0 */
+ 0x00014000, /* EmcDllXformDqs1 */
+ 0x00014000, /* EmcDllXformDqs2 */
+ 0x00014000, /* EmcDllXformDqs3 */
+ 0x00014000, /* EmcDllXformDqs4 */
+ 0x00014000, /* EmcDllXformDqs5 */
+ 0x00014000, /* EmcDllXformDqs6 */
+ 0x00014000, /* EmcDllXformDqs7 */
+ 0x00000000, /* EmcDllXformQUse0 */
+ 0x00000000, /* EmcDllXformQUse1 */
+ 0x00000000, /* EmcDllXformQUse2 */
+ 0x00000000, /* EmcDllXformQUse3 */
+ 0x00000000, /* EmcDllXformQUse4 */
+ 0x00000000, /* EmcDllXformQUse5 */
+ 0x00000000, /* EmcDllXformQUse6 */
+ 0x00000000, /* EmcDllXformQUse7 */
+ 0x00000000, /* EmcDliTrimTxDqs0 */
+ 0x00000000, /* EmcDliTrimTxDqs1 */
+ 0x00000000, /* EmcDliTrimTxDqs2 */
+ 0x00000000, /* EmcDliTrimTxDqs3 */
+ 0x00000000, /* EmcDliTrimTxDqs4 */
+ 0x00000000, /* EmcDliTrimTxDqs5 */
+ 0x00000000, /* EmcDliTrimTxDqs6 */
+ 0x00000000, /* EmcDliTrimTxDqs7 */
+ 0x00020000, /* EmcDllXformDq0 */
+ 0x00020000, /* EmcDllXformDq1 */
+ 0x00020000, /* EmcDllXformDq2 */
+ 0x00020000, /* EmcDllXformDq3 */
+ 0x000002a0, /* EmcXm2CmdPadCtrl */
+ 0x0800013d, /* EmcXm2DqsPadCtrl2 */
+ 0x00000000, /* EmcXm2DqPadCtrl2 */
+ 0x77fff884, /* EmcXm2ClkPadCtrl */
+ 0x01f1f508, /* EmcXm2CompPadCtrl */
+ 0x05057404, /* EmcXm2VttGenPadCtrl */
+ 0x54000007, /* EmcXm2VttGenPadCtrl2 */
+ 0x080001e8, /* EmcXm2QUsePadCtrl */
+ 0x08000021, /* EmcXm2DqsPadCtrl3 */
+ 0x00000802, /* EmcCttTermCtrl */
+ 0x00020000, /* EmcZcalInterval */
+ 0x00000040, /* EmcZcalWaitCnt */
+ 0x016a000c, /* EmcMrsWaitCnt */
+ 0x001fffff, /* EmcAutoCalInterval */
+ 0x00000000, /* EmcCtt */
+ 0x00000000, /* EmcCttDuration */
+ 0x800014d2, /* EmcDynSelfRefControl */
+ 0x00000005, /* McEmemArbCfg */
+ 0x8000003c, /* McEmemArbOutstandingReq */
+ 0x00000001, /* McEmemArbTimingRcd */
+ 0x00000002, /* McEmemArbTimingRp */
+ 0x00000008, /* McEmemArbTimingRc */
+ 0x00000005, /* McEmemArbTimingRas */
+ 0x0000000a, /* McEmemArbTimingFaw */
+ 0x00000001, /* McEmemArbTimingRrd */
+ 0x00000002, /* McEmemArbTimingRap2Pre */
+ 0x00000007, /* McEmemArbTimingWap2Pre */
+ 0x00000002, /* McEmemArbTimingR2R */
+ 0x00000002, /* McEmemArbTimingW2W */
+ 0x00000005, /* McEmemArbTimingR2W */
+ 0x00000006, /* McEmemArbTimingW2R */
+ 0x06030202, /* McEmemArbDaTurns */
+ 0x000b0608, /* McEmemArbDaCovers */
+ 0x70850f09, /* McEmemArbMisc0 */
+ 0x001f0000, /* McEmemArbRing1Throttle */
+ 0xe8000000, /* EmcFbioSpare */
+ 0xff00ff88, /* EmcCfgRsv */
+ },
+ 0x00000040, /* EmcZcalWaitCnt */
+ 0x00020000, /* EmcZcalInterval */
+ 0x00000000, /* EmcCfg bit 27PERIODIC_QRST */
+ 0x80000321, /* EmcMrs */
+ 0x80100002, /* EmcEmrs */
+ 0x00000000, /* EmcMrw1 */
+ 0x00000000, /* EmcCfg bit 28 DYN_SELF_REF */
+ },
+};
+
+int colibri_t30_emc_init(void)
+{
+//27, 54, 108, 416, 533
+//25.5, 51, 102, 408, 533, 750
+//25.5, 51, 102, 204, 533
+ tegra_init_emc(colibri_t30_emc_tables_mt41k256m16re_15e,
+ ARRAY_SIZE(colibri_t30_emc_tables_mt41k256m16re_15e));
+
+ return 0;
+}
diff --git a/arch/arm/mach-tegra/board-colibri_t30-panel.c b/arch/arm/mach-tegra/board-colibri_t30-panel.c
new file mode 100644
index 000000000000..dd2751428a28
--- /dev/null
+++ b/arch/arm/mach-tegra/board-colibri_t30-panel.c
@@ -0,0 +1,806 @@
+/*
+ * arch/arm/mach-tegra/board-colibri_t30-panel.c
+ *
+ * Copyright (c) 2012, Toradex, Inc.
+ *
+ * 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.
+ */
+
+#include <asm/atomic.h>
+#include <asm/mach-types.h>
+
+#include <linux/delay.h>
+#include <linux/earlysuspend.h>
+#include <linux/gpio.h>
+#include <linux/ion.h>
+#include <linux/nvhost.h>
+#include <linux/nvmap.h>
+#include <linux/platform_device.h>
+#include <linux/pwm_backlight.h>
+#include <linux/regulator/consumer.h>
+#include <linux/resource.h>
+#include <linux/tegra_ion.h>
+
+#include <mach/dc.h>
+#include <mach/fb.h>
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+#include <mach/smmu.h>
+
+#include "board.h"
+#include "board-colibri_t30.h"
+#include "devices.h"
+#include "gpio-names.h"
+#include "tegra3_host1x_devices.h"
+
+#ifndef COLIBRI_T30_VI
+#define colibri_t30_bl_enb TEGRA_GPIO_PV2 /* BL_ON */
+#endif
+#define colibri_t30_hdmi_hpd TEGRA_GPIO_PN7 /* HDMI_INT_N */
+
+static struct regulator *colibri_t30_hdmi_pll = NULL;
+static struct regulator *colibri_t30_hdmi_reg = NULL;
+static struct regulator *colibri_t30_hdmi_vddio = NULL;
+
+#ifndef COLIBRI_T30_VI
+static int colibri_t30_backlight_init(struct device *dev) {
+ int ret;
+
+ ret = gpio_request(colibri_t30_bl_enb, "BL_ON");
+ if (ret < 0)
+ return ret;
+
+ ret = gpio_direction_output(colibri_t30_bl_enb, 1);
+ if (ret < 0)
+ gpio_free(colibri_t30_bl_enb);
+
+ return ret;
+};
+
+static void colibri_t30_backlight_exit(struct device *dev) {
+ gpio_set_value(colibri_t30_bl_enb, 0);
+ gpio_free(colibri_t30_bl_enb);
+}
+
+static int colibri_t30_backlight_notify(struct device *dev, int brightness)
+{
+ struct platform_pwm_backlight_data *pdata = dev->platform_data;
+
+ gpio_set_value(colibri_t30_bl_enb, !!brightness);
+
+ /* Unified TFT interface displays (e.g. EDT ET070080DH6) LEDCTRL pin
+ with inverted behaviour (e.g. 0V brightest vs. 3.3V darkest)
+ Note: brightness polarity display model specific */
+ if (brightness) return pdata->max_brightness - brightness;
+ else return brightness;
+}
+
+static int colibri_t30_disp1_check_fb(struct device *dev, struct fb_info *info);
+
+static struct platform_pwm_backlight_data colibri_t30_backlight_data = {
+ .pwm_id = 0,
+ .max_brightness = 255,
+ .dft_brightness = 127,
+ .pwm_period_ns = 1000000, /* 1 kHz */
+ .init = colibri_t30_backlight_init,
+ .exit = colibri_t30_backlight_exit,
+ .notify = colibri_t30_backlight_notify,
+ /* Only toggle backlight on fb blank notifications for disp1 */
+ .check_fb = colibri_t30_disp1_check_fb,
+};
+
+static struct platform_device colibri_t30_backlight_device = {
+ .name = "pwm-backlight",
+ .id = -1,
+ .dev = {
+ .platform_data = &colibri_t30_backlight_data,
+ },
+};
+#endif /* !COLIBRI_T30_VI */
+
+static int colibri_t30_panel_enable(void)
+{
+ return 0;
+}
+
+static int colibri_t30_panel_disable(void)
+{
+ return 0;
+}
+
+#ifdef CONFIG_TEGRA_DC
+static int colibri_t30_hdmi_vddio_enable(void)
+{
+ int ret;
+ if (!colibri_t30_hdmi_vddio) {
+ colibri_t30_hdmi_vddio = regulator_get(NULL, "vdd_hdmi_con");
+ if (IS_ERR_OR_NULL(colibri_t30_hdmi_vddio)) {
+ ret = PTR_ERR(colibri_t30_hdmi_vddio);
+ pr_err("hdmi: couldn't get regulator vdd_hdmi_con\n");
+ colibri_t30_hdmi_vddio = NULL;
+ return ret;
+ }
+ }
+ ret = regulator_enable(colibri_t30_hdmi_vddio);
+ if (ret < 0) {
+ pr_err("hdmi: couldn't enable regulator vdd_hdmi_con\n");
+ regulator_put(colibri_t30_hdmi_vddio);
+ colibri_t30_hdmi_vddio = NULL;
+ return ret;
+ }
+ return ret;
+}
+
+static int colibri_t30_hdmi_vddio_disable(void)
+{
+ if (colibri_t30_hdmi_vddio) {
+ regulator_disable(colibri_t30_hdmi_vddio);
+ regulator_put(colibri_t30_hdmi_vddio);
+ colibri_t30_hdmi_vddio = NULL;
+ }
+ return 0;
+}
+
+static int colibri_t30_hdmi_enable(void)
+{
+ int ret;
+ if (!colibri_t30_hdmi_reg) {
+ colibri_t30_hdmi_reg = regulator_get(NULL, "avdd_hdmi");
+ if (IS_ERR_OR_NULL(colibri_t30_hdmi_reg)) {
+ pr_err("hdmi: couldn't get regulator avdd_hdmi\n");
+ colibri_t30_hdmi_reg = NULL;
+ return PTR_ERR(colibri_t30_hdmi_reg);
+ }
+ }
+ ret = regulator_enable(colibri_t30_hdmi_reg);
+ if (ret < 0) {
+ pr_err("hdmi: couldn't enable regulator avdd_hdmi\n");
+ return ret;
+ }
+ if (!colibri_t30_hdmi_pll) {
+ colibri_t30_hdmi_pll = regulator_get(NULL, "avdd_hdmi_pll");
+ if (IS_ERR_OR_NULL(colibri_t30_hdmi_pll)) {
+ pr_err("hdmi: couldn't get regulator avdd_hdmi_pll\n");
+ colibri_t30_hdmi_pll = NULL;
+ regulator_put(colibri_t30_hdmi_reg);
+ colibri_t30_hdmi_reg = NULL;
+ return PTR_ERR(colibri_t30_hdmi_pll);
+ }
+ }
+ ret = regulator_enable(colibri_t30_hdmi_pll);
+ if (ret < 0) {
+ pr_err("hdmi: couldn't enable regulator avdd_hdmi_pll\n");
+ return ret;
+ }
+ return 0;
+}
+
+static int colibri_t30_hdmi_disable(void)
+{
+ regulator_disable(colibri_t30_hdmi_reg);
+ regulator_put(colibri_t30_hdmi_reg);
+ colibri_t30_hdmi_reg = NULL;
+
+ regulator_disable(colibri_t30_hdmi_pll);
+ regulator_put(colibri_t30_hdmi_pll);
+ colibri_t30_hdmi_pll = NULL;
+ return 0;
+}
+static struct resource colibri_t30_disp1_resources[] = {
+ {
+ .name = "irq",
+ .start = INT_DISPLAY_GENERAL,
+ .end = INT_DISPLAY_GENERAL,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "regs",
+ .start = TEGRA_DISPLAY_BASE,
+ .end = TEGRA_DISPLAY_BASE + TEGRA_DISPLAY_SIZE-1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "fbmem",
+ .start = 0, /* Filled in by colibri_t30_panel_init() */
+ .end = 0, /* Filled in by colibri_t30_panel_init() */
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct resource colibri_t30_disp2_resources[] = {
+ {
+ .name = "irq",
+ .start = INT_DISPLAY_B_GENERAL,
+ .end = INT_DISPLAY_B_GENERAL,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "regs",
+ .start = TEGRA_DISPLAY2_BASE,
+ .end = TEGRA_DISPLAY2_BASE + TEGRA_DISPLAY2_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "fbmem",
+ .flags = IORESOURCE_MEM,
+ .start = 0,
+ .end = 0,
+ },
+ {
+ .name = "hdmi_regs",
+ .start = TEGRA_HDMI_BASE,
+ .end = TEGRA_HDMI_BASE + TEGRA_HDMI_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+#endif /* CONFIG_TEGRA_DC */
+
+static struct tegra_dc_mode colibri_t30_panel_modes[] = {
+#ifdef TEGRA_FB_VGA
+ {
+ /* 640x480p 60hz: EIA/CEA-861-B Format 1 */
+ .pclk = 25175000, /* pixclock */
+ .h_ref_to_sync = 8,
+ .v_ref_to_sync = 2,
+ .h_sync_width = 96, /* hsync_len */
+ .v_sync_width = 2, /* vsync_len */
+ .h_back_porch = 48, /* left_margin */
+ .v_back_porch = 33, /* upper_margin */
+ .h_active = 640,
+ .v_active = 480,
+ .h_front_porch = 16, /* right_margin */
+ .v_front_porch = 10, /* lower_margin */
+ },
+#else /* TEGRA_FB_VGA */
+ {
+ /* 800x480@60 (e.g. EDT ET070080DH6) */
+ .pclk = 32460000,
+ .h_ref_to_sync = 1,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 64,
+ .v_sync_width = 3,
+ .h_back_porch = 128,
+ .v_back_porch = 22,
+ .h_active = 800,
+ .v_active = 480,
+ .h_front_porch = 64,
+ .v_front_porch = 20,
+ },
+ {
+ /* 800x600@60 */
+ .pclk = 39272727,
+ .h_sync_width = 80,
+ .v_sync_width = 2,
+ .h_back_porch = 160,
+ .v_back_porch = 21,
+ .h_active = 800,
+ .v_active = 600,
+ .h_front_porch = 16,
+ .v_front_porch = 1,
+ },
+ {
+ /* TouchRevolution Fusion 10 aka Chunghwa Picture Tubes
+ CLAA101NC05 10.1 inch 1024x600 single channel LVDS panel */
+ .pclk = 48000000,
+ .h_sync_width = 5,
+ .v_sync_width = 5,
+ .h_back_porch = 104,
+ .v_back_porch = 24,
+ .h_active = 1024,
+ .v_active = 600,
+ .h_front_porch = 43,
+ .v_front_porch = 20,
+ },
+ {
+ /* 1024x768@60 */
+ .pclk = 78800000,
+ .h_sync_width = 96,
+ .v_sync_width = 3,
+ .h_back_porch = 176,
+ .v_back_porch = 28,
+ .h_active = 1024,
+ .v_active = 768,
+ .h_front_porch = 16,
+ .v_front_porch = 1,
+ },
+ {
+ /* 1024x768@75 */
+ .pclk = 82000000,
+ .h_sync_width = 104,
+ .v_sync_width = 4,
+ .h_back_porch = 168,
+ .v_back_porch = 34,
+ .h_active = 1024,
+ .v_active = 768,
+ .h_front_porch = 64,
+ .v_front_porch = 3,
+ },
+ {
+ /* 1280x720@60 */
+ .pclk = 74250000,
+ .h_ref_to_sync = 1,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 40,
+ .v_sync_width = 5,
+ .h_back_porch = 220,
+ .v_back_porch = 20,
+ .h_active = 1280,
+ .v_active = 720,
+ .h_front_porch = 110,
+ .v_front_porch = 5,
+//high active sync polarities
+ },
+ {
+ /* 1280x1024@60 */
+ .pclk = 108000000,
+// .h_ref_to_sync = 1,
+// .v_ref_to_sync = 1,
+ .h_sync_width = 144,
+ .v_sync_width = 3,
+ .h_back_porch = 248,
+ .v_back_porch = 38,
+ .h_active = 1280,
+ .v_active = 1024,
+ .h_front_porch = 16,
+ .v_front_porch = 1,
+//high active sync polarities
+ },
+ {
+ /* 1366x768@60 */
+ .pclk = 72072000,
+ .h_ref_to_sync = 11,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 58,
+ .v_sync_width = 4,
+ .h_back_porch = 58,
+ .v_back_porch = 4,
+ .h_active = 1366,
+ .v_active = 768,
+ .h_front_porch = 58,
+ .v_front_porch = 4,
+ },
+ {
+ /* 1600x1200@60 */
+ .pclk = 162000000,
+// .h_ref_to_sync = 1,
+// .v_ref_to_sync = 1,
+ .h_sync_width = 192,
+ .v_sync_width = 3,
+ .h_back_porch = 304,
+ .v_back_porch = 46,
+ .h_active = 1600,
+ .v_active = 1200,
+ .h_front_porch = 64,
+ .v_front_porch = 1,
+//high active sync polarities
+ },
+ {
+ .pclk = 119000000,
+ .h_ref_to_sync = 1,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 32,
+ .v_sync_width = 6,
+ .h_back_porch = 80,
+ .v_back_porch = 21,
+ .h_active = 1680,
+ .v_active = 1050,
+ .h_front_porch = 48,
+ .v_front_porch = 3,
+ },
+ {
+ /* 1680x1050@60 */
+ .pclk = 147140000,
+// .h_ref_to_sync = 1,
+// .v_ref_to_sync = 1,
+ .h_sync_width = 184,
+ .v_sync_width = 3,
+ .h_back_porch = 288,
+ .v_back_porch = 33,
+ .h_active = 1680,
+ .v_active = 1050,
+ .h_front_porch = 104,
+ .v_front_porch = 1,
+//high active vertical sync polarity
+ },
+ {
+ /* 1920x1080p 59.94/60hz EIA/CEA-861-B Format 16 */
+ .pclk = 148500000,
+ .h_ref_to_sync = 11,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 44,
+ .v_sync_width = 5,
+ .h_back_porch = 148,
+ .v_back_porch = 36,
+ .h_active = 1920,
+ .v_active = 1080,
+ .h_front_porch = 88,
+ .v_front_porch = 4,
+//high active sync polarities
+ },
+ {
+ .pclk = 154000000,
+ .h_ref_to_sync = 11,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 32,
+ .v_sync_width = 6,
+ .h_back_porch = 80,
+ .v_back_porch = 26,
+ .h_active = 1920,
+ .v_active = 1200,
+ .h_front_porch = 48,
+ .v_front_porch = 3,
+ },
+
+ /* portrait modes */
+
+ {
+ .pclk = 18000000,
+ .h_ref_to_sync = 8,
+ .v_ref_to_sync = 2,
+ .h_sync_width = 4,
+ .v_sync_width = 1,
+ .h_back_porch = 20,
+ .v_back_porch = 7,
+ .h_active = 480,
+ .v_active = 640,
+ .h_front_porch = 8,
+ .v_front_porch = 8,
+ },
+ {
+ .pclk = 10000000,
+ .h_ref_to_sync = 4,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 16,
+ .v_sync_width = 1,
+ .h_back_porch = 32,
+ .v_back_porch = 1,
+ .h_active = 540,
+ .v_active = 960,
+ .h_front_porch = 32,
+ .v_front_porch = 2,
+ },
+ {
+ .pclk = 61417000,
+ .h_ref_to_sync = 2,
+ .v_ref_to_sync = 2,
+ .h_sync_width = 4,
+ .v_sync_width = 4,
+ .h_back_porch = 100,
+ .v_back_porch = 14,
+ .h_active = 720,
+ .v_active = 1280,
+ .h_front_porch = 4,
+ .v_front_porch = 4,
+ },
+#endif /* TEGRA_FB_VGA */
+};
+
+#ifdef CONFIG_TEGRA_DC
+static struct tegra_fb_data colibri_t30_fb_data = {
+ .win = 0,
+#ifdef TEGRA_FB_VGA
+ .xres = 640,
+ .yres = 480,
+#else /* TEGRA_FB_VGA */
+ .xres = 800,
+ .yres = 480,
+#endif /* TEGRA_FB_VGA */
+ .bits_per_pixel = 16,
+ .flags = TEGRA_FB_FLIP_ON_PROBE,
+};
+
+static struct tegra_fb_data colibri_t30_hdmi_fb_data = {
+ .win = 0,
+ .xres = 640,
+ .yres = 480,
+ .bits_per_pixel = 16,
+ .flags = TEGRA_FB_FLIP_ON_PROBE,
+};
+
+static struct tegra_dc_out_pin colibri_t30_dc_out_pins[] = {
+ {
+ .name = TEGRA_DC_OUT_PIN_H_SYNC,
+ .pol = TEGRA_DC_OUT_PIN_POL_LOW,
+ },
+ {
+ .name = TEGRA_DC_OUT_PIN_V_SYNC,
+ .pol = TEGRA_DC_OUT_PIN_POL_LOW,
+ },
+ {
+ .name = TEGRA_DC_OUT_PIN_PIXEL_CLOCK,
+ .pol = TEGRA_DC_OUT_PIN_POL_LOW,
+ },
+};
+
+static struct tegra_dc_out colibri_t30_disp1_out = {
+ .type = TEGRA_DC_OUT_RGB,
+ .parent_clk = "pll_d_out0",
+ .parent_clk_backup = "pll_d2_out0",
+
+ .align = TEGRA_DC_ALIGN_MSB,
+ .order = TEGRA_DC_ORDER_RED_BLUE,
+ .depth = 18,
+ .dither = TEGRA_DC_ORDERED_DITHER,
+
+ .modes = colibri_t30_panel_modes,
+ .n_modes = ARRAY_SIZE(colibri_t30_panel_modes),
+
+ .out_pins = colibri_t30_dc_out_pins,
+ .n_out_pins = ARRAY_SIZE(colibri_t30_dc_out_pins),
+
+ .enable = colibri_t30_panel_enable,
+ .disable = colibri_t30_panel_disable,
+};
+
+static struct tegra_dc_out colibri_t30_disp2_out = {
+ .type = TEGRA_DC_OUT_HDMI,
+ .flags = TEGRA_DC_OUT_HOTPLUG_HIGH,
+ .parent_clk = "pll_d2_out0",
+
+ .dcc_bus = 3,
+ .hotplug_gpio = colibri_t30_hdmi_hpd,
+
+ .max_pixclock = KHZ2PICOS(148500),
+
+ .align = TEGRA_DC_ALIGN_MSB,
+ .order = TEGRA_DC_ORDER_RED_BLUE,
+
+ .enable = colibri_t30_hdmi_enable,
+ .disable = colibri_t30_hdmi_disable,
+
+ .postsuspend = colibri_t30_hdmi_vddio_disable,
+ .hotplug_init = colibri_t30_hdmi_vddio_enable,
+};
+
+static struct tegra_dc_platform_data colibri_t30_disp1_pdata = {
+ .flags = TEGRA_DC_FLAG_ENABLED,
+ .default_out = &colibri_t30_disp1_out,
+ .emc_clk_rate = 300000000,
+ .fb = &colibri_t30_fb_data,
+};
+
+static struct tegra_dc_platform_data colibri_t30_disp2_pdata = {
+ .flags = TEGRA_DC_FLAG_ENABLED,
+ .default_out = &colibri_t30_disp2_out,
+ .fb = &colibri_t30_hdmi_fb_data,
+ .emc_clk_rate = 300000000,
+};
+
+static struct nvhost_device colibri_t30_disp1_device = {
+ .name = "tegradc",
+ .id = 0,
+ .resource = colibri_t30_disp1_resources,
+ .num_resources = ARRAY_SIZE(colibri_t30_disp1_resources),
+ .dev = {
+ .platform_data = &colibri_t30_disp1_pdata,
+ },
+};
+
+#ifndef COLIBRI_T30_VI
+static int colibri_t30_disp1_check_fb(struct device *dev, struct fb_info *info)
+{
+ return info->device == &colibri_t30_disp1_device.dev;
+}
+#endif /* !COLIBRI_T30_VI */
+
+static struct nvhost_device colibri_t30_disp2_device = {
+ .name = "tegradc",
+ .id = 1,
+ .resource = colibri_t30_disp2_resources,
+ .num_resources = ARRAY_SIZE(colibri_t30_disp2_resources),
+ .dev = {
+ .platform_data = &colibri_t30_disp2_pdata,
+ },
+};
+#else /* CONFIG_TEGRA_DC */
+static int colibri_t30_disp1_check_fb(struct device *dev, struct fb_info *info)
+{
+ return 0;
+}
+#endif /* CONFIG_TEGRA_DC */
+
+#if defined(CONFIG_TEGRA_NVMAP)
+static struct nvmap_platform_carveout colibri_t30_carveouts[] = {
+ [0] = NVMAP_HEAP_CARVEOUT_IRAM_INIT,
+ [1] = {
+ .name = "generic-0",
+ .usage_mask = NVMAP_HEAP_CARVEOUT_GENERIC,
+ .base = 0, /* Filled in by colibri_t30_panel_init() */
+ .size = 0, /* Filled in by colibri_t30_panel_init() */
+ .buddy_size = SZ_32K,
+ },
+};
+
+static struct nvmap_platform_data colibri_t30_nvmap_data = {
+ .carveouts = colibri_t30_carveouts,
+ .nr_carveouts = ARRAY_SIZE(colibri_t30_carveouts),
+};
+
+static struct platform_device colibri_t30_nvmap_device = {
+ .name = "tegra-nvmap",
+ .id = -1,
+ .dev = {
+ .platform_data = &colibri_t30_nvmap_data,
+ },
+};
+#endif /* CONFIG_TEGRA_NVMAP */
+
+#if defined(CONFIG_ION_TEGRA)
+static struct platform_device tegra_iommu_device = {
+ .name = "tegra_iommu_device",
+ .id = -1,
+ .dev = {
+ .platform_data = (void *)((1 << HWGRP_COUNT) - 1),
+ },
+};
+
+static struct ion_platform_data tegra_ion_data = {
+ .nr = 4,
+ .heaps = {
+ {
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .id = TEGRA_ION_HEAP_CARVEOUT,
+ .name = "carveout",
+ .base = 0,
+ .size = 0,
+ },
+ {
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .id = TEGRA_ION_HEAP_IRAM,
+ .name = "iram",
+ .base = TEGRA_IRAM_BASE + TEGRA_RESET_HANDLER_SIZE,
+ .size = TEGRA_IRAM_SIZE - TEGRA_RESET_HANDLER_SIZE,
+ },
+ {
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .id = TEGRA_ION_HEAP_VPR,
+ .name = "vpr",
+ .base = 0,
+ .size = 0,
+ },
+ {
+ .type = ION_HEAP_TYPE_IOMMU,
+ .id = TEGRA_ION_HEAP_IOMMU,
+ .name = "iommu",
+ .base = TEGRA_SMMU_BASE,
+ .size = TEGRA_SMMU_SIZE,
+ .priv = &tegra_iommu_device.dev,
+ },
+ },
+};
+
+static struct platform_device tegra_ion_device = {
+ .name = "ion-tegra",
+ .id = -1,
+ .dev = {
+ .platform_data = &tegra_ion_data,
+ },
+};
+#endif /* CONFIG_ION_TEGRA */
+
+static struct platform_device *colibri_t30_gfx_devices[] __initdata = {
+#if defined(CONFIG_TEGRA_NVMAP)
+ &colibri_t30_nvmap_device,
+#endif
+#if defined(CONFIG_ION_TEGRA)
+ &tegra_ion_device,
+#endif
+#ifndef COLIBRI_T30_VI
+ &tegra_pwfm0_device,
+ &colibri_t30_backlight_device,
+#endif /* !COLIBRI_T30_VI */
+};
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+/* put early_suspend/late_resume handlers here for the display in order
+ * to keep the code out of the display driver, keeping it closer to upstream
+ */
+struct early_suspend colibri_t30_panel_early_suspender;
+
+static void colibri_t30_panel_early_suspend(struct early_suspend *h)
+{
+ /* power down LCD, add use a black screen for HDMI */
+ if (num_registered_fb > 0)
+ fb_blank(registered_fb[0], FB_BLANK_POWERDOWN);
+ if (num_registered_fb > 1)
+ fb_blank(registered_fb[1], FB_BLANK_NORMAL);
+}
+
+static void colibri_t30_panel_late_resume(struct early_suspend *h)
+{
+ unsigned i;
+ for (i = 0; i < num_registered_fb; i++)
+ fb_blank(registered_fb[i], FB_BLANK_UNBLANK);
+}
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+int __init colibri_t30_panel_init(void)
+{
+ int err = 0;
+ struct resource *res;
+ void __iomem *to_io;
+
+ /* enable hdmi hotplug gpio for hotplug detection */
+ gpio_request(colibri_t30_hdmi_hpd, "hdmi_hpd");
+ gpio_direction_input(colibri_t30_hdmi_hpd);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ colibri_t30_panel_early_suspender.suspend = colibri_t30_panel_early_suspend;
+ colibri_t30_panel_early_suspender.resume = colibri_t30_panel_late_resume;
+ colibri_t30_panel_early_suspender.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
+ register_early_suspend(&colibri_t30_panel_early_suspender);
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+#ifdef CONFIG_TEGRA_NVMAP
+ colibri_t30_carveouts[1].base = tegra_carveout_start;
+ colibri_t30_carveouts[1].size = tegra_carveout_size;
+#endif /* CONFIG_TEGRA_NVMAP */
+
+#ifdef CONFIG_ION_TEGRA
+ tegra_ion_data.heaps[0].base = tegra_carveout_start;
+ tegra_ion_data.heaps[0].size = tegra_carveout_size;
+#endif /* CONFIG_ION_TEGRA */
+
+#ifdef CONFIG_TEGRA_GRHOST
+ err = tegra3_register_host1x_devices();
+ if (err)
+ return err;
+#endif /* CONFIG_TEGRA_GRHOST */
+
+ err = platform_add_devices(colibri_t30_gfx_devices,
+ ARRAY_SIZE(colibri_t30_gfx_devices));
+
+#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC)
+ res = nvhost_get_resource_byname(&colibri_t30_disp1_device,
+ IORESOURCE_MEM, "fbmem");
+ res->start = tegra_fb_start;
+ res->end = tegra_fb_start + tegra_fb_size - 1;
+
+ res = nvhost_get_resource_byname(&colibri_t30_disp2_device,
+ IORESOURCE_MEM, "fbmem");
+ res->start = tegra_fb2_start;
+ res->end = tegra_fb2_start + tegra_fb2_size - 1;
+#endif /* CONFIG_TEGRA_GRHOST & CONFIG_TEGRA_DC */
+
+ /* Make sure LVDS framebuffer is cleared. */
+ to_io = ioremap(tegra_fb_start, tegra_fb_size);
+ if (to_io) {
+ memset(to_io, 0, tegra_fb_size);
+ iounmap(to_io);
+ } else pr_err("%s: Failed to map LVDS framebuffer\n", __func__);
+
+ /* Make sure HDMI framebuffer is cleared.
+ Note: this seems to fix a tegradc.1 initialisation race in case of
+ framebuffer console as well. */
+ to_io = ioremap(tegra_fb2_start, tegra_fb2_size);
+ if (to_io) {
+ memset(to_io, 0, tegra_fb2_size);
+ iounmap(to_io);
+ } else pr_err("%s: Failed to map HDMI framebuffer\n", __func__);
+
+#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC)
+ if (!err)
+ err = nvhost_device_register(&colibri_t30_disp1_device);
+
+ if (!err)
+ err = nvhost_device_register(&colibri_t30_disp2_device);
+#endif /* CONFIG_TEGRA_GRHOST & CONFIG_TEGRA_DC */
+
+#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_NVAVP)
+ if (!err)
+ err = nvhost_device_register(&nvavp_device);
+#endif
+ return err;
+}
diff --git a/arch/arm/mach-tegra/board-colibri_t30-pinmux.c b/arch/arm/mach-tegra/board-colibri_t30-pinmux.c
new file mode 100644
index 000000000000..87692bfa31ff
--- /dev/null
+++ b/arch/arm/mach-tegra/board-colibri_t30-pinmux.c
@@ -0,0 +1,648 @@
+/*
+ * arch/arm/mach-tegra/board-colibri_t30-pinmux.c
+ *
+ * Copyright (C) 2012 Toradex, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <mach/pinmux.h>
+
+#include "board-colibri_t30.h"
+#include "board.h"
+#include "gpio-names.h"
+
+#define DEFAULT_DRIVE(_name) \
+ { \
+ .pingroup = TEGRA_DRIVE_PINGROUP_##_name, \
+ .hsm = TEGRA_HSM_DISABLE, \
+ .schmitt = TEGRA_SCHMITT_ENABLE, \
+ .drive = TEGRA_DRIVE_DIV_1, \
+ .pull_down = TEGRA_PULL_31, \
+ .pull_up = TEGRA_PULL_31, \
+ .slew_rising = TEGRA_SLEW_SLOWEST, \
+ .slew_falling = TEGRA_SLEW_SLOWEST, \
+ }
+
+/* Setting the drive strength of pins
+ * hsm: Enable High speed mode (ENABLE/DISABLE)
+ * Schimit: Enable/disable schimit (ENABLE/DISABLE)
+ * drive: low power mode (DIV_1, DIV_2, DIV_4, DIV_8)
+ * pulldn_drive - drive down (falling edge) - Driver Output Pull-Down drive
+ * strength code. Value from 0 to 31.
+ * pullup_drive - drive up (rising edge) - Driver Output Pull-Up drive
+ * strength code. Value from 0 to 31.
+ * pulldn_slew - Driver Output Pull-Up slew control code - 2bit code
+ * code 11 is least slewing of signal. code 00 is highest
+ * slewing of the signal.
+ * Value - FASTEST, FAST, SLOW, SLOWEST
+ * pullup_slew - Driver Output Pull-Down slew control code -
+ * code 11 is least slewing of signal. code 00 is highest
+ * slewing of the signal.
+ * Value - FASTEST, FAST, SLOW, SLOWEST
+ */
+#define SET_DRIVE(_name, _hsm, _schmitt, _drive, _pulldn_drive, _pullup_drive, _pulldn_slew, _pullup_slew) \
+ { \
+ .pingroup = TEGRA_DRIVE_PINGROUP_##_name, \
+ .hsm = TEGRA_HSM_##_hsm, \
+ .schmitt = TEGRA_SCHMITT_##_schmitt, \
+ .drive = TEGRA_DRIVE_##_drive, \
+ .pull_down = TEGRA_PULL_##_pulldn_drive, \
+ .pull_up = TEGRA_PULL_##_pullup_drive, \
+ .slew_rising = TEGRA_SLEW_##_pulldn_slew, \
+ .slew_falling = TEGRA_SLEW_##_pullup_slew, \
+ }
+
+static __initdata struct tegra_drive_pingroup_config colibri_t30_drive_pinmux[] = {
+ /* DEFAULT_DRIVE(<pin_group>), */
+
+ /* Audio codec */
+ SET_DRIVE(DAP2, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+
+ /* All I2C pins are driven to maximum drive strength */
+
+ /* GEN1_I2C: I2C_SDA/SCL on SODIMM pin 194/196 (e.g. RTC on carrier board) */
+ SET_DRIVE(DBG, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+
+ /* DDC_CLOCK/DATA on X3 pin 15/16 (e.g. display EDID) */
+ SET_DRIVE(DDC, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+
+ /* PWR_I2C: power I2C to audio codec, PMIC, temperature sensor and
+ touch screen controller */
+ SET_DRIVE(AO1, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+
+ /* SDMMC2 */
+ SET_DRIVE(AO2, DISABLE, DISABLE, DIV_1, 46, 42, FAST, FAST),
+
+ /* eMMC on SDMMC4 */
+ SET_DRIVE(GMA, DISABLE, DISABLE, DIV_1, 9, 9, SLOWEST, SLOWEST),
+ SET_DRIVE(GMB, DISABLE, DISABLE, DIV_1, 9, 9, SLOWEST, SLOWEST),
+ SET_DRIVE(GMC, DISABLE, DISABLE, DIV_1, 9, 9, SLOWEST, SLOWEST),
+ SET_DRIVE(GMD, DISABLE, DISABLE, DIV_1, 9, 9, SLOWEST, SLOWEST),
+};
+
+#define DEFAULT_PINMUX(_pingroup, _mux, _pupd, _tri, _io) \
+ { \
+ .pingroup = TEGRA_PINGROUP_##_pingroup, \
+ .func = TEGRA_MUX_##_mux, \
+ .pupd = TEGRA_PUPD_##_pupd, \
+/* TRISTATE here means output driver is tri-stated */ \
+ .tristate = TEGRA_TRI_##_tri, \
+/* INPUT here means input driver is enabled vs. OUTPUT where it is disabled */ \
+ .io = TEGRA_PIN_##_io, \
+ .lock = TEGRA_PIN_LOCK_DEFAULT, \
+ .od = TEGRA_PIN_OD_DEFAULT, \
+ .ioreset = TEGRA_PIN_IO_RESET_DEFAULT, \
+ }
+
+#define I2C_PINMUX(_pingroup, _mux, _pupd, _tri, _io, _lock, _od) \
+ { \
+ .pingroup = TEGRA_PINGROUP_##_pingroup, \
+ .func = TEGRA_MUX_##_mux, \
+ .pupd = TEGRA_PUPD_##_pupd, \
+ .tristate = TEGRA_TRI_##_tri, \
+ .io = TEGRA_PIN_##_io, \
+ .lock = TEGRA_PIN_LOCK_##_lock, \
+ .od = TEGRA_PIN_OD_##_od, \
+ .ioreset = TEGRA_PIN_IO_RESET_DEFAULT, \
+ }
+
+#define VI_PINMUX(_pingroup, _mux, _pupd, _tri, _io, _lock, _ioreset) \
+ { \
+ .pingroup = TEGRA_PINGROUP_##_pingroup, \
+ .func = TEGRA_MUX_##_mux, \
+ .pupd = TEGRA_PUPD_##_pupd, \
+ .tristate = TEGRA_TRI_##_tri, \
+ .io = TEGRA_PIN_##_io, \
+ .lock = TEGRA_PIN_LOCK_##_lock, \
+ .od = TEGRA_PIN_OD_DEFAULT, \
+ .ioreset = TEGRA_PIN_IO_RESET_##_ioreset \
+ }
+
+static __initdata struct tegra_pingroup_config colibri_t30_pinmux[] = {
+//multiplexed KB_ROW_13
+#ifdef COLIBRI_T30_SDMMC4B
+ I2C_PINMUX(CAM_I2C_SCL, POPSDMMC4, PULL_UP, NORMAL, INPUT, DEFAULT, DISABLE),
+#else
+ I2C_PINMUX(CAM_I2C_SCL, I2C3, NORMAL, TRISTATE, OUTPUT, DEFAULT, DISABLE),
+#endif
+//multiplexed KB_ROW_14
+#ifdef COLIBRI_T30_SDMMC4B
+ I2C_PINMUX(CAM_I2C_SDA, POPSDMMC4, PULL_UP, NORMAL, INPUT, DEFAULT, DISABLE),
+#else
+ I2C_PINMUX(CAM_I2C_SDA, I2C3, NORMAL, TRISTATE, OUTPUT, DEFAULT, DISABLE),
+#endif
+//multiplexed KB_ROW_10
+#ifdef COLIBRI_T30_SDMMC4B
+ DEFAULT_PINMUX(CAM_MCLK, POPSDMMC4, NORMAL, NORMAL, INPUT),
+#else
+ DEFAULT_PINMUX(CAM_MCLK, VI_ALT2, NORMAL, TRISTATE, OUTPUT),
+#endif
+
+ DEFAULT_PINMUX(CLK1_OUT, EXTPERIPH1, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(CLK1_REQ, RSVD2, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+
+ DEFAULT_PINMUX(CLK2_OUT, EXTPERIPH2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(CLK2_REQ, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+
+ DEFAULT_PINMUX(CLK3_OUT, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(CLK3_REQ, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+
+ DEFAULT_PINMUX(CLK_32K_OUT, RSVD1, NORMAL, TRISTATE, OUTPUT),
+
+ DEFAULT_PINMUX(CRT_HSYNC, CRT, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(CRT_VSYNC, CRT, NORMAL, NORMAL, OUTPUT),
+
+ DEFAULT_PINMUX(DAP1_DIN, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(DAP1_DOUT, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(DAP1_FS, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(DAP1_SCLK, GMI, NORMAL, NORMAL, INPUT),
+
+//multiplexed LCD_D23
+ DEFAULT_PINMUX(DAP2_DIN, GMI, NORMAL, TRISTATE, OUTPUT),
+//multiplexed LCD_D22
+ DEFAULT_PINMUX(DAP2_DOUT, GMI, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(DAP2_FS, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(DAP2_SCLK, GMI, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(DAP3_DIN, I2S2, NORMAL, NORMAL, INPUT),
+// DEFAULT_PINMUX(DAP3_DOUT, I2S2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(DAP3_DOUT, I2S2, NORMAL, NORMAL, OUTPUT),
+// DEFAULT_PINMUX(DAP3_FS, I2S2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(DAP3_FS, I2S2, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(DAP3_SCLK, I2S2, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(DAP4_DIN, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(DAP4_DOUT, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(DAP4_FS, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(DAP4_SCLK, GMI, NORMAL, NORMAL, INPUT),
+
+ I2C_PINMUX(DDC_SCL, I2C4, NORMAL, NORMAL, INPUT, DEFAULT, ENABLE),
+ I2C_PINMUX(DDC_SDA, I2C4, NORMAL, NORMAL, INPUT, DEFAULT, ENABLE),
+
+ I2C_PINMUX(GEN1_I2C_SCL, I2C1, NORMAL, NORMAL, INPUT, DEFAULT, ENABLE),
+ I2C_PINMUX(GEN1_I2C_SDA, I2C1, NORMAL, NORMAL, INPUT, DEFAULT, ENABLE),
+
+ I2C_PINMUX(GEN2_I2C_SCL, RSVD3, PULL_UP, NORMAL, INPUT, DEFAULT, DISABLE),
+ I2C_PINMUX(GEN2_I2C_SDA, RSVD3, PULL_UP, NORMAL, INPUT, DEFAULT, DISABLE),
+
+ DEFAULT_PINMUX(GMI_A16, UARTD, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_A17, UARTD, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_A18, UARTD, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_A19, UARTD, NORMAL, NORMAL, INPUT),
+#ifdef COLIBRI_T30_V10
+ DEFAULT_PINMUX(GMI_AD0, NAND, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD1, NAND, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD2, NAND, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD3, NAND, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD4, NAND, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD5, NAND, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD6, NAND, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD7, NAND, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD8, RSVD2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD9, RSVD2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD10, RSVD2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD11, RSVD2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD12, RSVD2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD13, RSVD2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD14, RSVD2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD15, RSVD2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_ADV_N, NAND, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(GMI_CLK, NAND, NORMAL, NORMAL, OUTPUT),
+#else /* COLIBRI_T30_V10 */
+ DEFAULT_PINMUX(GMI_AD0, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD1, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD2, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD3, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD4, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD5, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD6, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD7, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD8, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD9, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD10, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD11, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD12, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD13, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD14, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_AD15, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_ADV_N, GMI, NORMAL, NORMAL, INPUT),
+//multiplexed OWR
+ DEFAULT_PINMUX(GMI_CLK, GMI, NORMAL, TRISTATE, OUTPUT),
+#endif /* COLIBRI_T30_V10 */
+ DEFAULT_PINMUX(GMI_CS0_N, RSVD1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_CS1_N, RSVD1, NORMAL, NORMAL, INPUT),
+#ifdef COLIBRI_T30_V10
+ DEFAULT_PINMUX(GMI_CS2_N, NAND, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(GMI_CS3_N, NAND, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(GMI_CS4_N, NAND, NORMAL, NORMAL, OUTPUT),
+#else /* COLIBRI_T30_V10 */
+ DEFAULT_PINMUX(GMI_CS2_N, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_CS3_N, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_CS4_N, GMI, NORMAL, NORMAL, INPUT),
+#endif /* COLIBRI_T30_V10 */
+ DEFAULT_PINMUX(GMI_CS6_N, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_CS7_N, GMI, NORMAL, NORMAL, INPUT),
+#ifdef COLIBRI_T30_V10
+ DEFAULT_PINMUX(GMI_DQS, NAND, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_IORDY, NAND, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(GMI_OE_N, NAND, NORMAL, NORMAL, OUTPUT),
+#else /* COLIBRI_T30_V10 */
+ DEFAULT_PINMUX(GMI_DQS, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+//multiplexed GMI_WAIT
+ DEFAULT_PINMUX(GMI_IORDY, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_OE_N, GMI, NORMAL, NORMAL, INPUT),
+#endif /* COLIBRI_T30_V10 */
+ DEFAULT_PINMUX(GMI_RST_N, GMI, NORMAL, NORMAL, INPUT),
+#ifdef COLIBRI_T30_V10
+ DEFAULT_PINMUX(GMI_WAIT, NAND, NORMAL, NORMAL, INPUT),
+//GPIO C7: eMMC vs. NAND flash detection
+ DEFAULT_PINMUX(GMI_WP_N, NAND, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_WR_N, NAND, NORMAL, NORMAL, OUTPUT),
+#else /* COLIBRI_T30_V10 */
+//multiplexed GMI_IORDY
+ DEFAULT_PINMUX(GMI_WAIT, GMI, NORMAL, TRISTATE, OUTPUT),
+//GPIO PU6: MMC_CD
+ DEFAULT_PINMUX(GMI_WP_N, RSVD1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GMI_WR_N, GMI, NORMAL, NORMAL, INPUT),
+#endif /* COLIBRI_T30_V10 */
+
+//multiplexed KB_ROW_12
+#ifdef COLIBRI_T30_SDMMC4B
+ DEFAULT_PINMUX(GPIO_PBB0, POPSDMMC4, PULL_UP, NORMAL, INPUT),
+#else
+ DEFAULT_PINMUX(GPIO_PBB0, RSVD1, NORMAL, TRISTATE, OUTPUT),
+#endif
+//multiplexed KB_ROW_15
+#ifdef COLIBRI_T30_SDMMC4B
+ DEFAULT_PINMUX(GPIO_PBB3, POPSDMMC4, PULL_UP, NORMAL, INPUT),
+#else
+ DEFAULT_PINMUX(GPIO_PBB3, VGP3, NORMAL, TRISTATE, OUTPUT),
+#endif
+ DEFAULT_PINMUX(GPIO_PBB4, VGP4, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GPIO_PBB5, VGP5, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GPIO_PBB6, VGP6, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GPIO_PBB7, RSVD1, NORMAL, NORMAL, INPUT),
+
+//multiplexed KB_ROW_11
+#ifdef COLIBRI_T30_SDMMC4B
+ DEFAULT_PINMUX(GPIO_PCC1, POPSDMMC4, NORMAL, NORMAL, INPUT),
+#else
+ DEFAULT_PINMUX(GPIO_PCC1, RSVD1, NORMAL, TRISTATE, OUTPUT),
+#endif
+#ifdef COLIBRI_T30_SDMMC4B
+//when used for SDMMC4: 10k to VDDIO_CAM
+ DEFAULT_PINMUX(GPIO_PCC2, POPSDMMC4, PULL_UP, NORMAL, INPUT),
+#else /* COLIBRI_T30_SDMMC4B */
+//multiplexed VI_D11
+#ifdef COLIBRI_T30_VI
+ DEFAULT_PINMUX(GPIO_PCC2, RSVD1, NORMAL, TRISTATE, OUTPUT),
+#else
+ DEFAULT_PINMUX(GPIO_PCC2, RSVD1, PULL_UP, NORMAL, INPUT),
+#endif
+#endif /* COLIBRI_T30_SDMMC4B */
+
+ DEFAULT_PINMUX(GPIO_PU0, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GPIO_PU1, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GPIO_PU2, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GPIO_PU3, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GPIO_PU4, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GPIO_PU5, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GPIO_PU6, GMI, NORMAL, NORMAL, INPUT),
+
+//GPIO V0: touch pendown int
+ DEFAULT_PINMUX(GPIO_PV0, RSVD, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GPIO_PV1, RSVD, NORMAL, NORMAL, INPUT),
+#ifdef COLIBRI_T30_VI
+//multiplexed VI_D0
+ DEFAULT_PINMUX(GPIO_PV2, RSVD1, NORMAL, TRISTATE, OUTPUT),
+//multiplexed VI_D8
+ DEFAULT_PINMUX(GPIO_PV3, RSVD1, NORMAL, TRISTATE, OUTPUT),
+#else
+//GPIO V2: BL_ON
+ DEFAULT_PINMUX(GPIO_PV2, RSVD1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GPIO_PV3, RSVD1, NORMAL, NORMAL, INPUT),
+#endif
+
+ DEFAULT_PINMUX(HDMI_CEC, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+//GPIO N7: HOTPLUG_DETECT
+ DEFAULT_PINMUX(HDMI_INT, RSVD0, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(JTAG_RTCK, RTCK, NORMAL, NORMAL, OUTPUT),
+
+//all tristate?
+ DEFAULT_PINMUX(KB_COL0, KBC, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_COL1, KBC, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_COL2, KBC, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_COL3, KBC, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_COL4, KBC, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_COL5, KBC, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_COL6, KBC, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_COL7, KBC, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_ROW0, RSVD2, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_ROW1, RSVD2, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_ROW2, RSVD2, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_ROW3, RSVD2, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_ROW4, RSVD3, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_ROW5, KBC, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_ROW6, KBC, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(KB_ROW7, KBC, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(KB_ROW8, KBC, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(KB_ROW9, KBC, NORMAL, TRISTATE, INPUT),
+
+//multiplexed SDMMC4.B
+#ifdef COLIBRI_T30_SDMMC4B
+ DEFAULT_PINMUX(KB_ROW10, KBC, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(KB_ROW11, KBC, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(KB_ROW12, KBC, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(KB_ROW13, KBC, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(KB_ROW14, KBC, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(KB_ROW15, KBC, NORMAL, TRISTATE, OUTPUT),
+#else
+ DEFAULT_PINMUX(KB_ROW10, SDMMC2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(KB_ROW11, SDMMC2, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(KB_ROW12, SDMMC2, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(KB_ROW13, SDMMC2, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(KB_ROW14, SDMMC2, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(KB_ROW15, SDMMC2, PULL_UP, NORMAL, INPUT),
+#endif
+
+ DEFAULT_PINMUX(LCD_CS0_N, RSVD, NORMAL, NORMAL, INPUT),
+//multiplexed with SDMMC3_DAT5 gated GMI_WR_N
+ DEFAULT_PINMUX(LCD_CS1_N, RSVD2, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(LCD_D0, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D1, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D2, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D3, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D4, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D5, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D6, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D7, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D8, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D9, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D10, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D11, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D12, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D13, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D14, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D15, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D16, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D17, DISPLAYA, NORMAL, NORMAL, INPUT),
+
+//multiplexed
+ DEFAULT_PINMUX(LCD_D18, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D19, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D20, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D21, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D22, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_D23, DISPLAYA, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(LCD_DC0, RSVD1, NORMAL, NORMAL, INPUT),
+//GPIO D2: THERMD_ALERT_N
+ DEFAULT_PINMUX(LCD_DC1, RSVD1, NORMAL, NORMAL, INPUT),
+//multiplexed LCD_M1
+ DEFAULT_PINMUX(LCD_DE, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_HSYNC, DISPLAYA, NORMAL, NORMAL, INPUT),
+//multiplexed LCD_DE
+ DEFAULT_PINMUX(LCD_M1, RSVD1, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(LCD_PCLK, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_PWR0, DISPLAYA, NORMAL, NORMAL, INPUT),
+//multiplexed VI_VSYNC
+#ifdef COLIBRI_T30_VI
+ DEFAULT_PINMUX(LCD_PWR1, RSVD1, NORMAL, TRISTATE, OUTPUT),
+#else
+ DEFAULT_PINMUX(LCD_PWR1, RSVD1, NORMAL, NORMAL, INPUT),
+#endif
+ DEFAULT_PINMUX(LCD_PWR2, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+ DEFAULT_PINMUX(LCD_SCK, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_SDIN, RSVD, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_SDOUT, DISPLAYA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_VSYNC, DISPLAYA, NORMAL, NORMAL, INPUT),
+//multiplexed with SDMMC3_DAT4 gated GMI_WR_N
+ DEFAULT_PINMUX(LCD_WR_N, RSVD, NORMAL, NORMAL, INPUT),
+//multiplexed GMI_CLK
+ DEFAULT_PINMUX(OWR, OWR, NORMAL, NORMAL, INPUT),
+//GPIO DD2: LAN_VBUS
+ DEFAULT_PINMUX(PEX_L0_CLKREQ_N, RSVD2, NORMAL, NORMAL, OUTPUT),
+//GPIO DD0: LAN_RESET
+ DEFAULT_PINMUX(PEX_L0_PRSNT_N, RSVD2, NORMAL, NORMAL, OUTPUT),
+//GPIO DD1: LAN_EXTWAKEUP
+ DEFAULT_PINMUX(PEX_L0_RST_N, RSVD2, NORMAL, NORMAL, INPUT),
+//multiplexed VI_D9
+#ifdef COLIBRI_T30_VI
+ DEFAULT_PINMUX(PEX_L1_CLKREQ_N, RSVD2, NORMAL, TRISTATE, OUTPUT),
+#else
+ DEFAULT_PINMUX(PEX_L1_CLKREQ_N, RSVD2, NORMAL, NORMAL, INPUT),
+#endif
+ DEFAULT_PINMUX(PEX_L1_PRSNT_N, RSVD2, PULL_DOWN, TRISTATE, OUTPUT), /* NC */
+#ifdef COLIBRI_T30_VI
+//multiplexed VI_D10
+ DEFAULT_PINMUX(PEX_L1_RST_N, RSVD2, NORMAL, TRISTATE, OUTPUT),
+//multiplexed VI_HSYNC
+ DEFAULT_PINMUX(PEX_L2_CLKREQ_N, RSVD2, NORMAL, TRISTATE, OUTPUT),
+#else
+ DEFAULT_PINMUX(PEX_L1_RST_N, RSVD2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(PEX_L2_CLKREQ_N, RSVD2, NORMAL, NORMAL, INPUT),
+#endif
+ DEFAULT_PINMUX(PEX_L2_PRSNT_N, RSVD2, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(PEX_L2_RST_N, RSVD2, PULL_UP, NORMAL, INPUT),
+//GPIO DD3: LAN_PME
+ DEFAULT_PINMUX(PEX_WAKE_N, RSVD2, NORMAL, NORMAL, INPUT),
+
+/* Power I2C pinmux */
+ I2C_PINMUX(PWR_I2C_SCL, I2CPWR, NORMAL, NORMAL, INPUT, DEFAULT, ENABLE),
+ I2C_PINMUX(PWR_I2C_SDA, I2CPWR, NORMAL, NORMAL, INPUT, DEFAULT, ENABLE),
+
+#ifdef COLIBRI_T30_VI
+//multiplexed VI_PCLK
+ DEFAULT_PINMUX(SDMMC1_CLK, RSVD1, NORMAL, TRISTATE, OUTPUT),
+//multiplexed VI_D1
+ DEFAULT_PINMUX(SDMMC1_CMD, RSVD1, NORMAL, TRISTATE, OUTPUT),
+//multiplexed VI_D2
+ DEFAULT_PINMUX(SDMMC1_DAT0, RSVD1, NORMAL, TRISTATE, OUTPUT),
+//multiplexed VI_D3
+ DEFAULT_PINMUX(SDMMC1_DAT1, RSVD1, NORMAL, TRISTATE, OUTPUT),
+//multiplexed VI_D4
+ DEFAULT_PINMUX(SDMMC1_DAT2, RSVD1, NORMAL, TRISTATE, OUTPUT),
+//multiplexed VI_D5
+ DEFAULT_PINMUX(SDMMC1_DAT3, RSVD1, NORMAL, TRISTATE, OUTPUT),
+#else
+ DEFAULT_PINMUX(SDMMC1_CLK, RSVD1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC1_CMD, RSVD1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC1_DAT0, RSVD1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC1_DAT1, RSVD1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC1_DAT2, RSVD1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC1_DAT3, RSVD1, NORMAL, NORMAL, INPUT),
+#endif
+
+ DEFAULT_PINMUX(SDMMC3_CLK, PWM2, NORMAL, NORMAL, INPUT),
+//multiplexed VI_D6
+#ifdef COLIBRI_T30_VI
+ DEFAULT_PINMUX(SDMMC3_CMD, SDMMC3, NORMAL, TRISTATE, OUTPUT),
+#else
+ DEFAULT_PINMUX(SDMMC3_CMD, PWM3, NORMAL, NORMAL, INPUT),
+#endif
+ DEFAULT_PINMUX(SDMMC3_DAT0, RSVD0, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC3_DAT1, RSVD0, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC3_DAT2, PWM1, NORMAL, NORMAL, INPUT),
+//multiplexed VI_D7
+#ifdef COLIBRI_T30_VI
+ DEFAULT_PINMUX(SDMMC3_DAT3, RSVD0, NORMAL, TRISTATE, OUTPUT),
+#else
+ DEFAULT_PINMUX(SDMMC3_DAT3, PWM0, NORMAL, NORMAL, INPUT),
+#endif
+//tri-stating GMI_WR_N on nPWE SODIMM pin 99
+ DEFAULT_PINMUX(SDMMC3_DAT4, SDMMC3, PULL_UP, TRISTATE, OUTPUT),
+//not tri-stating GMI_WR_N on RDnWR SODIMM pin 93
+ DEFAULT_PINMUX(SDMMC3_DAT5, SDMMC3, PULL_DOWN, TRISTATE, OUTPUT),
+//multiplexed ULPI_STP used as SSPFRM
+ DEFAULT_PINMUX(SDMMC3_DAT6, SPDIF, NORMAL, TRISTATE, OUTPUT),
+//multiplexed ULPI_CLK used as SSPTXD
+ DEFAULT_PINMUX(SDMMC3_DAT7, SPDIF, NORMAL, TRISTATE, OUTPUT),
+
+//eMMC
+#ifdef COLIBRI_T30_SDMMC4B
+ DEFAULT_PINMUX(SDMMC4_CLK, NAND, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(SDMMC4_CMD, NAND, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT0, GMI, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT1, GMI, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT2, GMI, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT3, GMI, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT4, GMI, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT5, VGP3, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT6, VGP4, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT7, VGP5, NORMAL, TRISTATE, OUTPUT),
+ DEFAULT_PINMUX(SDMMC4_RST_N, RSVD1, NORMAL, TRISTATE, OUTPUT),
+#else /* COLIBRI_T30_SDMMC4B */
+ DEFAULT_PINMUX(SDMMC4_CLK, SDMMC4, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_CMD, SDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT0, SDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT1, SDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT2, SDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT3, SDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT4, SDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT5, SDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT6, SDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_DAT7, SDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC4_RST_N, RSVD1, PULL_DOWN, NORMAL, INPUT),
+#endif /* COLIBRI_T30_SDMMC4B */
+
+//GPIO K6: USB_ID, multiplexed ACC1_DETECT
+ DEFAULT_PINMUX(SPDIF_IN, HDA, PULL_UP, NORMAL, INPUT),
+//GPIO K5: USBC_DET(VBUS), multiplexed USB1_VBUS
+ DEFAULT_PINMUX(SPDIF_OUT, RSVD1, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(SPI1_CS0_N, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SPI1_MISO, RSVD3, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SPI1_MOSI, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SPI1_SCK, GMI, NORMAL, NORMAL, INPUT),
+//multiplexed LCD_D18
+ DEFAULT_PINMUX(SPI2_CS0_N, GMI, NORMAL, TRISTATE, OUTPUT),
+//GPIO W2: USBH_PEN
+ DEFAULT_PINMUX(SPI2_CS1_N, SPI2, PULL_UP, NORMAL, INPUT),
+//GPIO W3: USBH_OC
+ DEFAULT_PINMUX(SPI2_CS2_N, SPI2, NORMAL, NORMAL, INPUT),
+//multiplexed LCD_D20
+ DEFAULT_PINMUX(SPI2_MISO, GMI, NORMAL, TRISTATE, OUTPUT),
+//multiplexed LCD_D21
+ DEFAULT_PINMUX(SPI2_MOSI, GMI, NORMAL, TRISTATE, OUTPUT),
+//multiplexed LCD_D19
+ DEFAULT_PINMUX(SPI2_SCK, GMI, NORMAL, TRISTATE, OUTPUT),
+
+ DEFAULT_PINMUX(SYS_CLK_REQ, SYSCLK, NORMAL, TRISTATE, OUTPUT),
+
+ DEFAULT_PINMUX(UART2_CTS_N, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(UART2_RTS_N, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(UART2_RXD, IRDA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(UART2_TXD, IRDA, NORMAL, NORMAL, INPUT),
+
+ DEFAULT_PINMUX(UART3_CTS_N, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(UART3_RTS_N, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(UART3_RXD, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(UART3_TXD, GMI, NORMAL, NORMAL, INPUT),
+
+//multiplexed SDMMC3_DAT7
+ DEFAULT_PINMUX(ULPI_CLK, SPI1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_DATA0, UARTA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_DATA1, UARTA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_DATA2, UARTA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_DATA3, UARTA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_DATA4, UARTA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_DATA5, UARTA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_DATA6, UARTA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_DATA7, UARTA, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_DIR, SPI1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(ULPI_NXT, SPI1, NORMAL, NORMAL, INPUT),
+//multiplexed SDMMC3_DAT6
+ DEFAULT_PINMUX(ULPI_STP, SPI1, NORMAL, NORMAL, INPUT),
+
+//VI pins are all input level-shifted and multiplexed
+//unused VI pins could disable input drivers
+ VI_PINMUX(VI_D0, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D1, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D2, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D3, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D4, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D5, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D6, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D7, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D8, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D9, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D10, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_D11, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_HSYNC, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+//GPIO T1: EN_MIC_GND
+ DEFAULT_PINMUX(VI_MCLK, VI, NORMAL, NORMAL, OUTPUT),
+ VI_PINMUX(VI_PCLK, VI, PULL_UP, TRISTATE, INPUT, DISABLE, DISABLE),
+ VI_PINMUX(VI_VSYNC, VI, NORMAL, TRISTATE, INPUT, DISABLE, DISABLE),
+};
+
+#define GPIO_INIT_PIN_MODE(_gpio, _is_input, _value) \
+ { \
+ .gpio_nr = _gpio, \
+ .is_input = _is_input, \
+ .value = _value, \
+ }
+
+static struct gpio_init_pin_info colibri_t30_init_gpio_mode[] = {
+};
+
+static void __init colibri_t30_gpio_init_configure(void)
+{
+ int len;
+ int i;
+ struct gpio_init_pin_info *pins_info;
+
+ len = ARRAY_SIZE(colibri_t30_init_gpio_mode);
+ pins_info = colibri_t30_init_gpio_mode;
+
+ for (i = 0; i < len; ++i) {
+ tegra_gpio_init_configure(pins_info->gpio_nr,
+ pins_info->is_input,
+ pins_info->value);
+ pins_info++;
+ }
+}
+
+int __init colibri_t30_pinmux_init(void)
+{
+ colibri_t30_gpio_init_configure();
+
+ tegra_pinmux_config_table(colibri_t30_pinmux,
+ ARRAY_SIZE(colibri_t30_pinmux));
+ tegra_drive_pinmux_config_table(colibri_t30_drive_pinmux,
+ ARRAY_SIZE(colibri_t30_drive_pinmux));
+
+ return 0;
+}
diff --git a/arch/arm/mach-tegra/board-colibri_t30-power.c b/arch/arm/mach-tegra/board-colibri_t30-power.c
new file mode 100644
index 000000000000..b6e2d70d4cbc
--- /dev/null
+++ b/arch/arm/mach-tegra/board-colibri_t30-power.c
@@ -0,0 +1,505 @@
+/*
+ * arch/arm/mach-tegra/board-colibri_t30-power.c
+ *
+ * Copyright (C) 2012 Toradex, Inc.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#include <asm/mach-types.h>
+
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/mfd/max77663-core.h>
+#include <linux/mfd/tps6591x.h>
+#include <linux/pda_power.h>
+#include <linux/platform_device.h>
+//#include <linux/power/gpio-charger.h>
+#include <linux/regulator/fixed.h>
+//#include <linux/regulator/gpio-switch-regulator.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/tps62360.h>
+#include <linux/regulator/tps6591x-regulator.h>
+#include <linux/resource.h>
+
+#include <mach/edp.h>
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+#include <mach/pinmux.h>
+//#include <mach/suspend.h>
+
+#include "board-colibri_t30.h"
+#include "board.h"
+#include "gpio-names.h"
+#include "tegra3_tsensor.h"
+#include "pm.h"
+#include "wakeups.h"
+#include "wakeups-t3.h"
+
+#define PMC_CTRL 0x0
+#define PMC_CTRL_INTR_LOW (1 << 17)
+
+/* SW1: +V1.35_VDDIO_DDR */
+static struct regulator_consumer_supply tps6591x_vdd1_supply_0[] = {
+ REGULATOR_SUPPLY("mem_vddio_ddr", NULL),
+ REGULATOR_SUPPLY("t30_vddio_ddr", NULL),
+};
+
+/* SW2: unused */
+static struct regulator_consumer_supply tps6591x_vdd2_supply_0[] = {
+ REGULATOR_SUPPLY("unused_rail_vdd2", NULL),
+};
+
+/* SW CTRL: +V1.0_VDD_CPU */
+static struct regulator_consumer_supply tps6591x_vddctrl_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_cpu_pmu", NULL),
+ REGULATOR_SUPPLY("vdd_cpu", NULL),
+//!=vddio_sys!
+ REGULATOR_SUPPLY("vdd_sys", NULL),
+};
+
+/* SWIO: +V1.8 */
+static struct regulator_consumer_supply tps6591x_vio_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_gen1v8", NULL),
+ REGULATOR_SUPPLY("avdd_usb_pll", NULL),
+ REGULATOR_SUPPLY("avdd_osc", NULL),
+ REGULATOR_SUPPLY("vddio_sdmmc", "sdhci-tegra.3"),
+ REGULATOR_SUPPLY("pwrdet_sdmmc4", NULL),
+ REGULATOR_SUPPLY("vdd1v8_satelite", NULL),
+ REGULATOR_SUPPLY("vddio_vi", NULL),
+ REGULATOR_SUPPLY("pwrdet_vi", NULL),
+ REGULATOR_SUPPLY("ldo1", NULL),
+ REGULATOR_SUPPLY("ldo2", NULL),
+ REGULATOR_SUPPLY("ldo6", NULL),
+ REGULATOR_SUPPLY("ldo7", NULL),
+ REGULATOR_SUPPLY("ldo8", NULL),
+ REGULATOR_SUPPLY("vcore_audio", NULL),
+ REGULATOR_SUPPLY("avcore_audio", NULL),
+ REGULATOR_SUPPLY("vcore1_lpddr2", NULL),
+ REGULATOR_SUPPLY("vcom_1v8", NULL),
+ REGULATOR_SUPPLY("pmuio_1v8", NULL),
+ REGULATOR_SUPPLY("avdd_ic_usb", NULL),
+};
+
+/* unused */
+static struct regulator_consumer_supply tps6591x_ldo1_supply_0[] = {
+ REGULATOR_SUPPLY("unused_rail_ldo1", NULL),
+};
+
+/* EN_+V3.3 switching via FET: +V3.3_AUDIO_AVDD_S, +V3.3 and +V1.8_VDD_LAN
+ see also v3_3 fixed supply */
+static struct regulator_consumer_supply tps6591x_ldo2_supply_0[] = {
+ REGULATOR_SUPPLY("en_V3_3", NULL),
+};
+
+/* unused in Colibri T30, used in Apalis T30 */
+static struct regulator_consumer_supply tps6591x_ldo3_supply_0[] = {
+ REGULATOR_SUPPLY("avdd_dsi_csi", NULL),
+ REGULATOR_SUPPLY("pwrdet_mipi", NULL),
+};
+
+/* +V1.2_VDD_RTC */
+static struct regulator_consumer_supply tps6591x_ldo4_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_rtc", NULL),
+};
+
+/* +V2.8_AVDD_VDAC */
+//only required for analog RGB
+static struct regulator_consumer_supply tps6591x_ldo5_supply_0[] = {
+ REGULATOR_SUPPLY("avdd_vdac", NULL),
+};
+
+/* +V1.05_AVDD_PLLE */
+static struct regulator_consumer_supply tps6591x_ldo6_supply_0[] = {
+ REGULATOR_SUPPLY("avdd_plle", NULL),
+};
+
+/* +V1.2_AVDD_PLL */
+static struct regulator_consumer_supply tps6591x_ldo7_supply_0[] = {
+ REGULATOR_SUPPLY("avdd_plla_p_c_s", NULL),
+ REGULATOR_SUPPLY("avdd_pllm", NULL),
+ REGULATOR_SUPPLY("avdd_pllu_d", NULL),
+ REGULATOR_SUPPLY("avdd_pllu_d2", NULL),
+ REGULATOR_SUPPLY("avdd_pllx", NULL),
+};
+
+/* +V1.0_VDD_DDR_HS */
+static struct regulator_consumer_supply tps6591x_ldo8_supply_0[] = {
+ REGULATOR_SUPPLY("vdd_ddr_hs", NULL),
+};
+
+#define TPS_PDATA_INIT(_name, _sname, _minmv, _maxmv, _supply_reg, _always_on, \
+ _boot_on, _apply_uv, _init_uV, _init_enable, _init_apply, _ectrl, _flags) \
+ static struct tps6591x_regulator_platform_data pdata_##_name##_##_sname = \
+ { \
+ .regulator = { \
+ .constraints = { \
+ .min_uV = (_minmv)*1000, \
+ .max_uV = (_maxmv)*1000, \
+ .valid_modes_mask = (REGULATOR_MODE_NORMAL | \
+ REGULATOR_MODE_STANDBY), \
+ .valid_ops_mask = (REGULATOR_CHANGE_MODE | \
+ REGULATOR_CHANGE_STATUS | \
+ REGULATOR_CHANGE_VOLTAGE), \
+ .always_on = _always_on, \
+ .boot_on = _boot_on, \
+ .apply_uV = _apply_uv, \
+ }, \
+ .num_consumer_supplies = \
+ ARRAY_SIZE(tps6591x_##_name##_supply_##_sname), \
+ .consumer_supplies = tps6591x_##_name##_supply_##_sname, \
+ .supply_regulator = _supply_reg, \
+ }, \
+ .init_uV = _init_uV * 1000, \
+ .init_enable = _init_enable, \
+ .init_apply = _init_apply, \
+ .ectrl = _ectrl, \
+ .flags = _flags, \
+ }
+
+TPS_PDATA_INIT(vdd1, 0, 1350, 1350, 0, 1, 1, 0, -1, 0, 0, 0, 0);
+TPS_PDATA_INIT(vdd2, 0, 1050, 1050, 0, 0, 1, 0, -1, 0, 0, EXT_CTRL_SLEEP_OFF, 0);
+TPS_PDATA_INIT(vddctrl, 0, 800, 1300, 0, 1, 1, 0, -1, 0, 0, EXT_CTRL_EN1, 0);
+TPS_PDATA_INIT(vio, 0, 1800, 1800, 0, 1, 1, 0, -1, 0, 0, 0, 0);
+
+TPS_PDATA_INIT(ldo1, 0, 1000, 3300, tps6591x_rails(VIO), 0, 0, 0, -1, 0, 1, 0, 0);
+/* Make sure EN_+V3.3 is always on! */
+TPS_PDATA_INIT(ldo2, 0, 1200, 1200, tps6591x_rails(VIO), 1, 1, 1, -1, 0, 1, 0, 0);
+
+TPS_PDATA_INIT(ldo3, 0, 1200, 1200, 0, 0, 0, 0, -1, 0, 0, 0, 0);
+TPS_PDATA_INIT(ldo4, 0, 900, 1400, 0, 1, 0, 0, -1, 0, 0, 0, LDO_LOW_POWER_ON_SUSPEND);
+TPS_PDATA_INIT(ldo5, 0, 2800, 2800, 0, 0, 0, 0, -1, 0, 0, 0, 0);
+/* AVDD_PLLE should be 1.05V, but ldo_6 can not be adjusted in a 50mV granularity */
+TPS_PDATA_INIT(ldo6, 0, 1000, 1100, tps6591x_rails(VIO), 0, 0, 1, -1, 0, 0, 0, 0);
+
+TPS_PDATA_INIT(ldo7, 0, 1200, 1200, tps6591x_rails(VIO), 1, 1, 1, -1, 0, 0, EXT_CTRL_SLEEP_OFF, LDO_LOW_POWER_ON_SUSPEND);
+TPS_PDATA_INIT(ldo8, 0, 1000, 1000, tps6591x_rails(VIO), 1, 0, 0, -1, 0, 0, EXT_CTRL_SLEEP_OFF, LDO_LOW_POWER_ON_SUSPEND);
+
+#if defined(CONFIG_RTC_DRV_TPS6591x)
+static struct tps6591x_rtc_platform_data rtc_data = {
+ .irq = TEGRA_NR_IRQS + TPS6591X_INT_RTC_ALARM,
+ .time = {
+ .tm_year = 2000,
+ .tm_mon = 0,
+ .tm_mday = 1,
+ .tm_hour = 0,
+ .tm_min = 0,
+ .tm_sec = 0,
+ },
+};
+
+#define TPS_RTC_REG() \
+ { \
+ .id = 0, \
+ .name = "rtc_tps6591x", \
+ .platform_data = &rtc_data, \
+ }
+#endif
+
+#define TPS_REG(_id, _name, _sname) \
+ { \
+ .id = TPS6591X_ID_##_id, \
+ .name = "tps6591x-regulator", \
+ .platform_data = &pdata_##_name##_##_sname, \
+ }
+
+static struct tps6591x_subdev_info colibri_t30_tps_devs[] = {
+ TPS_REG(VDD_1, vdd1, 0),
+ TPS_REG(VDD_2, vdd2, 0),
+ TPS_REG(VDDCTRL, vddctrl, 0),
+ TPS_REG(VIO, vio, 0),
+ TPS_REG(LDO_1, ldo1, 0),
+ TPS_REG(LDO_2, ldo2, 0),
+ TPS_REG(LDO_3, ldo3, 0),
+ TPS_REG(LDO_4, ldo4, 0),
+ TPS_REG(LDO_5, ldo5, 0),
+ TPS_REG(LDO_6, ldo6, 0),
+ TPS_REG(LDO_7, ldo7, 0),
+ TPS_REG(LDO_8, ldo8, 0),
+#if defined(CONFIG_RTC_DRV_TPS6591x)
+ TPS_RTC_REG(),
+#endif
+};
+
+static struct tps6591x_sleep_keepon_data tps_slp_keepon = {
+ .clkout32k_keepon = 1,
+};
+
+static struct tps6591x_platform_data tps_platform = {
+ .irq_base = TPS6591X_IRQ_BASE,
+ .gpio_base = TPS6591X_GPIO_BASE,
+ .dev_slp_en = true,
+ .slp_keepon = &tps_slp_keepon,
+ .use_power_off = true,
+};
+
+static struct i2c_board_info __initdata colibri_t30_regulators[] = {
+ {
+ I2C_BOARD_INFO("tps6591x", 0x2D),
+//PWR_INT_IN wake18
+ .irq = INT_EXTERNAL_PMU,
+ .platform_data = &tps_platform,
+ },
+};
+
+/* TPS62362 DC-DC converter
+ SW: +V1.2_VDD_CORE
+ Note: Colibri T30 V1.0 have TPS62360 with different voltage levels at startup */
+static struct regulator_consumer_supply tps6236x_dcdc_supply[] = {
+ REGULATOR_SUPPLY("vdd_core", NULL),
+};
+
+static struct tps62360_regulator_platform_data tps6236x_pdata = {
+ .reg_init_data = { \
+ .constraints = { \
+ .min_uV = 900000, \
+ .max_uV = 1400000, \
+ .valid_modes_mask = (REGULATOR_MODE_NORMAL | \
+ REGULATOR_MODE_STANDBY), \
+ .valid_ops_mask = (REGULATOR_CHANGE_MODE | \
+ REGULATOR_CHANGE_STATUS | \
+ REGULATOR_CHANGE_VOLTAGE), \
+ .always_on = 1, \
+ .boot_on = 1, \
+ .apply_uV = 0, \
+ }, \
+ .num_consumer_supplies = ARRAY_SIZE(tps6236x_dcdc_supply), \
+ .consumer_supplies = tps6236x_dcdc_supply, \
+ }, \
+ .en_discharge = true, \
+ .vsel0_gpio = -1, \
+ .vsel1_gpio = -1, \
+ .vsel0_def_state = 1, \
+ .vsel1_def_state = 1, \
+};
+
+static struct i2c_board_info __initdata tps6236x_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("tps62360", 0x60),
+ .platform_data = &tps6236x_pdata,
+ },
+};
+
+/* Macro for defining fixed regulator sub device data */
+#define FIXED_SUPPLY(_name) "fixed_reg_"#_name
+#define FIXED_REG_OD(_id, _var, _name, _in_supply, _always_on, \
+ _boot_on, _gpio_nr, _active_high, _boot_state, \
+ _millivolts, _od_state) \
+ static struct regulator_init_data ri_data_##_var = \
+ { \
+ .supply_regulator = _in_supply, \
+ .num_consumer_supplies = \
+ ARRAY_SIZE(fixed_reg_##_name##_supply), \
+ .consumer_supplies = fixed_reg_##_name##_supply, \
+ .constraints = { \
+ .valid_modes_mask = (REGULATOR_MODE_NORMAL), \
+ .valid_ops_mask = (REGULATOR_CHANGE_STATUS), \
+ .always_on = _always_on, \
+ .boot_on = _boot_on, \
+ }, \
+ }; \
+ static struct fixed_voltage_config fixed_reg_##_var##_pdata = \
+ { \
+ .supply_name = FIXED_SUPPLY(_name), \
+ .microvolts = _millivolts * 1000, \
+ .gpio = _gpio_nr, \
+ .enable_high = _active_high, \
+ .enabled_at_boot = _boot_state, \
+ .init_data = &ri_data_##_var, \
+ .gpio_is_open_drain = _od_state, \
+ }; \
+ static struct platform_device fixed_reg_##_var##_dev = { \
+ .name = "reg-fixed-voltage", \
+ .id = _id, \
+ .dev = { \
+ .platform_data = &fixed_reg_##_var##_pdata, \
+ }, \
+ }
+
+#define FIXED_REG(_id, _var, _name, _in_supply, _always_on, _boot_on, \
+ _gpio_nr, _active_high, _boot_state, _millivolts) \
+ FIXED_REG_OD(_id, _var, _name, _in_supply, _always_on, _boot_on, \
+ _gpio_nr, _active_high, _boot_state, _millivolts, false)
+
+#define ADD_FIXED_REG(_name) (&fixed_reg_##_name##_dev)
+
+/* PMU GP6: EN_VDD_HDMI switching via FET: +V1.8_AVDD_HDMI_PLL and +V3.3_AVDD_HDMI */
+static struct regulator_consumer_supply fixed_reg_en_hdmi_supply[] = {
+ REGULATOR_SUPPLY("avdd_hdmi", NULL),
+ REGULATOR_SUPPLY("avdd_hdmi_pll", NULL),
+// REGULATOR_SUPPLY("vdd_3v3_hdmi_cec", NULL),
+// REGULATOR_SUPPLY("vdd_hdmi_con", NULL),
+};
+
+//EN_VDD_CORE PMIC GPIO2
+//EN_VDD_FUSE PMIC GPIO4
+//EN_VDD_HDMI PMIC GPIO6
+
+FIXED_REG(2, en_hdmi, en_hdmi, NULL, 0, 0, TPS6591X_GPIO_6, true, 1, 1800);
+
+/* +V3.3 is switched on by LDO2, As this can not be modeled we use a fixed
+ regulator without enable, 3.3V must not be switched off anyway.
++V3.3:
+VDD_DDR_RX
+VDDIO_LCD_1
+VDDIO_LCD_2
+VDDIO_CAM
+LM95245
+VDDIO_SYS_01
+VDDIO_SYS_02
+VDDIO_BB
+VDDIO_AUDIO
+VDDIO_GMI_1
+VDDIO_GMI_2
+VDDIO_GMI_3
+VDDIO_UART
+VDDIO_SDMMC1
+AVDD_USB
+VDDIO_SDMMC3
+74AVCAH164245
+VDDIO_PEX_CTL
+TPS65911 VDDIO
+MT29F16G08
+SGTL5000 VDDIO
+STMPE811
+AX88772B VCC3x
+SDIN5D2-2G VCCx */
+static struct regulator_consumer_supply fixed_reg_v3_3_supply[] = {
+ REGULATOR_SUPPLY("avdd_audio", NULL),
+ REGULATOR_SUPPLY("avdd_usb", NULL),
+ REGULATOR_SUPPLY("vddio_sd_slot", "sdhci-tegra.1"),
+ REGULATOR_SUPPLY("vddio_sys", NULL),
+ REGULATOR_SUPPLY("vddio_uart", NULL),
+ REGULATOR_SUPPLY("pwrdet_uart", NULL),
+ REGULATOR_SUPPLY("vddio_audio", NULL),
+ REGULATOR_SUPPLY("pwrdet_audio", NULL),
+ REGULATOR_SUPPLY("vddio_bb", NULL),
+ REGULATOR_SUPPLY("pwrdet_bb", NULL),
+ REGULATOR_SUPPLY("vddio_lcd_pmu", NULL),
+ REGULATOR_SUPPLY("pwrdet_lcd", NULL),
+ REGULATOR_SUPPLY("vddio_cam", NULL),
+ REGULATOR_SUPPLY("pwrdet_cam", NULL),
+ /* if this supply is defined, the sdhci driver tries
+ * to set it to 1.8V */
+// REGULATOR_SUPPLY("vddio_sdmmc", "sdhci-tegra.1"),
+ REGULATOR_SUPPLY("pwrdet_sdmmc2", NULL),
+ REGULATOR_SUPPLY("pwrdet_sdmmc1", NULL),
+ REGULATOR_SUPPLY("pwrdet_sdmmc3", NULL),
+ REGULATOR_SUPPLY("pwrdet_pex_ctl", NULL),
+ REGULATOR_SUPPLY("pwrdet_nand", NULL),
+
+ /* SGTL5000 */
+ REGULATOR_SUPPLY("VDDA", "4-000a"),
+ REGULATOR_SUPPLY("VDDIO", "4-000a"),
+};
+
+FIXED_REG(3, v3_3, v3_3, NULL, 1, 1, -1, true, 1, 3300);
+
+/* Gpio switch regulator platform data */
+static struct platform_device *fixed_reg_devs_colibri_t30[] = {
+ ADD_FIXED_REG(en_hdmi),
+ ADD_FIXED_REG(v3_3),
+};
+
+int __init colibri_t30_regulator_init(void)
+{
+ void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
+ u32 pmc_ctrl;
+
+ /* configure the power management controller to trigger PMU
+ * interrupts when low */
+
+ pmc_ctrl = readl(pmc + PMC_CTRL);
+ writel(pmc_ctrl | PMC_CTRL_INTR_LOW, pmc + PMC_CTRL);
+
+ /* The regulator details have complete constraints */
+ regulator_has_full_constraints();
+
+ tps_platform.num_subdevs =
+ ARRAY_SIZE(colibri_t30_tps_devs);
+ tps_platform.subdevs = colibri_t30_tps_devs;
+
+ i2c_register_board_info(4, colibri_t30_regulators, 1);
+
+ /* Register the TPS6236x. */
+ pr_info("Registering the device TPS62360\n");
+ i2c_register_board_info(4, tps6236x_boardinfo, 1);
+
+ return 0;
+}
+
+int __init colibri_t20_fixed_regulator_init(void)
+{
+ return platform_add_devices(fixed_reg_devs_colibri_t30, ARRAY_SIZE(fixed_reg_devs_colibri_t30));
+}
+subsys_initcall_sync(colibri_t20_fixed_regulator_init);
+
+static void colibri_t30_board_suspend(int lp_state, enum suspend_stage stg)
+{
+ if ((lp_state == TEGRA_SUSPEND_LP1) && (stg == TEGRA_SUSPEND_BEFORE_CPU))
+ tegra_console_uart_suspend();
+}
+
+static void colibri_t30_board_resume(int lp_state, enum resume_stage stg)
+{
+ if ((lp_state == TEGRA_SUSPEND_LP1) && (stg == TEGRA_RESUME_AFTER_CPU))
+ tegra_console_uart_resume();
+}
+
+static struct tegra_suspend_platform_data colibri_t30_suspend_data = {
+ .cpu_timer = 2000,
+ .cpu_off_timer = 200,
+ .suspend_mode = TEGRA_SUSPEND_LP1,
+ .core_timer = 0x7e7e,
+ .core_off_timer = 0,
+ .corereq_high = true,
+ .sysclkreq_high = true,
+ .cpu_lp2_min_residency = 2000,
+ .board_suspend = colibri_t30_board_suspend,
+ .board_resume = colibri_t30_board_resume,
+};
+
+int __init colibri_t30_suspend_init(void)
+{
+ /* Make core_pwr_req to high */
+ colibri_t30_suspend_data.corereq_high = true;
+
+ /* CORE_PWR_REQ to be high required to enable the dc-dc converter tps62361x */
+ colibri_t30_suspend_data.corereq_high = true;
+
+//required?
+ colibri_t30_suspend_data.cpu_timer = 5000;
+ colibri_t30_suspend_data.cpu_off_timer = 5000;
+
+ tegra_init_suspend(&colibri_t30_suspend_data);
+ return 0;
+}
+
+#ifdef CONFIG_TEGRA_EDP_LIMITS
+int __init colibri_t30_edp_init(void)
+{
+ unsigned int regulator_mA;
+
+ regulator_mA = get_maximum_cpu_current_supported();
+ if (!regulator_mA) {
+ regulator_mA = 6000; /* regular T30/s */
+ }
+ pr_info("%s: CPU regulator %d mA\n", __func__, regulator_mA);
+
+ tegra_init_cpu_edp_limits(regulator_mA);
+ return 0;
+}
+#endif
diff --git a/arch/arm/mach-tegra/board-colibri_t30.c b/arch/arm/mach-tegra/board-colibri_t30.c
new file mode 100644
index 000000000000..f08b38b6cbbe
--- /dev/null
+++ b/arch/arm/mach-tegra/board-colibri_t30.c
@@ -0,0 +1,1232 @@
+/*
+ * arch/arm/mach-tegra/board-colibri_t30.c
+ *
+ * Copyright (c) 2012-2013 Toradex, Inc.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <linux/clk.h>
+#include <linux/colibri_usb.h>
+#include <linux/types.h> /* required by linux/gpio_keys.h */
+#include <linux/gpio_keys.h>
+#include <linux/i2c.h>
+#include <linux/i2c-tegra.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/leds_pwm.h>
+#include <linux/lm95245.h>
+#include <linux/mfd/stmpe.h>
+#include <linux/platform_data/tegra_usb.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/spi/spi.h>
+#include <linux/spi-tegra.h>
+#include <linux/tegra_uart.h>
+
+#include <mach/io_dpd.h>
+#include <mach/sdhci.h>
+#include <mach/tegra_asoc_pdata.h>
+#include <mach/tegra_fiq_debugger.h>
+#include <mach/thermal.h>
+#include <mach/usb_phy.h>
+#include <mach/w1.h>
+
+#include "board-colibri_t30.h"
+#include "board.h"
+#include "clock.h"
+#include "devices.h"
+#include "gpio-names.h"
+#include "pm.h"
+
+/* ADC */
+
+//TODO
+
+/* Audio */
+
+static struct tegra_asoc_platform_data colibri_t30_audio_sgtl5000_pdata = {
+ .gpio_spkr_en = -1,
+ .gpio_hp_det = -1,
+ .gpio_hp_mute = -1,
+ .gpio_int_mic_en = -1,
+ .gpio_ext_mic_en = -1,
+ .i2s_param[HIFI_CODEC] = {
+ .audio_port_id = 0, /* index of below registered
+ tegra_i2s_device */
+ .i2s_mode = TEGRA_DAIFMT_I2S,
+ .is_i2s_master = 1,
+ .sample_size = 16,
+ },
+ .i2s_param[BASEBAND] = {
+ .audio_port_id = -1,
+ },
+ .i2s_param[BT_SCO] = {
+ .audio_port_id = -1,
+ },
+};
+
+static struct platform_device colibri_t30_audio_sgtl5000_device = {
+ .name = "tegra-snd-colibri_t30-sgtl5000",
+ .id = 0,
+ .dev = {
+ .platform_data = &colibri_t30_audio_sgtl5000_pdata,
+ },
+};
+
+#ifdef CONFIG_TEGRA_CAMERA
+/* Camera */
+static struct platform_device tegra_camera = {
+ .name = "tegra_camera",
+ .id = -1,
+};
+#endif /* CONFIG_TEGRA_CAMERA */
+
+/* Clocks */
+static struct tegra_clk_init_table colibri_t30_clk_init_table[] __initdata = {
+ /* name parent rate enabled */
+ {"audio1", "i2s1_sync", 0, false},
+ {"audio2", "i2s2_sync", 0, false},
+ {"audio3", "i2s3_sync", 0, false},
+ {"blink", "clk_32k", 32768, true},
+ {"d_audio", "clk_m", 12000000, false},
+ {"dam0", "clk_m", 12000000, false},
+ {"dam1", "clk_m", 12000000, false},
+ {"dam2", "clk_m", 12000000, false},
+
+//required?
+ {"hda", "pll_p", 108000000, false},
+ {"hda2codec_2x","pll_p", 48000000, false},
+
+ {"i2c1", "pll_p", 3200000, false},
+ {"i2c2", "pll_p", 3200000, false},
+ {"i2c3", "pll_p", 3200000, false},
+ {"i2c4", "pll_p", 3200000, false},
+ {"i2c5", "pll_p", 3200000, false},
+ {"i2s0", "pll_a_out0", 0, false},
+ {"i2s1", "pll_a_out0", 0, false},
+ {"i2s2", "pll_a_out0", 0, false},
+ {"i2s3", "pll_a_out0", 0, false},
+ {"pll_m", NULL, 0, false},
+ {"pwm", "pll_p", 3187500, false},
+ {"spdif_out", "pll_a_out0", 0, false},
+ {"vi", "pll_p", 0, false},
+ {"vi_sensor", "pll_p", 150000000, false},
+ {NULL, NULL, 0, 0},
+};
+
+/* GPIO */
+
+//TODO: sysfs GPIO exports
+
+/* I2C */
+
+/* Make sure that the pinmuxing enable the 'open drain' feature for pins used
+ for I2C */
+
+/* GEN1_I2C: I2C_SDA/SCL on SODIMM pin 194/196 (e.g. RTC on carrier board) */
+static struct i2c_board_info colibri_t30_i2c_bus1_board_info[] __initdata = {
+ {
+ /* M41T0M6 real time clock on Iris carrier board */
+ I2C_BOARD_INFO("rtc-ds1307", 0x68),
+ .type = "m41t00",
+ },
+#ifdef CONFIG_TOUCHSCREEN_FUSION_F0710A
+ {
+ /* TouchRevolution Fusion 7 and 10 multi-touch controller */
+ I2C_BOARD_INFO("fusion_F0710A", 0x10),
+ },
+#endif /* CONFIG_TOUCHSCREEN_FUSION_F0710A */
+};
+
+static struct tegra_i2c_platform_data colibri_t30_i2c1_platform_data = {
+ .adapter_nr = 0,
+ .arb_recovery = arb_lost_recovery,
+ .bus_clk_rate = {400000, 0},
+ .bus_count = 1,
+ .scl_gpio = {I2C_SCL, 0},
+ .sda_gpio = {I2C_SDA, 0},
+ .slave_addr = 0x00FC,
+};
+
+/* GEN2_I2C: unused */
+
+/* DDC_CLOCK/DATA on X3 pin 15/16 (e.g. display EDID) */
+static struct tegra_i2c_platform_data colibri_t30_i2c4_platform_data = {
+ .adapter_nr = 3,
+ .arb_recovery = arb_lost_recovery,
+ .bus_clk_rate = {10000, 10000},
+ .bus_count = 1,
+ .scl_gpio = {DDC_SCL, 0},
+ .sda_gpio = {DDC_SDA, 0},
+ .slave_addr = 0x00FC,
+};
+
+/* PWR_I2C: power I2C to audio codec, PMIC, temperature sensor and touch screen
+ controller */
+
+/* STMPE811 touch screen controller */
+static struct stmpe_ts_platform_data stmpe811_ts_data = {
+ .adc_freq = 1, /* 3.25 MHz ADC clock speed */
+ .ave_ctrl = 3, /* 8 sample average control */
+ .fraction_z = 7, /* 7 length fractional part in z */
+ .i_drive = 1, /* 50 mA typical 80 mA max touchscreen
+ drivers current limit value */
+ .mod_12b = 1, /* 12-bit ADC */
+ .ref_sel = 0, /* internal ADC reference */
+ .sample_time = 4, /* ADC converstion time: 80 clocks */
+ .settling = 3, /* 1 ms panel driver settling time */
+ .touch_det_delay = 5, /* 5 ms touch detect interrupt delay */
+};
+
+static struct stmpe_platform_data stmpe811_data = {
+ .blocks = STMPE_BLOCK_TOUCHSCREEN,
+ .id = 1,
+ .irq_base = STMPE811_IRQ_BASE,
+ .irq_trigger = IRQF_TRIGGER_FALLING,
+ .ts = &stmpe811_ts_data,
+};
+
+static void lm95245_probe_callback(struct device *dev);
+
+static struct lm95245_platform_data colibri_t30_lm95245_pdata = {
+ .enable_os_pin = true,
+ .probe_callback = lm95245_probe_callback,
+};
+
+static struct i2c_board_info colibri_t30_i2c_bus5_board_info[] __initdata = {
+ {
+ /* SGTL5000 audio codec */
+ I2C_BOARD_INFO("sgtl5000", 0x0a),
+ },
+ {
+ /* STMPE811 touch screen controller */
+ I2C_BOARD_INFO("stmpe", 0x41),
+ .flags = I2C_CLIENT_WAKE,
+ .platform_data = &stmpe811_data,
+ .type = "stmpe811",
+ },
+ {
+ /* LM95245 temperature sensor
+ Note: OVERT_N directly connected to PMIC PWRDN */
+ I2C_BOARD_INFO("lm95245", 0x4c),
+ .platform_data = &colibri_t30_lm95245_pdata,
+ },
+};
+
+static struct tegra_i2c_platform_data colibri_t30_i2c5_platform_data = {
+ .adapter_nr = 4,
+ .arb_recovery = arb_lost_recovery,
+ .bus_clk_rate = {400000, 0},
+ .bus_count = 1,
+ .scl_gpio = {PWR_I2C_SCL, 0},
+ .sda_gpio = {PWR_I2C_SDA, 0},
+};
+
+static void __init colibri_t30_i2c_init(void)
+{
+ tegra_i2c_device1.dev.platform_data = &colibri_t30_i2c1_platform_data;
+ tegra_i2c_device4.dev.platform_data = &colibri_t30_i2c4_platform_data;
+ tegra_i2c_device5.dev.platform_data = &colibri_t30_i2c5_platform_data;
+
+ platform_device_register(&tegra_i2c_device1);
+ platform_device_register(&tegra_i2c_device4);
+ platform_device_register(&tegra_i2c_device5);
+
+#ifdef CONFIG_TOUCHSCREEN_FUSION_F0710A
+ if ((gpio_request(FUSION_PEN_DOWN, "103, Iris X16-15 Pen") == 0) &&
+ (gpio_direction_input(FUSION_PEN_DOWN) == 0)) {
+ gpio_export(FUSION_PEN_DOWN, 0);
+ } else {
+ printk(KERN_ERR "Could not obtain GPIO for Fusion pen down\n");
+ return;
+ }
+
+ if ((gpio_request(FUSION_RESET, "101, Iris X16-16 RST") == 0) &&
+ (gpio_direction_output(FUSION_RESET, 1) == 0)) {
+ gpio_direction_output(FUSION_RESET, 0);
+ mdelay(10);
+ gpio_direction_output(FUSION_RESET, 1);
+ } else {
+ printk(KERN_ERR "Could not obtain GPIO for Fusion reset\n");
+ return;
+ }
+
+ colibri_t30_i2c_bus1_board_info[1].irq = gpio_to_irq(FUSION_PEN_DOWN);
+#endif /* CONFIG_TOUCHSCREEN_FUSION_F0710A */
+
+ i2c_register_board_info(0, colibri_t30_i2c_bus1_board_info,
+ ARRAY_SIZE(colibri_t30_i2c_bus1_board_info));
+
+ /* enable touch interrupt GPIO */
+ gpio_request(TOUCH_PEN_INT, "TOUCH_PEN_INT");
+ gpio_direction_input(TOUCH_PEN_INT);
+
+ colibri_t30_i2c_bus5_board_info[1].irq = gpio_to_irq(TOUCH_PEN_INT);
+ i2c_register_board_info(4, colibri_t30_i2c_bus5_board_info,
+ ARRAY_SIZE(colibri_t30_i2c_bus5_board_info));
+}
+
+/* Keys
+ Note: active-low means pull-ups required on carrier board resp. via
+ pin-muxing
+ Note2: power-key active-high due to EvalBoard v3.1a having 100 K pull-down
+ on SODIMM pin 45 */
+
+#ifdef CONFIG_KEYBOARD_GPIO
+#define GPIO_KEY(_id, _gpio, _lowactive, _iswake) \
+ { \
+ .code = _id, \
+ .gpio = TEGRA_GPIO_##_gpio, \
+ .active_low = _lowactive, \
+ .desc = #_id, \
+ .type = EV_KEY, \
+ .wakeup = _iswake, \
+ .debounce_interval = 10, \
+ }
+
+static struct gpio_keys_button colibri_t30_keys[] = {
+#ifndef COLIBRI_T30_VI
+ GPIO_KEY(KEY_FIND, PCC2, 1, 0), /* SODIMM pin 77 */
+#endif
+ GPIO_KEY(KEY_HOME, PT6, 1, 0), /* SODIMM pin 127 */
+ GPIO_KEY(KEY_BACK, PT5, 1, 1), /* SODIMM pin 133,
+ Iris X16-14 */
+ GPIO_KEY(KEY_VOLUMEUP, PDD7, 1, 0), /* SODIMM pin 22 */
+ GPIO_KEY(KEY_VOLUMEDOWN, PCC6, 1, 0), /* SODIMM pin 24 */
+ GPIO_KEY(KEY_POWER, PV1, 0, 1), /* SODIMM pin 45,
+ Iris X16-20 */
+ GPIO_KEY(KEY_MENU, PK6, 1, 0), /* SODIMM pin 135 */
+};
+
+static struct gpio_keys_platform_data colibri_t30_keys_platform_data = {
+ .buttons = colibri_t30_keys,
+ .nbuttons = ARRAY_SIZE(colibri_t30_keys),
+};
+
+static struct platform_device colibri_t30_keys_device = {
+ .name = "gpio-keys",
+ .id = 0,
+ .dev = {
+ .platform_data = &colibri_t30_keys_platform_data,
+ },
+};
+#endif /* CONFIG_KEYBOARD_GPIO */
+
+/* MMC/SD */
+
+#ifndef COLIBRI_T30_SDMMC4B
+static struct tegra_sdhci_platform_data colibri_t30_emmc_platform_data = {
+ .cd_gpio = -1,
+ .ddr_clk_limit = 52000000,
+ .is_8bit = 1,
+ .mmc_data = {
+ .built_in = 1,
+ },
+ .power_gpio = -1,
+ .tap_delay = 0x0f,
+ .wp_gpio = -1,
+};
+#endif /* COLIBRI_T30_SDMMC4B */
+
+static struct tegra_sdhci_platform_data colibri_t30_sdcard_platform_data = {
+ .cd_gpio = MMC_CD,
+ .ddr_clk_limit = 52000000,
+ .is_8bit = 0,
+ .power_gpio = -1,
+ .tap_delay = 0x0f,
+ .wp_gpio = -1,
+};
+
+static void __init colibri_t30_sdhci_init(void)
+{
+ /* register eMMC first */
+ tegra_sdhci_device4.dev.platform_data =
+#ifdef COLIBRI_T30_SDMMC4B
+ &colibri_t30_sdcard_platform_data;
+#else
+ &colibri_t30_emmc_platform_data;
+#endif
+ platform_device_register(&tegra_sdhci_device4);
+
+#ifndef COLIBRI_T30_SDMMC4B
+ tegra_sdhci_device2.dev.platform_data =
+ &colibri_t30_sdcard_platform_data;
+ platform_device_register(&tegra_sdhci_device2);
+#endif
+}
+
+/* PWM LEDs */
+static struct led_pwm tegra_leds_pwm[] = {
+ {
+ .name = "PWM<B>",
+ .pwm_id = 1,
+ .max_brightness = 255,
+ .pwm_period_ns = 19600,
+ },
+ {
+ .name = "PWM<C>",
+ .pwm_id = 2,
+ .max_brightness = 255,
+ .pwm_period_ns = 19600,
+ },
+ {
+ .name = "PWM<D>",
+ .pwm_id = 3,
+ .max_brightness = 255,
+ .pwm_period_ns = 19600,
+ },
+};
+
+static struct led_pwm_platform_data tegra_leds_pwm_data = {
+ .num_leds = ARRAY_SIZE(tegra_leds_pwm),
+ .leds = tegra_leds_pwm,
+};
+
+static struct platform_device tegra_led_pwm_device = {
+ .name = "leds_pwm",
+ .id = -1,
+ .dev = {
+ .platform_data = &tegra_leds_pwm_data,
+ },
+};
+
+/* RTC */
+
+#ifdef CONFIG_RTC_DRV_TEGRA
+static struct resource tegra_rtc_resources[] = {
+ [0] = {
+ .start = TEGRA_RTC_BASE,
+ .end = TEGRA_RTC_BASE + TEGRA_RTC_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = INT_RTC,
+ .end = INT_RTC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tegra_rtc_device = {
+ .name = "tegra_rtc",
+ .id = -1,
+ .resource = tegra_rtc_resources,
+ .num_resources = ARRAY_SIZE(tegra_rtc_resources),
+};
+#endif /* CONFIG_RTC_DRV_TEGRA */
+
+/* SPI */
+
+#if defined(CONFIG_SPI_TEGRA) && defined(CONFIG_SPI_SPIDEV)
+static struct spi_board_info tegra_spi_devices[] __initdata = {
+ {
+ .bus_num = 0, /* SPI1: Colibri SSP */
+ .chip_select = 0,
+ .irq = 0,
+ .max_speed_hz = 50000000,
+ .modalias = "spidev",
+ .mode = SPI_MODE_0,
+ .platform_data = NULL,
+ },
+};
+
+static void __init colibri_t30_register_spidev(void)
+{
+ spi_register_board_info(tegra_spi_devices,
+ ARRAY_SIZE(tegra_spi_devices));
+}
+#else /* CONFIG_SPI_TEGRA && CONFIG_SPI_SPIDEV */
+#define colibri_t30_register_spidev() do {} while (0)
+#endif /* CONFIG_SPI_TEGRA && CONFIG_SPI_SPIDEV */
+
+static struct platform_device *colibri_t30_spi_devices[] __initdata = {
+ &tegra_spi_device1,
+};
+
+static struct spi_clk_parent spi_parent_clk[] = {
+ [0] = {.name = "pll_p"},
+#ifndef CONFIG_TEGRA_PLLM_RESTRICTED
+ [1] = {.name = "pll_m"},
+ [2] = {.name = "clk_m"},
+#else /* !CONFIG_TEGRA_PLLM_RESTRICTED */
+ [1] = {.name = "clk_m"},
+#endif /* !CONFIG_TEGRA_PLLM_RESTRICTED */
+};
+
+static struct tegra_spi_platform_data colibri_t30_spi_pdata = {
+ .is_dma_based = true,
+ .max_dma_buffer = 16 * 1024,
+ .is_clkon_always = false,
+ .max_rate = 100000000,
+};
+
+static void __init colibri_t30_spi_init(void)
+{
+ int i;
+ struct clk *c;
+
+ for (i = 0; i < ARRAY_SIZE(spi_parent_clk); ++i) {
+ c = tegra_get_clock_by_name(spi_parent_clk[i].name);
+ if (IS_ERR_OR_NULL(c)) {
+ pr_err("Not able to get the clock for %s\n",
+ spi_parent_clk[i].name);
+ continue;
+ }
+ spi_parent_clk[i].parent_clk = c;
+ spi_parent_clk[i].fixed_clk_rate = clk_get_rate(c);
+ }
+ colibri_t30_spi_pdata.parent_clk_list = spi_parent_clk;
+ colibri_t30_spi_pdata.parent_clk_count = ARRAY_SIZE(spi_parent_clk);
+ tegra_spi_device1.dev.platform_data = &colibri_t30_spi_pdata;
+ platform_add_devices(colibri_t30_spi_devices,
+ ARRAY_SIZE(colibri_t30_spi_devices));
+}
+
+/* Thermal throttling */
+
+static void *colibri_t30_alert_data;
+static void (*colibri_t30_alert_func)(void *);
+static int colibri_t30_low_edge = 0;
+static int colibri_t30_low_hysteresis = 3000;
+static int colibri_t30_low_limit = 0;
+static struct device *lm95245_device = NULL;
+static int thermd_alert_irq_disabled = 0;
+struct work_struct thermd_alert_work;
+struct workqueue_struct *thermd_alert_workqueue;
+
+static struct balanced_throttle throttle_list[] = {
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+ {
+ .id = BALANCED_THROTTLE_ID_TJ,
+ .throt_tab_size = 10,
+ .throt_tab = {
+ { 0, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 760000, 1000 },
+ { 760000, 1050 },
+ {1000000, 1050 },
+ {1000000, 1100 },
+ },
+ },
+#endif /* CONFIG_TEGRA_THERMAL_THROTTLE */
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ {
+ .id = BALANCED_THROTTLE_ID_SKIN,
+ .throt_tab_size = 6,
+ .throt_tab = {
+ { 640000, 1200 },
+ { 640000, 1200 },
+ { 760000, 1200 },
+ { 760000, 1200 },
+ {1000000, 1200 },
+ {1000000, 1200 },
+ },
+ },
+#endif /* CONFIG_TEGRA_SKIN_THROTTLE */
+};
+
+/* All units are in millicelsius */
+static struct tegra_thermal_data thermal_data = {
+ .shutdown_device_id = THERMAL_DEVICE_ID_NCT_EXT,
+ .temp_shutdown = 115000,
+
+#if defined(CONFIG_TEGRA_EDP_LIMITS) || defined(CONFIG_TEGRA_THERMAL_THROTTLE)
+ .throttle_edp_device_id = THERMAL_DEVICE_ID_NCT_EXT,
+#endif
+#ifdef CONFIG_TEGRA_EDP_LIMITS
+ .edp_offset = TDIODE_OFFSET, /* edp based on tdiode */
+ .hysteresis_edp = 3000,
+#endif
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+ .temp_throttle = 85000,
+ .tc1 = 0,
+ .tc2 = 1,
+ .passive_delay = 2000,
+#endif /* CONFIG_TEGRA_THERMAL_THROTTLE */
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ .skin_device_id = THERMAL_DEVICE_ID_SKIN,
+ .temp_throttle_skin = 43000,
+ .tc1_skin = 0,
+ .tc2_skin = 1,
+ .passive_delay_skin = 5000,
+
+ .skin_temp_offset = 9793,
+ .skin_period = 1100,
+ .skin_devs_size = 2,
+ .skin_devs = {
+ {
+ THERMAL_DEVICE_ID_NCT_EXT,
+ {
+ 2, 1, 1, 1,
+ 1, 1, 1, 1,
+ 1, 1, 1, 0,
+ 1, 1, 0, 0,
+ 0, 0, -1, -7
+ }
+ },
+ {
+ THERMAL_DEVICE_ID_NCT_INT,
+ {
+ -11, -7, -5, -3,
+ -3, -2, -1, 0,
+ 0, 0, 1, 1,
+ 1, 2, 2, 3,
+ 4, 6, 11, 18
+ }
+ },
+ },
+#endif /* CONFIG_TEGRA_SKIN_THROTTLE */
+};
+
+/* Over-temperature shutdown OS aka high limit GPIO pin interrupt handler */
+static irqreturn_t thermd_alert_irq(int irq, void *data)
+{
+ disable_irq_nosync(irq);
+ thermd_alert_irq_disabled = 1;
+ queue_work(thermd_alert_workqueue, &thermd_alert_work);
+
+ return IRQ_HANDLED;
+}
+
+/* Gets both entered by THERMD_ALERT GPIO interrupt as well as re-scheduled. */
+static void thermd_alert_work_func(struct work_struct *work)
+{
+ int temp = 0;
+
+ lm95245_get_remote_temp(lm95245_device, &temp);
+
+ /* This emulates NCT1008 low limit behaviour */
+ if (!colibri_t30_low_edge && temp <= colibri_t30_low_limit) {
+ colibri_t30_alert_func(colibri_t30_alert_data);
+ colibri_t30_low_edge = 1;
+ } else if (colibri_t30_low_edge && temp > colibri_t30_low_limit +
+ colibri_t30_low_hysteresis) {
+ colibri_t30_low_edge = 0;
+ }
+
+ /* Avoid unbalanced enable for IRQ 367 */
+ if (thermd_alert_irq_disabled) {
+ colibri_t30_alert_func(colibri_t30_alert_data);
+ thermd_alert_irq_disabled = 0;
+ enable_irq(gpio_to_irq(THERMD_ALERT));
+ }
+
+ /* Keep re-scheduling */
+ msleep(2000);
+ queue_work(thermd_alert_workqueue, &thermd_alert_work);
+}
+
+static int lm95245_get_temp(void *_data, long *temp)
+{
+ struct device *lm95245_device = _data;
+ int lm95245_temp = 0;
+ lm95245_get_remote_temp(lm95245_device, &lm95245_temp);
+ *temp = lm95245_temp;
+ return 0;
+}
+
+static int lm95245_get_temp_low(void *_data, long *temp)
+{
+ *temp = 0;
+ return 0;
+}
+
+/* Our temperature sensor only allows triggering an interrupt on over-
+ temperature shutdown aka the high limit we therefore need to setup a
+ workqueue to catch leaving the low limit. */
+static int lm95245_set_limits(void *_data,
+ long lo_limit_milli,
+ long hi_limit_milli)
+{
+ struct device *lm95245_device = _data;
+ colibri_t30_low_limit = lo_limit_milli;
+ if (lm95245_device) lm95245_set_remote_os_limit(lm95245_device,
+ hi_limit_milli);
+ return 0;
+}
+
+static int lm95245_set_alert(void *_data,
+ void (*alert_func)(void *),
+ void *alert_data)
+{
+ lm95245_device = _data;
+ colibri_t30_alert_func = alert_func;
+ colibri_t30_alert_data = alert_data;
+ return 0;
+}
+
+static int lm95245_set_shutdown_temp(void *_data, long shutdown_temp)
+{
+ struct device *lm95245_device = _data;
+ if (lm95245_device) lm95245_set_remote_critical_limit(lm95245_device,
+ shutdown_temp);
+ return 0;
+}
+
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+/* Internal aka local board/case temp */
+static int lm95245_get_itemp(void *dev_data, long *temp)
+{
+ struct device *lm95245_device = dev_data;
+ int lm95245_temp = 0;
+ lm95245_get_local_temp(lm95245_device, &lm95245_temp);
+ *temp = lm95245_temp;
+ return 0;
+}
+#endif /* CONFIG_TEGRA_SKIN_THROTTLE */
+
+static void lm95245_probe_callback(struct device *dev)
+{
+ struct tegra_thermal_device *lm95245_remote;
+
+ lm95245_remote = kzalloc(sizeof(struct tegra_thermal_device),
+ GFP_KERNEL);
+ if (!lm95245_remote) {
+ pr_err("unable to allocate thermal device\n");
+ return;
+ }
+
+ lm95245_remote->name = "lm95245_remote";
+ lm95245_remote->id = THERMAL_DEVICE_ID_NCT_EXT;
+ lm95245_remote->data = dev;
+ lm95245_remote->offset = TDIODE_OFFSET;
+ lm95245_remote->get_temp = lm95245_get_temp;
+ lm95245_remote->get_temp_low = lm95245_get_temp_low;
+ lm95245_remote->set_limits = lm95245_set_limits;
+ lm95245_remote->set_alert = lm95245_set_alert;
+ lm95245_remote->set_shutdown_temp = lm95245_set_shutdown_temp;
+
+ tegra_thermal_device_register(lm95245_remote);
+
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ {
+ struct tegra_thermal_device *lm95245_local;
+ lm95245_local = kzalloc(sizeof(struct tegra_thermal_device),
+ GFP_KERNEL);
+ if (!lm95245_local) {
+ kfree(lm95245_local);
+ pr_err("unable to allocate thermal device\n");
+ return;
+ }
+
+ lm95245_local->name = "lm95245_local";
+ lm95245_local->id = THERMAL_DEVICE_ID_NCT_INT;
+ lm95245_local->data = dev;
+ lm95245_local->get_temp = lm95245_get_itemp;
+
+ tegra_thermal_device_register(lm95245_local);
+ }
+#endif /* CONFIG_TEGRA_SKIN_THROTTLE */
+
+ if (request_irq(gpio_to_irq(THERMD_ALERT), thermd_alert_irq,
+ IRQF_TRIGGER_LOW, "THERMD_ALERT", NULL))
+ pr_err("%s: unable to register THERMD_ALERT interrupt\n",
+ __func__);
+}
+
+static void colibri_t30_thermd_alert_init(void)
+{
+ gpio_request(THERMD_ALERT, "THERMD_ALERT");
+ gpio_direction_input(THERMD_ALERT);
+
+ thermd_alert_workqueue = create_singlethread_workqueue("THERMD_ALERT");
+
+ INIT_WORK(&thermd_alert_work, thermd_alert_work_func);
+}
+
+/* UART */
+
+static struct platform_device *colibri_t30_uart_devices[] __initdata = {
+ &tegra_uarta_device, /* Colibri FFUART */
+ &tegra_uartd_device, /* Colibri BTUART */
+ &tegra_uartb_device, /* Colibri STDUART */
+};
+
+static struct uart_clk_parent uart_parent_clk[] = {
+ [0] = {.name = "clk_m"},
+ [1] = {.name = "pll_p"},
+#ifndef CONFIG_TEGRA_PLLM_RESTRICTED
+ [2] = {.name = "pll_m"},
+#endif
+};
+
+static struct tegra_uart_platform_data colibri_t30_uart_pdata;
+
+static void __init uart_debug_init(void)
+{
+ int debug_port_id;
+
+ debug_port_id = get_tegra_uart_debug_port_id();
+ if (debug_port_id < 0) {
+ debug_port_id = 0;
+ }
+
+ switch (debug_port_id) {
+ case 0:
+ /* UARTA is the debug port. */
+ pr_info("Selecting UARTA as the debug console\n");
+ colibri_t30_uart_devices[0] = &debug_uarta_device;
+ debug_uart_clk = clk_get_sys("serial8250.0", "uarta");
+ debug_uart_port_base = ((struct plat_serial8250_port *)(
+ debug_uarta_device.dev.platform_data))->mapbase;
+ break;
+
+ case 1:
+ /* UARTB is the debug port. */
+ pr_info("Selecting UARTB as the debug console\n");
+ colibri_t30_uart_devices[2] = &debug_uartb_device;
+ debug_uart_clk = clk_get_sys("serial8250.0", "uartb");
+ debug_uart_port_base = ((struct plat_serial8250_port *)(
+ debug_uartb_device.dev.platform_data))->mapbase;
+ break;
+
+ case 3:
+ /* UARTD is the debug port. */
+ pr_info("Selecting UARTD as the debug console\n");
+ colibri_t30_uart_devices[1] = &debug_uartd_device;
+ debug_uart_clk = clk_get_sys("serial8250.0", "uartd");
+ debug_uart_port_base = ((struct plat_serial8250_port *)(
+ debug_uartd_device.dev.platform_data))->mapbase;
+ break;
+
+ default:
+ pr_info("The debug console id %d is invalid, Assuming UARTA",
+ debug_port_id);
+ colibri_t30_uart_devices[0] = &debug_uarta_device;
+ debug_uart_clk = clk_get_sys("serial8250.0", "uarta");
+ debug_uart_port_base = ((struct plat_serial8250_port *)(
+ debug_uarta_device.dev.platform_data))->mapbase;
+ break;
+ }
+ return;
+}
+
+static void __init colibri_t30_uart_init(void)
+{
+ struct clk *c;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(uart_parent_clk); ++i) {
+ c = tegra_get_clock_by_name(uart_parent_clk[i].name);
+ if (IS_ERR_OR_NULL(c)) {
+ pr_err("Not able to get the clock for %s\n",
+ uart_parent_clk[i].name);
+ continue;
+ }
+ uart_parent_clk[i].parent_clk = c;
+ uart_parent_clk[i].fixed_clk_rate = clk_get_rate(c);
+ }
+ colibri_t30_uart_pdata.parent_clk_list = uart_parent_clk;
+ colibri_t30_uart_pdata.parent_clk_count = ARRAY_SIZE(uart_parent_clk);
+ tegra_uarta_device.dev.platform_data = &colibri_t30_uart_pdata;
+ tegra_uartb_device.dev.platform_data = &colibri_t30_uart_pdata;
+ tegra_uartd_device.dev.platform_data = &colibri_t30_uart_pdata;
+
+ /* Register low speed only if it is selected */
+ if (!is_tegra_debug_uartport_hs()) {
+ uart_debug_init();
+ /* Clock enable for the debug channel */
+ if (!IS_ERR_OR_NULL(debug_uart_clk)) {
+ pr_info("The debug console clock name is %s\n",
+ debug_uart_clk->name);
+ c = tegra_get_clock_by_name("pll_p");
+ if (IS_ERR_OR_NULL(c))
+ pr_err("Not getting the parent clock pll_p\n");
+ else
+ clk_set_parent(debug_uart_clk, c);
+
+ clk_enable(debug_uart_clk);
+ clk_set_rate(debug_uart_clk, clk_get_rate(c));
+ } else {
+ pr_err("Not getting the clock %s for debug console\n",
+ debug_uart_clk->name);
+ }
+ }
+
+ platform_add_devices(colibri_t30_uart_devices,
+ ARRAY_SIZE(colibri_t30_uart_devices));
+}
+
+/* USB */
+
+//TODO: overcurrent
+
+static struct tegra_usb_platform_data tegra_udc_pdata = {
+ .has_hostpc = true,
+ .op_mode = TEGRA_USB_OPMODE_DEVICE,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .port_otg = true,
+ .u_cfg.utmi = {
+ .elastic_limit = 16,
+ .hssync_start_delay = 0,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup = 8,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
+ },
+ .u_data.dev = {
+ .charging_supported = false,
+ .remote_wakeup_supported = false,
+ .vbus_gpio = -1,
+ .vbus_pmu_irq = 0,
+ },
+};
+
+static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = {
+ .has_hostpc = true,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .port_otg = true,
+ .u_cfg.utmi = {
+ .elastic_limit = 16,
+ .hssync_start_delay = 0,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup = 15,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
+ },
+ .u_data.host = {
+ .hot_plug = true,
+ .power_off_on_suspend = false,
+ .remote_wakeup_supported = true,
+ .vbus_gpio = -1,
+ .vbus_reg = NULL,
+ },
+};
+
+static void ehci2_utmi_platform_post_phy_on(void)
+{
+ /* enable VBUS */
+ gpio_set_value(LAN_V_BUS, 1);
+
+ /* reset */
+ gpio_set_value(LAN_RESET, 0);
+
+ udelay(5);
+
+ /* unreset */
+ gpio_set_value(LAN_RESET, 1);
+}
+
+static void ehci2_utmi_platform_pre_phy_off(void)
+{
+ /* disable VBUS */
+ gpio_set_value(LAN_V_BUS, 0);
+}
+
+static struct tegra_usb_phy_platform_ops ehci2_utmi_plat_ops = {
+ .post_phy_on = ehci2_utmi_platform_post_phy_on,
+ .pre_phy_off = ehci2_utmi_platform_pre_phy_off,
+};
+
+static struct tegra_usb_platform_data tegra_ehci2_utmi_pdata = {
+ .has_hostpc = true,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .ops = &ehci2_utmi_plat_ops,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .port_otg = false,
+ .u_cfg.utmi = {
+ .elastic_limit = 16,
+ .hssync_start_delay = 0,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup = 15,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
+ },
+ .u_data.host = {
+ .hot_plug = false,
+ .power_off_on_suspend = true,
+ .remote_wakeup_supported = true,
+ .vbus_gpio = -1,
+ .vbus_reg = NULL,
+ },
+};
+
+static struct tegra_usb_platform_data tegra_ehci3_utmi_pdata = {
+ .has_hostpc = true,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .port_otg = false,
+ .u_cfg.utmi = {
+ .elastic_limit = 16,
+ .hssync_start_delay = 0,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup = 8,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
+ },
+ .u_data.host = {
+ .hot_plug = true,
+ .power_off_on_suspend = false,
+ .remote_wakeup_supported = true,
+ .vbus_gpio = USBH_PEN,
+ .vbus_gpio_inverted = 1,
+ .vbus_reg = NULL,
+ },
+};
+
+#ifndef CONFIG_USB_TEGRA_OTG
+static struct platform_device *tegra_usb_otg_host_register(void)
+{
+ struct platform_device *pdev;
+ void *platform_data;
+ int val;
+
+ pdev = platform_device_alloc(tegra_ehci1_device.name,
+ tegra_ehci1_device.id);
+ if (!pdev)
+ return NULL;
+
+ val = platform_device_add_resources(pdev, tegra_ehci1_device.resource,
+ tegra_ehci1_device.num_resources);
+ if (val)
+ goto error;
+
+ pdev->dev.dma_mask = tegra_ehci1_device.dev.dma_mask;
+ pdev->dev.coherent_dma_mask = tegra_ehci1_device.dev.coherent_dma_mask;
+
+ platform_data = kmalloc(sizeof(struct tegra_usb_platform_data),
+ GFP_KERNEL);
+ if (!platform_data)
+ goto error;
+
+ memcpy(platform_data, &tegra_ehci1_utmi_pdata,
+ sizeof(struct tegra_usb_platform_data));
+ pdev->dev.platform_data = platform_data;
+
+ val = platform_device_add(pdev);
+ if (val)
+ goto error_add;
+
+ return pdev;
+
+error_add:
+ kfree(platform_data);
+error:
+ pr_err("%s: failed to add the host controller device\n", __func__);
+ platform_device_put(pdev);
+ return NULL;
+}
+
+static void tegra_usb_otg_host_unregister(struct platform_device *pdev)
+{
+ kfree(pdev->dev.platform_data);
+ pdev->dev.platform_data = NULL;
+ platform_device_unregister(pdev);
+}
+
+static struct colibri_otg_platform_data colibri_otg_pdata = {
+ .cable_detect_gpio = USBC_DET,
+ .host_register = &tegra_usb_otg_host_register,
+ .host_unregister = &tegra_usb_otg_host_unregister,
+};
+#else /* !CONFIG_USB_TEGRA_OTG */
+static struct tegra_usb_otg_data tegra_otg_pdata = {
+ .ehci_device = &tegra_ehci1_device,
+ .ehci_pdata = &tegra_ehci1_utmi_pdata,
+};
+#endif /* !CONFIG_USB_TEGRA_OTG */
+
+#ifndef CONFIG_USB_TEGRA_OTG
+struct platform_device colibri_otg_device = {
+ .name = "colibri-otg",
+ .id = -1,
+ .dev = {
+ .platform_data = &colibri_otg_pdata,
+ },
+};
+#endif /* !CONFIG_USB_TEGRA_OTG */
+
+static void colibri_t30_usb_init(void)
+{
+ gpio_request(LAN_V_BUS, "LAN_V_BUS");
+ gpio_direction_output(LAN_V_BUS, 0);
+ gpio_export(LAN_V_BUS, false);
+
+ gpio_request(LAN_RESET, "LAN_RESET");
+ gpio_direction_output(LAN_RESET, 0);
+ gpio_export(LAN_RESET, false);
+
+ /* OTG should be the first to be registered
+ EHCI instance 0: USB1_DP/N -> USBOTG_P/N */
+#ifndef CONFIG_USB_TEGRA_OTG
+ platform_device_register(&colibri_otg_device);
+#else /* !CONFIG_USB_TEGRA_OTG */
+ tegra_otg_device.dev.platform_data = &tegra_otg_pdata;
+ platform_device_register(&tegra_otg_device);
+#endif /* !CONFIG_USB_TEGRA_OTG */
+
+ /* setup the udc platform data */
+ tegra_udc_device.dev.platform_data = &tegra_udc_pdata;
+ platform_device_register(&tegra_udc_device);
+
+ /* EHCI instance 1: ASIX ETH */
+ tegra_ehci2_device.dev.platform_data = &tegra_ehci2_utmi_pdata;
+ platform_device_register(&tegra_ehci2_device);
+
+ /* EHCI instance 2: USB3_DP/N -> USBH1_P/N */
+ tegra_ehci3_device.dev.platform_data = &tegra_ehci3_utmi_pdata;
+ platform_device_register(&tegra_ehci3_device);
+}
+
+/* W1, aka OWR, aka OneWire */
+
+#ifdef CONFIG_W1_MASTER_TEGRA
+struct tegra_w1_timings colibri_t30_w1_timings = {
+ .tsu = 1,
+ .trelease = 0xf,
+ .trdv = 0xf,
+ .tlow0 = 0x3c,
+ .tlow1 = 1,
+ .tslot = 0x77,
+
+ .tpdl = 0x78,
+ .tpdh = 0x1e,
+ .trstl = 0x1df,
+ .trsth = 0x1df,
+ .rdsclk = 0x7,
+ .psclk = 0x50,
+};
+
+struct tegra_w1_platform_data colibri_t30_w1_platform_data = {
+ .clk_id = "tegra_w1",
+ .timings = &colibri_t30_w1_timings,
+};
+#endif /* CONFIG_W1_MASTER_TEGRA */
+
+static struct platform_device *colibri_t30_devices[] __initdata = {
+ &tegra_pmu_device,
+#if defined(CONFIG_RTC_DRV_TEGRA)
+ &tegra_rtc_device,
+#endif
+#if defined(CONFIG_TEGRA_IOVMM_SMMU) || defined(CONFIG_TEGRA_IOMMU_SMMU)
+ &tegra_smmu_device,
+#endif
+ &tegra_wdt0_device,
+ &tegra_wdt1_device,
+ &tegra_wdt2_device,
+#if defined(CONFIG_TEGRA_AVP)
+ &tegra_avp_device,
+#endif
+#ifdef CONFIG_TEGRA_CAMERA
+ &tegra_camera,
+#endif
+#if defined(CONFIG_CRYPTO_DEV_TEGRA_SE)
+ &tegra_se_device,
+#endif
+#if defined(CONFIG_CRYPTO_DEV_TEGRA_AES)
+ &tegra_aes_device,
+#endif
+
+ &tegra_ahub_device,
+ &tegra_dam_device0,
+ &tegra_dam_device1,
+ &tegra_dam_device2,
+ &tegra_i2s_device2,
+ &tegra_spdif_device,
+ &spdif_dit_device,
+ &tegra_pcm_device,
+ &colibri_t30_audio_sgtl5000_device,
+
+ &tegra_cec_device,
+#if defined(CONFIG_CRYPTO_DEV_TEGRA_AES)
+ &tegra_aes_device,
+#endif
+#ifdef CONFIG_KEYBOARD_GPIO
+ &colibri_t30_keys_device,
+#endif
+ &tegra_led_pwm_device,
+ &tegra_pwfm1_device,
+ &tegra_pwfm2_device,
+ &tegra_pwfm3_device,
+#ifdef CONFIG_W1_MASTER_TEGRA
+ &tegra_w1_device,
+#endif
+};
+
+static void __init colibri_t30_init(void)
+{
+ tegra_thermal_init(&thermal_data,
+ throttle_list,
+ ARRAY_SIZE(throttle_list));
+ tegra_clk_init_from_table(colibri_t30_clk_init_table);
+ colibri_t30_pinmux_init();
+ colibri_t30_thermd_alert_init();
+ colibri_t30_i2c_init();
+ colibri_t30_spi_init();
+ colibri_t30_usb_init();
+#ifdef CONFIG_TEGRA_EDP_LIMITS
+ colibri_t30_edp_init();
+#endif
+ colibri_t30_uart_init();
+#ifdef CONFIG_W1_MASTER_TEGRA
+ tegra_w1_device.dev.platform_data = &colibri_t30_w1_platform_data;
+#endif
+ platform_add_devices(colibri_t30_devices, ARRAY_SIZE(colibri_t30_devices));
+ tegra_ram_console_debug_init();
+ tegra_io_dpd_init();
+ colibri_t30_sdhci_init();
+ colibri_t30_regulator_init();
+ colibri_t30_suspend_init();
+ colibri_t30_panel_init();
+// colibri_t30_sensors_init();
+ colibri_t30_emc_init();
+ colibri_t30_register_spidev();
+
+ tegra_release_bootloader_fb();
+#ifdef CONFIG_TEGRA_WDT_RECOVERY
+ tegra_wdt_recovery_init();
+#endif
+ tegra_serial_debug_init(TEGRA_UARTD_BASE, INT_WDT_CPU, NULL, -1, -1);
+
+ /* Activate Mic Bias */
+ gpio_request(EN_MIC_GND, "EN_MIC_GND");
+ gpio_direction_output(EN_MIC_GND, 1);
+}
+
+static void __init colibri_t30_reserve(void)
+{
+#if defined(CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM)
+ /* Support 1920X1080 32bpp,double buffered on HDMI*/
+ tegra_reserve(0, SZ_8M + SZ_1M, SZ_16M);
+#else
+ tegra_reserve(SZ_128M, SZ_8M, SZ_8M);
+#endif
+ tegra_ram_console_debug_reserve(SZ_1M);
+}
+
+static const char *colibri_t30_dt_board_compat[] = {
+ "toradex,colibri_t30",
+ NULL
+};
+
+MACHINE_START(COLIBRI_T30, "Toradex Colibri T30")
+ .boot_params = 0x80000100,
+ .dt_compat = colibri_t30_dt_board_compat,
+ .init_early = tegra_init_early,
+ .init_irq = tegra_init_irq,
+ .init_machine = colibri_t30_init,
+ .map_io = tegra_map_common_io,
+ .reserve = colibri_t30_reserve,
+ .timer = &tegra_timer,
+MACHINE_END
diff --git a/arch/arm/mach-tegra/board-colibri_t30.h b/arch/arm/mach-tegra/board-colibri_t30.h
new file mode 100644
index 000000000000..4244a007ee72
--- /dev/null
+++ b/arch/arm/mach-tegra/board-colibri_t30.h
@@ -0,0 +1,120 @@
+/*
+ * arch/arm/mach-tegra/board-colibri_t30.h
+ *
+ * Copyright (c) 2012 Toradex, Inc.
+ *
+ * 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 _MACH_TEGRA_BOARD_COLIBRI_T30_H
+#define _MACH_TEGRA_BOARD_COLIBRI_T30_H
+
+#include <linux/mfd/tps6591x.h>
+
+#include <mach/gpio.h>
+#include <mach/irqs.h>
+
+/* Uncomment for camera interface support on Colibri Evaluation carrier
+ board */
+#ifdef CONFIG_TEGRA_CAMERA
+#define COLIBRI_T30_VI
+#endif
+
+/* Run framebuffer in VGA mode */
+#define TEGRA_FB_VGA
+
+/* GPIO */
+
+#define DDC_SCL TEGRA_GPIO_PV4 /* X2-15 */
+#define DDC_SDA TEGRA_GPIO_PV5 /* X2-16 */
+
+#ifdef COLIBRI_T30_V10
+#define EMMC_DETECT TEGRA_GPIO_PC7
+#endif
+
+#define EN_MIC_GND TEGRA_GPIO_PT1
+
+#define FUSION_PEN_DOWN TEGRA_GPIO_PY6 /* SODIMM 103 */
+#define FUSION_RESET TEGRA_GPIO_PY7 /* SODIMM 101 */
+
+#define I2C_SCL TEGRA_GPIO_PC4 /* SODIMM 196 */
+#define I2C_SDA TEGRA_GPIO_PC5 /* SODIMM 194 */
+
+#define LAN_EXT_WAKEUP TEGRA_GPIO_PDD1
+#define LAN_PME TEGRA_GPIO_PDD3
+#define LAN_RESET TEGRA_GPIO_PDD0
+#define LAN_V_BUS TEGRA_GPIO_PDD2
+
+#ifdef COLIBRI_T30_V10
+#define MMC_CD TEGRA_GPIO_PU6 /* SODIMM 43 */
+#else
+#define MMC_CD TEGRA_GPIO_PC7 /* SODIMM 43 */
+#endif
+
+#define PWR_I2C_SCL TEGRA_GPIO_PZ6
+#define PWR_I2C_SDA TEGRA_GPIO_PZ7
+
+#define THERMD_ALERT TEGRA_GPIO_PD2
+
+#define TOUCH_PEN_INT TEGRA_GPIO_PV0
+
+#define USBC_DET TEGRA_GPIO_PK5 /* SODIMM 137 */
+#define USBH_OC TEGRA_GPIO_PW3 /* SODIMM 131 */
+#define USBH_PEN TEGRA_GPIO_PW2 /* SODIMM 129 */
+
+/* Uncomment for Colibri T30 V1.0a prototypes */
+//#define COLIBRI_T30_V10
+
+/* Uncomment for SD-card on SDMMC4B rather than SDMMC2 */
+//#define COLIBRI_T30_SDMMC4B
+
+/* STMPE811 IRQs */
+#define STMPE811_IRQ_BASE TEGRA_NR_IRQS
+#define STMPE811_IRQ_END (STMPE811_IRQ_BASE + 22)
+
+#define TDIODE_OFFSET (10000) /* in millicelsius */
+
+/* External peripheral act as gpio */
+/* TPS6591x GPIOs */
+#define TPS6591X_GPIO_BASE TEGRA_NR_GPIOS
+#define TPS6591X_GPIO_0 (TPS6591X_GPIO_BASE + TPS6591X_GPIO_GP0)
+#define TPS6591X_GPIO_1 (TPS6591X_GPIO_BASE + TPS6591X_GPIO_GP1)
+#define TPS6591X_GPIO_2 (TPS6591X_GPIO_BASE + TPS6591X_GPIO_GP2)
+#define TPS6591X_GPIO_3 (TPS6591X_GPIO_BASE + TPS6591X_GPIO_GP3)
+#define TPS6591X_GPIO_4 (TPS6591X_GPIO_BASE + TPS6591X_GPIO_GP4)
+#define TPS6591X_GPIO_5 (TPS6591X_GPIO_BASE + TPS6591X_GPIO_GP5)
+#define TPS6591X_GPIO_6 (TPS6591X_GPIO_BASE + TPS6591X_GPIO_GP6)
+#define TPS6591X_GPIO_7 (TPS6591X_GPIO_BASE + TPS6591X_GPIO_GP7)
+#define TPS6591X_GPIO_8 (TPS6591X_GPIO_BASE + TPS6591X_GPIO_GP8)
+#define TPS6591X_GPIO_END (TPS6591X_GPIO_BASE + TPS6591X_GPIO_NR)
+
+/*****************Interrupt tables ******************/
+/* External peripheral act as interrupt controller */
+/* TPS6591x IRQs */
+#define TPS6591X_IRQ_BASE STMPE811_IRQ_END
+#define TPS6591X_IRQ_END (TPS6591X_IRQ_BASE + 18)
+
+int colibri_t30_regulator_init(void);
+int colibri_t30_suspend_init(void);
+int colibri_t30_pinmux_init(void);
+int colibri_t30_panel_init(void);
+int colibri_t30_sensors_init(void);
+int colibri_t30_gpio_switch_regulator_init(void);
+int colibri_t30_pins_state_init(void);
+int colibri_t30_emc_init(void);
+int colibri_t30_power_off_init(void);
+int colibri_t30_edp_init(void);
+
+#endif
diff --git a/arch/arm/mach-tegra/board-e1853.h b/arch/arm/mach-tegra/board-e1853.h
index 58b8ab8725af..ebd8c1b0b576 100644
--- a/arch/arm/mach-tegra/board-e1853.h
+++ b/arch/arm/mach-tegra/board-e1853.h
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/e1853/board-e1853.h
+ * arch/arm/mach-tegra/board-e1853.h
*
* Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
*
diff --git a/arch/arm/mach-tegra/board-touch-kai-synaptics-spi.c b/arch/arm/mach-tegra/board-touch-kai-synaptics-spi.c
index 718047acf896..5c5cb9b1bae0 100644
--- a/arch/arm/mach-tegra/board-touch-kai-synaptics-spi.c
+++ b/arch/arm/mach-tegra/board-touch-kai-synaptics-spi.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-touch-synaptics-spi.c
+ * arch/arm/mach-tegra/board-touch-kai-synaptics-spi.c
*
* Copyright (C) 2010-2012 NVIDIA Corporation
*
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
index 035a41c99359..703393ba7bd9 100644
--- a/arch/arm/mach-tegra/clock.h
+++ b/arch/arm/mach-tegra/clock.h
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/include/mach/clock.h
+ * arch/arm/mach-tegra/clock.h
*
* Copyright (C) 2010 Google, Inc.
*
@@ -25,7 +25,12 @@
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
#define USE_PLL_LOCK_BITS 0 /* Never use lock bits on Tegra2 */
#else
-#define USE_PLL_LOCK_BITS 1 /* Use lock bits for PLL stabiliation */
+#if defined(CONFIG_MACH_APALIS_T30) || defined(CONFIG_MACH_COLIBRI_T30)
+/* Hack: avoid lock-up during boot-up due to missing pll_a lock bit. */
+#define USE_PLL_LOCK_BITS 0 /* Never use lock bits on Apalis/Colibri T30 */
+#else /* CONFIG_MACH_APALIS_T30 | CONFIG_MACH_COLIBRI_T30 */
+#define USE_PLL_LOCK_BITS 1 /* Use lock bits for PLL stabilisation */
+#endif /* CONFIG_MACH_APALIS_T30 | CONFIG_MACH_COLIBRI_T30 */
#define USE_PLLE_SS 1 /* Use spread spectrum coefficients for PLLE */
#define PLL_POST_LOCK_DELAY 50 /* Safety delay after lock is detected */
#endif
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 0d1407b6b668..d5acd8bdea76 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -172,6 +172,9 @@ static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
{ "pll_p_out4", "pll_p", 108000000, false },
{ "pll_m", "clk_m", 0, true },
{ "pll_m_out1", "pll_m", 120000000, true },
+//[ 0.000000] Failed to set parent pll_c_out1 for sclk (violates clock limit 240000000)
+//[ 0.000000] Unable to set parent pll_c_out1 of clock sclk: -22
+ { "pll_c_out1", "pll_c", 40000000, false },
{ "sclk", "pll_c_out1", 40000000, true },
{ "hclk", "sclk", 40000000, true },
{ "pclk", "hclk", 40000000, true },
@@ -466,6 +469,21 @@ static int __init tegra_lp0_vec_arg(char *options)
}
early_param("lp0_vec", tegra_lp0_vec_arg);
+static int __init tegra_bootloader_fb_arg0(char *options)
+{
+ char *p = options;
+
+ tegra_bootloader_fb_size = memparse(p, &p);
+ if (*p == '@')
+ tegra_bootloader_fb_start = memparse(p+1, &p);
+
+ pr_info("Found fbmem: %08lx@%08lx\n",
+ tegra_bootloader_fb_size, tegra_bootloader_fb_start);
+
+ return 0;
+}
+early_param("fbmem", tegra_bootloader_fb_arg0);
+
static int __init tegra_bootloader_fb_arg(char *options)
{
char *p = options;
@@ -496,6 +514,27 @@ static int __init tegra_bootloader_fb2_arg(char *options)
}
early_param("tegra_fbmem2", tegra_bootloader_fb2_arg);
+/* To specify NVIDIA carveout memory */
+static int __init parse_nvmem(char *p)
+{
+ unsigned long size, start;
+ char *endp;
+
+ size = memparse(p, &endp);
+ if (*endp == '@') {
+ start = memparse(endp + 1, NULL);
+ if (start && size) {
+ pr_info("Found nvmem: %08lx@%08lx\n", size, start);
+ tegra_carveout_start = start;
+ tegra_carveout_size = size;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+early_param("nvmem", parse_nvmem);
+
static int __init tegra_sku_override(char *id)
{
char *p = id;
@@ -892,6 +931,9 @@ void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size,
tegra_carveout_size = 0;
} else
tegra_carveout_size = carveout_size;
+ } else {
+ /* special handling due to already reserved fbmem/nvmem */
+ fb2_size -= tegra_bootloader_fb_size;
}
if (fb2_size) {
@@ -906,6 +948,11 @@ void __init tegra_reserve(unsigned long carveout_size, unsigned long fb_size,
tegra_fb2_size = fb2_size;
}
+ if (!carveout_size) {
+ /* special handling due to already reserved fbmem/nvmem */
+ tegra_fb2_size += tegra_bootloader_fb_size;
+ }
+
if (fb_size) {
tegra_fb_start = memblock_end_of_DRAM() - fb_size;
if (memblock_remove(tegra_fb_start, fb_size)) {
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c
index 508320582560..c3bc1ded475a 100644
--- a/arch/arm/mach-tegra/devices.c
+++ b/arch/arm/mach-tegra/devices.c
@@ -886,6 +886,31 @@ struct platform_device debug_uarte_device = {
#endif
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+static struct resource tegra_ac97_resource[] = {
+ [0] = {
+ .start = INT_AC97,
+ .end = INT_AC97,
+ .flags = IORESOURCE_IRQ
+ },
+ [1] = {
+ .start = TEGRA_DMA_REQ_SEL_AC97,
+ .end = TEGRA_DMA_REQ_SEL_AC97,
+ .flags = IORESOURCE_DMA
+ },
+ [2] = {
+ .start = TEGRA_AC97_BASE,
+ .end = TEGRA_AC97_BASE + TEGRA_AC97_SIZE - 1,
+ .flags = IORESOURCE_MEM
+ }
+};
+
+struct platform_device tegra_ac97_device = {
+ .name = "tegra20-ac97",
+ .id = -1,
+ .resource = tegra_ac97_resource,
+ .num_resources = ARRAY_SIZE(tegra_ac97_resource),
+};
+
static struct resource i2s_resource1[] = {
[0] = {
.start = INT_I2S1,
diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h
index ca492cdd11db..02962b59031f 100644
--- a/arch/arm/mach-tegra/devices.h
+++ b/arch/arm/mach-tegra/devices.h
@@ -75,6 +75,7 @@ extern struct platform_device tegra_udc_device;
extern struct platform_device tegra_ehci1_device;
extern struct platform_device tegra_ehci2_device;
extern struct platform_device tegra_ehci3_device;
+extern struct platform_device tegra_ac97_device;
extern struct platform_device tegra_i2s_device1;
extern struct platform_device tegra_i2s_device2;
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
diff --git a/arch/arm/mach-tegra/gic.h b/arch/arm/mach-tegra/gic.h
index 22bb85f18525..bd5423ea1235 100644
--- a/arch/arm/mach-tegra/gic.h
+++ b/arch/arm/mach-tegra/gic.h
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/include/mach/gic.h
+ * arch/arm/mach-tegra/gic.h
*
* Copyright (C) 2010-2012 NVIDIA Corporation
*
diff --git a/arch/arm/mach-tegra/gpio-names.h b/arch/arm/mach-tegra/gpio-names.h
index cb3c5ce29c0f..b1adddf12388 100644
--- a/arch/arm/mach-tegra/gpio-names.h
+++ b/arch/arm/mach-tegra/gpio-names.h
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/include/mach/gpio-names.h
+ * arch/arm/mach-tegra/gpio-names.h
*
* Copyright (c) 2010 Google, Inc
* Copyright (C) 2011 NVIDIA Corporation.
diff --git a/arch/arm/mach-tegra/include/mach/ac97.h b/arch/arm/mach-tegra/include/mach/ac97.h
new file mode 100644
index 000000000000..a62cb93123a9
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/ac97.h
@@ -0,0 +1,87 @@
+/*
+ * arch/arm/mach-tegra/include/mach/ac97.h
+ *
+ * Copyright (C) 2011 Toradex, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ARCH_ARM_MACH_TEGRA_AC97_H
+#define __ARCH_ARM_MACH_TEGRA_AC97_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+/* Offsets from TEGRA_AC97_BASE */
+#define AC_AC_CTRL_0 0
+#define AC_AC_CMD_0 4
+#define AC_AC_STATUS1_0 8
+/* ... */
+#define AC_AC_FIFO1_SCR_0 0x1c
+#define AC_AC_FIFO2_SCR_0 0x2c
+/* ... */
+#define AC_AC_FIFO_OUT1_0 0x40
+#define AC_AC_FIFO_IN1_0 0x80
+#define AC_AC_FIFO_OUT2_0 0x140
+#define AC_AC_FIFO_IN2_0 0x180
+
+/* AC_AC_CTRL_0 */
+#define AC_AC_CTRL_STM2_EN (1<<16)
+#define AC_AC_CTRL_DOUBLE_SAMPLING_EN (1<<11)
+#define AC_AC_CTRL_IO_CNTRL_EN (1<<10)
+#define AC_AC_CTRL_HSET_DAC_EN (1<<9)
+#define AC_AC_CTRL_LINE2_DAC_EN (1<<8)
+#define AC_AC_CTRL_PCM_LFE_EN (1<<7)
+#define AC_AC_CTRL_PCM_SUR_EN (1<<6)
+#define AC_AC_CTRL_PCM_CEN_DAC_EN (1<<5)
+#define AC_AC_CTRL_LINE1_DAC_EN (1<<4)
+#define AC_AC_CTRL_PCM_DAC_EN (1<<3)
+#define AC_AC_CTRL_COLD_RESET (1<<2)
+#define AC_AC_CTRL_WARM_RESET (1<<1)
+#define AC_AC_CTRL_STM_EN (1<<0)
+
+/* AC_AC_CMD_0 */
+#define AC_AC_CMD_CMD_ADDR_SHIFT (24)
+#define AC_AC_CMD_CMD_ADDR_MASK (0xff<<AC_AC_CMD_CMD_ADDR_SHIFT)
+#define AC_AC_CMD_CMD_DATA_SHIFT (8)
+#define AC_AC_CMD_CMD_DATA_MASK (0xffff<<AC_AC_CMD_CMD_DATA_SHIFT)
+#define AC_AC_CMD_CMD_ID_SHIFT (2)
+#define AC_AC_CMD_CMD_ID_MASK (0x3<<AC_AC_CMD_CMD_ID_SHIFT)
+#define AC_AC_CMD_BUSY (1<<0)
+
+/* AC_AC_STATUS1_0 */
+#define AC_AC_STATUS1_STA_ADDR1_SHIFT (24)
+#define AC_AC_STATUS1_STA_ADDR1_MASK (0xff<<AC_AC_STATUS1_STA_ADDR1_SHIFT)
+#define AC_AC_STATUS1_STA_DATA1_SHIFT (8)
+#define AC_AC_STATUS1_STA_DATA1_MASK (0xffff<<AC_AC_STATUS1_STA_DATA1_SHIFT)
+#define AC_AC_STATUS1_STA_VALID1 (1<<2)
+#define AC_AC_STATUS1_STANDBY1 (1<<1)
+#define AC_AC_STATUS1_CODEC1_RDY (1<<0)
+
+/* AC_AC_FIFO1_SCR_0 and AC_AC_FIFO2_SCR_0 */
+#define AC_AC_FIFOx_SCR_REC_FIFOx_MT_CNT_SHIFT (27)
+#define AC_AC_FIFOx_SCR_REC_FIFOx_MT_CNT_MASK (0x1f << REC_FIFO1_MT_CNT_SHIFT)
+#define AC_AC_FIFOx_SCR_PB_FIFOx_MT_CNT_SHIFT (22)
+#define AC_AC_FIFOx_SCR_PB_FIFOx_MT_CNT_MASK (0x1f << PB_FIFO1_MT_CNT_SHIFT)
+#define AC_AC_FIFOx_SCR_REC_FIFOx_OVERRUN_INT_STA (1<<19)
+#define AC_AC_FIFOx_SCR_PB_FIFOx_UNDERRUN_INT_STA (1<<18)
+#define AC_AC_FIFOx_SCR_RECx_FORCE_MT (1<<17)
+#define AC_AC_FIFOx_SCR_PBx_FORCE_MT (1<<16)
+#define AC_AC_FIFOx_SCR_REC_FIFOx_FULL_EN (1<<15)
+#define AC_AC_FIFOx_SCR_REC_FIFOx_3QRT_FULL_EN (1<<14)
+#define AC_AC_FIFOx_SCR_REC_FIFOx_QRT_FULL_EN (1<<13)
+#define AC_AC_FIFOx_SCR_REC_FIFOx_NOT_MT_EN (1<<12)
+#define AC_AC_FIFOx_SCR_PB_FIFOx_NOT_FULL_EN (1<<11)
+#define AC_AC_FIFOx_SCR_PB_FIFOx_QRT_MT_EN (1<<10)
+#define AC_AC_FIFOx_SCR_PB_FIFOx_3QRT_MT_EN (1<<9)
+#define AC_AC_FIFOx_SCR_PB_FIFOx_MT_EN (1<<8)
+
+#endif /* __ARCH_ARM_MACH_TEGRA_AC97_H */
diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h
index d7aaed0bdcdc..d22a58f22a60 100644
--- a/arch/arm/mach-tegra/include/mach/dc.h
+++ b/arch/arm/mach-tegra/include/mach/dc.h
@@ -544,9 +544,11 @@ void tegra_dc_incr_syncpt_min(struct tegra_dc *dc, int i, u32 val);
*/
int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n);
int tegra_dc_sync_windows(struct tegra_dc_win *windows[], int n);
+#ifndef CONFIG_ANDROID
int tegra_dc_config_frame_end_intr(struct tegra_dc *dc, bool enable);
bool tegra_dc_is_within_n_vsync(struct tegra_dc *dc, s64 ts);
bool tegra_dc_does_vsync_separate(struct tegra_dc *dc, s64 new_ts, s64 old_ts);
+#endif /* !CONFIG_ANDROID */
int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode);
struct fb_videomode;
diff --git a/arch/arm/mach-tegra/include/mach/kfuse.h b/arch/arm/mach-tegra/include/mach/kfuse.h
index cfe85cc86ff2..b9262a3d6d0f 100644
--- a/arch/arm/mach-tegra/include/mach/kfuse.h
+++ b/arch/arm/mach-tegra/include/mach/kfuse.h
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/kfuse.h
+ * arch/arm/mach-tegra/include/mach/kfuse.h
*
* Copyright (C) 2010-2011 NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/include/mach/tegra_usb_modem_power.h b/arch/arm/mach-tegra/include/mach/tegra_usb_modem_power.h
index 210b9f61ecb5..98abc9a35e3e 100644
--- a/arch/arm/mach-tegra/include/mach/tegra_usb_modem_power.h
+++ b/arch/arm/mach-tegra/include/mach/tegra_usb_modem_power.h
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/include/mach/tegra_usb_modem_power.c
+ * arch/arm/mach-tegra/include/mach/tegra_usb_modem_power.h
*
* Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved.
*
diff --git a/arch/arm/mach-tegra/include/mach/tegra_wm8753_pdata.h b/arch/arm/mach-tegra/include/mach/tegra_wm8753_pdata.h
index 944e410b4aec..50e5cc804893 100644
--- a/arch/arm/mach-tegra/include/mach/tegra_wm8753_pdata.h
+++ b/arch/arm/mach-tegra/include/mach/tegra_wm8753_pdata.h
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h
+ * arch/arm/mach-tegra/include/mach/tegra_wm8753_pdata.h
*
* Copyright 2011 NVIDIA, Inc.
*
diff --git a/arch/arm/mach-tegra/include/mach/thermal.h b/arch/arm/mach-tegra/include/mach/thermal.h
index ed71d0340a96..12262685d7cd 100644
--- a/arch/arm/mach-tegra/include/mach/thermal.h
+++ b/arch/arm/mach-tegra/include/mach/thermal.h
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/thermal.h
+ * arch/arm/mach-tegra/include/mach/thermal.h
*
* Copyright (C) 2010-2012 NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-gpio.c b/arch/arm/mach-tegra/p852/board-p852-gpio.c
index 6272d36fb849..c92ca8dd2423 100644
--- a/arch/arm/mach-tegra/p852/board-p852-gpio.c
+++ b/arch/arm/mach-tegra/p852/board-p852-gpio.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-gpio.c
+ * arch/arm/mach-tegra/p852/board-p852-gpio.c
*
* Copyright (C) 2010-2011 NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-i2c.c b/arch/arm/mach-tegra/p852/board-p852-i2c.c
index 041ec252b6c1..0d197e04852f 100644
--- a/arch/arm/mach-tegra/p852/board-p852-i2c.c
+++ b/arch/arm/mach-tegra/p852/board-p852-i2c.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-i2c.c
+ * arch/arm/mach-tegra/p852/board-p852-i2c.c
*
* Copyright (c) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-panel.c b/arch/arm/mach-tegra/p852/board-p852-panel.c
index 8ed62f039dc8..579632081344 100644
--- a/arch/arm/mach-tegra/p852/board-p852-panel.c
+++ b/arch/arm/mach-tegra/p852/board-p852-panel.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-panel.c
+ * arch/arm/mach-tegra/p852/board-p852-panel.c
*
* Copyright (c) 2010-2012, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-pinmux.c b/arch/arm/mach-tegra/p852/board-p852-pinmux.c
index 0ded989f7a13..d00f23d3c32b 100644
--- a/arch/arm/mach-tegra/p852/board-p852-pinmux.c
+++ b/arch/arm/mach-tegra/p852/board-p852-pinmux.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-pinmux.c
+ * arch/arm/mach-tegra/p852/board-p852-pinmux.c
*
* Copyright (c) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-sdhci.c b/arch/arm/mach-tegra/p852/board-p852-sdhci.c
index 54fd42e38ab6..f7ee9355d633 100644
--- a/arch/arm/mach-tegra/p852/board-p852-sdhci.c
+++ b/arch/arm/mach-tegra/p852/board-p852-sdhci.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-sdhci.c
+ * arch/arm/mach-tegra/p852/board-p852-sdhci.c
*
* Copyright (c) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-sku1-b00.c b/arch/arm/mach-tegra/p852/board-p852-sku1-b00.c
index 1cd89c5dfd76..7ab3671d6dd7 100644
--- a/arch/arm/mach-tegra/p852/board-p852-sku1-b00.c
+++ b/arch/arm/mach-tegra/p852/board-p852-sku1-b00.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-sku1-b00.c
+ * arch/arm/mach-tegra/p852/board-p852-sku1-b00.c
*
* Copyright (C) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-sku1-c0x.c b/arch/arm/mach-tegra/p852/board-p852-sku1-c0x.c
index 4a783fb9b635..ddacfa0528f9 100644
--- a/arch/arm/mach-tegra/p852/board-p852-sku1-c0x.c
+++ b/arch/arm/mach-tegra/p852/board-p852-sku1-c0x.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-sku1-c0x.c
+ * arch/arm/mach-tegra/p852/board-p852-sku1-c0x.c
*
* Copyright (C) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-sku1.c b/arch/arm/mach-tegra/p852/board-p852-sku1.c
index 387ba054bd84..09213c1955ae 100644
--- a/arch/arm/mach-tegra/p852/board-p852-sku1.c
+++ b/arch/arm/mach-tegra/p852/board-p852-sku1.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-sku1.c
+ * arch/arm/mach-tegra/p852/board-p852-sku1.c
*
* Copyright (c) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-sku13-b00.c b/arch/arm/mach-tegra/p852/board-p852-sku13-b00.c
index 39e01f660eaf..8bf74e5e98eb 100644
--- a/arch/arm/mach-tegra/p852/board-p852-sku13-b00.c
+++ b/arch/arm/mach-tegra/p852/board-p852-sku13-b00.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-sku13-b00.c
+ * arch/arm/mach-tegra/p852/board-p852-sku13-b00.c
*
* Copyright (c) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-sku13.c b/arch/arm/mach-tegra/p852/board-p852-sku13.c
index 92d917e6e2c1..5009a43aa432 100644
--- a/arch/arm/mach-tegra/p852/board-p852-sku13.c
+++ b/arch/arm/mach-tegra/p852/board-p852-sku13.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-sku13.c
+ * arch/arm/mach-tegra/p852/board-p852-sku13.c
*
* Copyright (c) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-sku23-b00.c b/arch/arm/mach-tegra/p852/board-p852-sku23-b00.c
index 6f464ec3620f..70f0147faffb 100644
--- a/arch/arm/mach-tegra/p852/board-p852-sku23-b00.c
+++ b/arch/arm/mach-tegra/p852/board-p852-sku23-b00.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-sku23-b00.c
+ * arch/arm/mach-tegra/p852/board-p852-sku23-b00.c
*
* Copyright (c) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-sku23-c01.c b/arch/arm/mach-tegra/p852/board-p852-sku23-c01.c
index f946e0ed35ee..b9ed72efc508 100644
--- a/arch/arm/mach-tegra/p852/board-p852-sku23-c01.c
+++ b/arch/arm/mach-tegra/p852/board-p852-sku23-c01.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-sku23-c01.c
+ * arch/arm/mach-tegra/p852/board-p852-sku23-c01.c
*
* Copyright (c) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-sku23.c b/arch/arm/mach-tegra/p852/board-p852-sku23.c
index a2bc9b4ca0b6..d61a28fea12f 100644
--- a/arch/arm/mach-tegra/p852/board-p852-sku23.c
+++ b/arch/arm/mach-tegra/p852/board-p852-sku23.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-sku23.c
+ * arch/arm/mach-tegra/p852/board-p852-sku23.c
*
* Copyright (c) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-sku3.c b/arch/arm/mach-tegra/p852/board-p852-sku3.c
index 380df9a7439a..ee6be1c53f7a 100644
--- a/arch/arm/mach-tegra/p852/board-p852-sku3.c
+++ b/arch/arm/mach-tegra/p852/board-p852-sku3.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-sku3.c
+ * arch/arm/mach-tegra/p852/board-p852-sku3.c
*
* Copyright (c) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-sku5-b00.c b/arch/arm/mach-tegra/p852/board-p852-sku5-b00.c
index 59f6f13f7729..506fab25c968 100644
--- a/arch/arm/mach-tegra/p852/board-p852-sku5-b00.c
+++ b/arch/arm/mach-tegra/p852/board-p852-sku5-b00.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-sku5_b00.c
+ * arch/arm/mach-tegra/p852/board-p852-sku5-b00.c
*
* Copyright (c) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-sku5-c01.c b/arch/arm/mach-tegra/p852/board-p852-sku5-c01.c
index f9c8e72911b6..0dda7a21c94d 100644
--- a/arch/arm/mach-tegra/p852/board-p852-sku5-c01.c
+++ b/arch/arm/mach-tegra/p852/board-p852-sku5-c01.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-sku5-c01.c
+ * arch/arm/mach-tegra/p852/board-p852-sku5-c01.c
*
* Copyright (c) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-sku8-b00.c b/arch/arm/mach-tegra/p852/board-p852-sku8-b00.c
index 4cc4d53d980f..e9a11b427de1 100644
--- a/arch/arm/mach-tegra/p852/board-p852-sku8-b00.c
+++ b/arch/arm/mach-tegra/p852/board-p852-sku8-b00.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-sku8-b00.c
+ * arch/arm/mach-tegra/p852/board-p852-sku8-b00.c
*
* Copyright (C) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-sku8-c01.c b/arch/arm/mach-tegra/p852/board-p852-sku8-c01.c
index 71210cd12b90..f1da518f2eef 100644
--- a/arch/arm/mach-tegra/p852/board-p852-sku8-c01.c
+++ b/arch/arm/mach-tegra/p852/board-p852-sku8-c01.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-sku8-c00.c
+ * arch/arm/mach-tegra/p852/board-p852-sku8-c01.c
*
* Copyright (C) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-sku9-b00.c b/arch/arm/mach-tegra/p852/board-p852-sku9-b00.c
index 7c3d9c3d9a3d..fd2f1cb95716 100644
--- a/arch/arm/mach-tegra/p852/board-p852-sku9-b00.c
+++ b/arch/arm/mach-tegra/p852/board-p852-sku9-b00.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-sku9-b00.c
+ * arch/arm/mach-tegra/p852/board-p852-sku9-b00.c
*
* Copyright (C) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852-sku9-c01.c b/arch/arm/mach-tegra/p852/board-p852-sku9-c01.c
index 94c79294fb47..9add0e83a0d3 100644
--- a/arch/arm/mach-tegra/p852/board-p852-sku9-c01.c
+++ b/arch/arm/mach-tegra/p852/board-p852-sku9-c01.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852-sku9-c00.c
+ * arch/arm/mach-tegra/p852/board-p852-sku9-c01.c
*
* Copyright (C) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852.c b/arch/arm/mach-tegra/p852/board-p852.c
index 0382d7306f42..fba0db4a1a05 100644
--- a/arch/arm/mach-tegra/p852/board-p852.c
+++ b/arch/arm/mach-tegra/p852/board-p852.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852.c
+ * arch/arm/mach-tegra/p852/board-p852.c
*
* Copyright (c) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/p852/board-p852.h b/arch/arm/mach-tegra/p852/board-p852.h
index 8e8f1444029c..58934e6dc1cc 100644
--- a/arch/arm/mach-tegra/p852/board-p852.h
+++ b/arch/arm/mach-tegra/p852/board-p852.h
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/board-p852.h
+ * arch/arm/mach-tegra/p852/board-p852.h
*
* Copyright (c) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
index 04d3a5db3f7e..cf27e2c88a58 100644
--- a/arch/arm/mach-tegra/pcie.c
+++ b/arch/arm/mach-tegra/pcie.c
@@ -36,8 +36,6 @@
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
-#include <linux/workqueue.h>
-#include <linux/gpio.h>
#include <asm/sizes.h>
#include <asm/mach/pci.h>
@@ -50,6 +48,51 @@
#define MSELECT_CONFIG_0_ENABLE_PCIE_APERTURE 5
+#define PINMUX_AUX_PEX_L0_RST_N_0 0x33bc
+#define PINMUX_AUX_PEX_L0_RST_N_0_E_INPUT 5
+#define PINMUX_AUX_PEX_L0_RST_N_0_E_INPUT_ENABLE 1
+
+#define PINMUX_AUX_PEX_L1_RST_N_0 0x33cc
+#define PINMUX_AUX_PEX_L1_RST_N_0_E_INPUT 5
+#define PINMUX_AUX_PEX_L1_RST_N_0_E_INPUT_ENABLE 1
+
+#define PINMUX_AUX_PEX_L2_RST_N_0 0x33d8
+#define PINMUX_AUX_PEX_L2_RST_N_0_E_INPUT 5
+#define PINMUX_AUX_PEX_L2_RST_N_0_E_INPUT_ENABLE 1
+#define AFI_PEX0_CTRL_0_PEX0_CLKREQ_EN 1
+#define NV_PCIE2_PADS_REFCLK_CFG1 0x000000cc
+#define APBDEV_PMC_SCRATCH42_0_PCX_CLAMP_MASK 0x1
+
+
+#define AFI_MSI_VEC0_0 0x6c
+#define AFI_MSI_VEC1_0 0x70
+#define AFI_MSI_VEC2_0 0x74
+#define AFI_MSI_VEC3_0 0x78
+#define AFI_MSI_VEC4_0 0x7c
+#define AFI_MSI_VEC5_0 0x80
+#define AFI_MSI_VEC6_0 0x84
+#define AFI_MSI_VEC7_0 0x88
+
+#define AFI_MSI_EN_VEC0_0 0x8c
+#define AFI_MSI_EN_VEC1_0 0x90
+#define AFI_MSI_EN_VEC2_0 0x94
+#define AFI_MSI_EN_VEC3_0 0x98
+#define AFI_MSI_EN_VEC4_0 0x9c
+#define AFI_MSI_EN_VEC5_0 0xa0
+#define AFI_MSI_EN_VEC6_0 0xa4
+#define AFI_MSI_EN_VEC7_0 0xa8
+
+#define AFI_MSI_FPCI_BAR_ST_0 0x64
+#define AFI_MSI_BAR_SZ_0 0x60
+#define AFI_MSI_AXI_BAR_ST_0 0x68
+#define AFI_INTR_MASK_0 0xb4
+#define AFI_INTR_MASK_0_INT_MASK 0
+#define AFI_INTR_MASK_0_MSI_MASK 8
+
+
+#define AFI_PEXBIAS_CTRL_0 0x168
+
+
/* register definitions */
#define AFI_OFFSET 0x3800
#define PADS_OFFSET 0x3000
@@ -85,27 +128,8 @@
#define AFI_MSI_FPCI_BAR_ST 0x64
#define AFI_MSI_AXI_BAR_ST 0x68
-#define AFI_MSI_VEC0_0 0x6c
-#define AFI_MSI_VEC1_0 0x70
-#define AFI_MSI_VEC2_0 0x74
-#define AFI_MSI_VEC3_0 0x78
-#define AFI_MSI_VEC4_0 0x7c
-#define AFI_MSI_VEC5_0 0x80
-#define AFI_MSI_VEC6_0 0x84
-#define AFI_MSI_VEC7_0 0x88
-
-#define AFI_MSI_EN_VEC0_0 0x8c
-#define AFI_MSI_EN_VEC1_0 0x90
-#define AFI_MSI_EN_VEC2_0 0x94
-#define AFI_MSI_EN_VEC3_0 0x98
-#define AFI_MSI_EN_VEC4_0 0x9c
-#define AFI_MSI_EN_VEC5_0 0xa0
-#define AFI_MSI_EN_VEC6_0 0xa4
-#define AFI_MSI_EN_VEC7_0 0xa8
-
#define AFI_CONFIGURATION 0xac
#define AFI_CONFIGURATION_EN_FPCI (1 << 0)
-#define AFI_CONFIGURATION_DFPCI_RSPPASSPW (1 << 2)
#define AFI_FPCI_ERROR_MASKS 0xb0
@@ -114,19 +138,19 @@
#define AFI_INTR_MASK_MSI_MASK (1 << 8)
#define AFI_INTR_CODE 0xb8
-#define AFI_INTR_CODE_MASK 0xf
-#define AFI_INTR_MASTER_ABORT 4
-#define AFI_INTR_LEGACY 6
+#define AFI_INTR_CODE_MASK 0xf
+#define AFI_INTR_MASTER_ABORT 4
+#define AFI_INTR_LEGACY 6
#define AFI_INTR_SIGNATURE 0xbc
#define AFI_SM_INTR_ENABLE 0xc4
#define AFI_AFI_INTR_ENABLE 0xc8
-#define AFI_INTR_EN_INI_SLVERR (1 << 0)
-#define AFI_INTR_EN_INI_DECERR (1 << 1)
-#define AFI_INTR_EN_TGT_SLVERR (1 << 2)
-#define AFI_INTR_EN_TGT_DECERR (1 << 3)
-#define AFI_INTR_EN_TGT_WRERR (1 << 4)
+#define AFI_INTR_EN_INI_SLVERR (1 << 0)
+#define AFI_INTR_EN_INI_DECERR (1 << 1)
+#define AFI_INTR_EN_TGT_SLVERR (1 << 2)
+#define AFI_INTR_EN_TGT_DECERR (1 << 3)
+#define AFI_INTR_EN_TGT_WRERR (1 << 4)
#define AFI_INTR_EN_DFPCI_DECERR (1 << 5)
#define AFI_INTR_EN_AXI_DECERR (1 << 6)
#define AFI_INTR_EN_FPCI_TIMEOUT (1 << 7)
@@ -148,20 +172,11 @@
#define AFI_PEX1_CTRL 0x118
#define AFI_PEX2_CTRL 0x128
#define AFI_PEX_CTRL_RST (1 << 0)
-#define AFI_PEX_CTRL_CLKREQ_EN (1 << 1)
#define AFI_PEX_CTRL_REFCLK_EN (1 << 3)
-#define AFI_PEXBIAS_CTRL_0 0x168
-
#define RP_VEND_XP 0x00000F00
#define RP_VEND_XP_DL_UP (1 << 30)
-#define RP_TXBA1 0x00000E1C
-#define RP_TXBA1_CM_OVER_PW_BURST_MASK (0xF << 4)
-#define RP_TXBA1_CM_OVER_PW_BURST_INIT_VAL (0x4 << 4)
-#define RP_TXBA1_PW_OVER_CM_BURST_MASK (0xF)
-#define RP_TXBA1_PW_OVER_CM_BURST_INIT_VAL (0x4)
-
#define RP_LINK_CONTROL_STATUS 0x00000090
#define RP_LINK_CONTROL_STATUS_LINKSTAT_MASK 0x3fff0000
@@ -188,19 +203,16 @@
#define PADS_PLL_CTL_TXCLKREF_DIV10 (0 << 20)
#define PADS_PLL_CTL_TXCLKREF_DIV5 (1 << 20)
-#define PADS_REFCLK_CFG1 0x000000CC
-
/* PMC access is required for PCIE xclk (un)clamping */
#define PMC_SCRATCH42 0x144
#define PMC_SCRATCH42_PCX_CLAMP (1 << 0)
+#define NV_PCIE2_RP_TXBA1 0x00000E1C /* RW-4R */
+
#define NV_PCIE2_RP_PRIV_MISC 0x00000FE0
#define PCIE2_RP_PRIV_MISC_CTLR_CLK_CLAMP_ENABLE 1 << 23
#define PCIE2_RP_PRIV_MISC_TMS_CLK_CLAMP_ENABLE 1 << 31
-#define NV_PCIE2_RP_VEND_XP1 0x00000F04
-#define NV_PCIE2_RP_VEND_XP1_LINK_PVT_CTL_L1_ASPM_SUPPORT_ENABLE 1 << 21
-
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
/*
* Tegra2 defines 1GB in the AXI address map for PCIe.
@@ -270,7 +282,7 @@
*/
#define PCIE_IOMAP_SZ (PCIE_REGS_SZ + PCIE_CFG_SZ + PCIE_EXT_CFG_SZ)
-#define MMIO_BASE (TEGRA_PCIE_BASE + PCIE_IOMAP_SZ)
+#define MMIO_BASE (TEGRA_PCIE_BASE + SZ_48M)
#define MMIO_SIZE SZ_1M
#define MEM_BASE_0 (TEGRA_PCIE_BASE + SZ_256M)
#define MEM_SIZE SZ_256M
@@ -284,9 +296,6 @@
#define PCIE_CONF_REG(r) \
(((r) & ~0x3) | (((r) < 256) ? PCIE_CFG_OFF : PCIE_EXT_CFG_OFF))
-#define PCIE_CTRL_REGS 7
-#define COMBINE_PCIE_PCIX_SPACE 2
-
struct tegra_pcie_port {
int index;
u8 root_bus_nr;
@@ -298,7 +307,6 @@ struct tegra_pcie_port {
char mem_space_name[16];
char prefetch_space_name[20];
struct resource res[3];
- struct pci_bus* bus;
};
struct tegra_pcie_info {
@@ -307,10 +315,9 @@ struct tegra_pcie_info {
void __iomem *reg_clk_base;
void __iomem *regs;
- struct resource *res_mmio;
+ struct resource res_mmio;
int power_rails_enabled;
int pcie_power_enabled;
- struct work_struct hotplug_detect;
struct regulator *regulator_hvdd;
struct regulator *regulator_pexio;
@@ -318,13 +325,15 @@ struct tegra_pcie_info {
struct clk *pcie_xclk;
struct clk *pll_e;
struct tegra_pci_platform_data *plat_data;
-}tegra_pcie;
+};
-struct resource tegra_pcie_res_mmio = {
- .name = "PCI IO",
- .start = MMIO_BASE,
- .end = MMIO_BASE + MMIO_SIZE - 1,
- .flags = IORESOURCE_MEM,
+static struct tegra_pcie_info tegra_pcie = {
+ .res_mmio = {
+ .name = "PCI IO",
+ .start = MMIO_BASE,
+ .end = MMIO_BASE + MMIO_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
};
static struct resource pcie_io_space;
@@ -333,11 +342,8 @@ static struct resource pcie_prefetch_mem_space;
/* disable read write while noirq operation
* is performed since pcie is powered off */
static bool is_pcie_noirq_op = false;
-/* enable and init msi once during boot or resume */
-static bool msi_enable;
-/* this flag is used for enumeration by hotplug */
-/* when dock is not connected while system boot */
-static bool is_dock_conn_at_boot = true;
+/* used to backup config space registers of all pcie devices */
+static u32 *pbackup_config_space = NULL;
void __iomem *tegra_pcie_io_base;
EXPORT_SYMBOL(tegra_pcie_io_base);
@@ -529,7 +535,7 @@ static void __devinit tegra_pcie_relax_enable(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable);
-static void tegra_pcie_preinit(void)
+static void __init tegra_pcie_preinit(void)
{
pcie_io_space.name = "PCIe I/O Space";
pcie_io_space.start = PCIBIOS_MIN_IO;
@@ -600,80 +606,6 @@ static struct hw_pci tegra_pcie_hw = {
.map_irq = tegra_pcie_map_irq,
};
-#ifdef CONFIG_PM
-static int tegra_pcie_suspend(struct device *dev);
-static int tegra_pcie_resume(struct device *dev);
-
-/* It enumerates the devices when dock is connected after system boot */
-/* this is similar to pcibios_init_hw in bios32.c */
-static void tegra_pcie_hotplug_init(void)
-{
- struct pci_sys_data *sys = NULL;
- int ret, nr;
-
- if (is_dock_conn_at_boot)
- return;
-
- tegra_pcie_preinit();
- for (nr = 0; nr < tegra_pcie_hw.nr_controllers; nr++) {
- sys = kzalloc(sizeof(struct pci_sys_data), GFP_KERNEL);
- if (!sys)
- panic("PCI: unable to allocate sys data!");
-
-#ifdef CONFIG_PCI_DOMAINS
- sys->domain = tegra_pcie_hw.domain;
-#endif
- sys->hw = &tegra_pcie_hw;
- sys->busnr = nr;
- sys->swizzle = tegra_pcie_hw.swizzle;
- sys->map_irq = tegra_pcie_hw.map_irq;
- sys->resource[0] = &ioport_resource;
- sys->resource[1] = &iomem_resource;
- ret = tegra_pcie_setup(nr, sys);
- if (ret > 0)
- pci_create_bus(NULL, nr, &tegra_pcie_ops, sys);
- }
- is_dock_conn_at_boot = true;
-}
-#endif
-
-static void tegra_pcie_attach(void)
-{
-#ifdef CONFIG_PM
- tegra_pcie_resume(NULL);
-#endif
-}
-
-static void tegra_pcie_detach(void)
-{
-#ifdef CONFIG_PM
- tegra_pcie_suspend(NULL);
-#endif
-}
-
-static void work_hotplug_handler(struct work_struct *work)
-{
- struct tegra_pcie_info *pcie_driver =
- container_of(work, struct tegra_pcie_info, hotplug_detect);
- int val;
-
- if (pcie_driver->plat_data->gpio == -1)
- return;
- val = gpio_get_value(pcie_driver->plat_data->gpio);
- if (val == 0) {
- pr_info("Pcie Dock Connected\n");
- tegra_pcie_attach();
- } else {
- pr_info("Pcie Dock DisConnected\n");
- tegra_pcie_detach();
- }
-}
-
-static irqreturn_t gpio_pcie_detect_isr(int irq, void *arg)
-{
- schedule_work(&tegra_pcie.hotplug_detect);
- return IRQ_HANDLED;
-}
static irqreturn_t tegra_pcie_isr(int irq, void *arg)
{
@@ -789,9 +721,11 @@ static void tegra_pcie_enable_controller(void)
{
u32 val, reg;
int i;
+ void __iomem *reg_apb_misc_base;
void __iomem *reg_mselect_base;
-
+ reg_apb_misc_base = IO_ADDRESS(TEGRA_APB_MISC_BASE);
reg_mselect_base = IO_ADDRESS(TEGRA_MSELECT_BASE);
+
/* select the PCIE APERTURE in MSELECT config */
reg = readl(reg_mselect_base);
reg |= 1 << MSELECT_CONFIG_0_ENABLE_PCIE_APERTURE;
@@ -800,7 +734,8 @@ static void tegra_pcie_enable_controller(void)
/* Enable slot clock and pulse the reset signals */
for (i = 0, reg = AFI_PEX0_CTRL; i < MAX_PCIE_SUPPORTED_PORTS;
i++, reg += (i*8)) {
- val = afi_readl(reg) | AFI_PEX_CTRL_CLKREQ_EN | AFI_PEX_CTRL_REFCLK_EN;
+ val = afi_readl(reg) | AFI_PEX_CTRL_REFCLK_EN |
+ (1 << AFI_PEX0_CTRL_0_PEX0_CLKREQ_EN);
afi_writel(val, reg);
val &= ~AFI_PEX_CTRL_RST;
afi_writel(val, reg);
@@ -810,8 +745,7 @@ static void tegra_pcie_enable_controller(void)
}
afi_writel(0, AFI_PEXBIAS_CTRL_0);
- /* Enable all PCIE controller and */
- /* system management configuration of PCIE crossbar */
+ /* Enable dual controller and both ports */
val = afi_readl(AFI_PCIE_CONFIG);
val &= ~(AFI_PCIE_CONFIG_PCIEC0_DISABLE_DEVICE |
AFI_PCIE_CONFIG_PCIEC1_DISABLE_DEVICE |
@@ -824,7 +758,6 @@ static void tegra_pcie_enable_controller(void)
#endif
afi_writel(val, AFI_PCIE_CONFIG);
- /* Disable Gen 2 capability of PCIE */
val = afi_readl(AFI_FUSE) & ~AFI_FUSE_PCIE_T0_GEN2_DIS;
afi_writel(val, AFI_FUSE);
@@ -837,15 +770,15 @@ static void tegra_pcie_enable_controller(void)
/*
* set up PHY PLL inputs select PLLE output as refclock,
- * set pll TX clock ref to div10 (not div5)
- * set pll ref clock buf to enable.
+ * set TX ref sel to div10 (not div5)
*/
val = pads_readl(PADS_PLL_CTL);
val &= ~(PADS_PLL_CTL_REFCLK_MASK | PADS_PLL_CTL_TXCLKREF_MASK);
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
val |= (PADS_PLL_CTL_REFCLK_INTERNAL_CML | PADS_PLL_CTL_TXCLKREF_DIV10);
#else
- val |= (PADS_PLL_CTL_REFCLK_INTERNAL_CML | PADS_PLL_CTL_TXCLKREF_BUF_EN);
+ val |= (PADS_PLL_CTL_REFCLK_INTERNAL_CML |
+ PADS_PLL_CTL_TXCLKREF_BUF_EN);
#endif
pads_writel(val, PADS_PLL_CTL);
@@ -858,7 +791,7 @@ static void tegra_pcie_enable_controller(void)
* This doesn't exist in the documentation
*/
pads_writel(0xfa5cfa5c, 0xc8);
- pads_writel(0x0000FA5C, PADS_REFCLK_CFG1);
+ pads_writel(0x0000FA5C, NV_PCIE2_PADS_REFCLK_CFG1);
/* Wait for the PLL to lock */
do {
@@ -877,11 +810,13 @@ static void tegra_pcie_enable_controller(void)
/* Take the PCIe interface module out of reset */
tegra_periph_reset_deassert(tegra_pcie.pcie_xclk);
- /* WAR avoid hang on CPU read/write while gpu transfers in progress */
- val = afi_readl(AFI_CONFIGURATION) | AFI_CONFIGURATION_DFPCI_RSPPASSPW;
-
/* Finally enable PCIe */
- val |= AFI_CONFIGURATION_EN_FPCI;
+ val = afi_readl(AFI_CONFIGURATION);
+ val = val | AFI_CONFIGURATION_EN_FPCI;
+
+ /* Enable DFPCI_RSPPASSPW */
+ val |= 4;
+
afi_writel(val, AFI_CONFIGURATION);
val = (AFI_INTR_EN_INI_SLVERR | AFI_INTR_EN_INI_DECERR |
@@ -900,14 +835,10 @@ static void tegra_pcie_enable_controller(void)
return;
}
-static int tegra_pcie_enable_regulators(void)
+static int tegra_pci_enable_regulators(void)
{
- if (tegra_pcie.power_rails_enabled) {
- pr_debug("PCIE: Already power rails enabled");
+ if (tegra_pcie.power_rails_enabled)
return 0;
- }
- tegra_pcie.power_rails_enabled = 1;
-
if (tegra_pcie.regulator_hvdd == NULL) {
printk(KERN_INFO "PCIE.C: %s : regulator hvdd_pex\n",
__func__);
@@ -952,17 +883,16 @@ static int tegra_pcie_enable_regulators(void)
if (tegra_pcie.regulator_avdd_plle)
regulator_enable(tegra_pcie.regulator_avdd_plle);
+ tegra_pcie.power_rails_enabled = 1;
+
return 0;
}
-static int tegra_pcie_disable_regulators(void)
+static int tegra_pci_disable_regulators(void)
{
int err = 0;
-
- if (tegra_pcie.power_rails_enabled == 0) {
- pr_debug("PCIE: Already power rails disabled");
+ if (tegra_pcie.power_rails_enabled == 0)
goto err_exit;
- }
if (tegra_pcie.regulator_hvdd)
err = regulator_disable(tegra_pcie.regulator_hvdd);
if (err)
@@ -978,104 +908,30 @@ err_exit:
return err;
}
-static int tegra_pcie_power_regate(void)
-{
- int err;
- err = tegra_unpowergate_partition_with_clk_on(TEGRA_POWERGATE_PCIE);
- if (err) {
- pr_err("PCIE: powerup sequence failed: %d\n", err);
- return err;
- }
- tegra_periph_reset_assert(tegra_pcie.pcie_xclk);
- return clk_enable(tegra_pcie.pll_e);
-}
-
-static int tegra_pcie_map_resources(void)
-{
- int err;
-
- /* Allocate config space virtual memory */
- tegra_pcie.regs = ioremap_nocache(TEGRA_PCIE_BASE, PCIE_IOMAP_SZ);
- if (tegra_pcie.regs == NULL) {
- pr_err("PCIE: Failed to map PCI/AFI registers\n");
- return -ENOMEM;
- }
-
- err = request_resource(&iomem_resource, &tegra_pcie_res_mmio);
- if (err) {
- pr_err("PCIE: Failed to request resources: %d\n", err);
- return err;
- }
- tegra_pcie.res_mmio = &tegra_pcie_res_mmio;
-
- /* Allocate downstream IO virtual memory */
- tegra_pcie_io_base = ioremap_nocache(tegra_pcie_res_mmio.start,
- resource_size(&tegra_pcie_res_mmio));
- if (tegra_pcie_io_base == NULL) {
- pr_err("PCIE: Failed to map IO\n");
- return -ENOMEM;
- }
- return err;
-}
-
-void tegra_pcie_unmap_resources(void)
-{
- if (tegra_pcie_io_base) {
- iounmap(tegra_pcie_io_base);
- tegra_pcie_io_base = 0;
- }
- if (tegra_pcie.res_mmio) {
- release_resource(tegra_pcie.res_mmio);
- tegra_pcie.res_mmio = 0;
- }
- if (tegra_pcie.regs) {
- iounmap(tegra_pcie.regs);
- tegra_pcie.regs = 0;
- }
-}
-static int tegra_pcie_power_off(void);
-
static int tegra_pcie_power_on(void)
{
int err = 0;
-
- if (tegra_pcie.pcie_power_enabled) {
- pr_debug("PCIE: Already powered on");
- goto err_exit;
- }
- tegra_pcie.pcie_power_enabled = 1;
-
- err = tegra_pcie_enable_regulators();
- if (err) {
- pr_err("PCIE: Failed to enable regulators\n");
- goto err_exit;
- }
- err = tegra_pcie_power_regate();
- if (err) {
- pr_err("PCIE: Failed to power regate\n");
+ if (tegra_pcie.pcie_power_enabled)
+ return 0;
+ err = tegra_pci_enable_regulators();
+ if (err)
goto err_exit;
- }
- err = tegra_pcie_map_resources();
- if (err) {
- pr_err("PCIE: Failed to map resources\n");
+ err = tegra_unpowergate_partition_with_clk_on(TEGRA_POWERGATE_PCIE);
+ if (err)
goto err_exit;
- }
+ if (tegra_pcie.pll_e)
+ clk_enable(tegra_pcie.pll_e);
+ tegra_pcie.pcie_power_enabled = 1;
err_exit:
- if (err)
- tegra_pcie_power_off();
return err;
}
static int tegra_pcie_power_off(void)
{
int err = 0;
-
- if (tegra_pcie.pcie_power_enabled == 0) {
- pr_debug("PCIE: Already powered off");
- goto err_exit;
- }
- tegra_pcie_unmap_resources();
+ if (tegra_pcie.pcie_power_enabled == 0)
+ return 0;
if (tegra_pcie.pll_e)
clk_disable(tegra_pcie.pll_e);
@@ -1083,13 +939,25 @@ static int tegra_pcie_power_off(void)
if (err)
goto err_exit;
- err = tegra_pcie_disable_regulators();
+ err = tegra_pci_disable_regulators();
tegra_pcie.pcie_power_enabled = 0;
err_exit:
return err;
}
+static int tegra_pcie_power_regate(void)
+{
+ int err;
+ err = tegra_unpowergate_partition_with_clk_on(TEGRA_POWERGATE_PCIE);
+ if (err) {
+ pr_err("PCIE: powerup sequence failed: %d\n", err);
+ return err;
+ }
+ tegra_periph_reset_assert(tegra_pcie.pcie_xclk);
+ return clk_enable(tegra_pcie.pll_e);
+}
+
static int tegra_pcie_clocks_get(void)
{
/* reset the PCIEXCLK */
@@ -1114,42 +982,78 @@ error_exit:
static void tegra_pcie_clocks_put(void)
{
- if (tegra_pcie.pll_e)
- clk_put(tegra_pcie.pll_e);
- if (tegra_pcie.pcie_xclk)
- clk_put(tegra_pcie.pcie_xclk);
+ clk_put(tegra_pcie.pll_e);
+ clk_put(tegra_pcie.pcie_xclk);
}
-static int tegra_pcie_get_resources(void)
+static int __init tegra_pcie_get_resources(void)
{
+ struct resource *res_mmio = 0;
int err;
-
tegra_pcie.power_rails_enabled = 0;
- tegra_pcie.pcie_power_enabled = 0;
+ err = tegra_pci_enable_regulators();
+ if (err) {
+ pr_err("PCIE: failed to enable power rails %d\n", err);
+ goto err_pwr_on_rail;
+ }
+ tegra_unpowergate_partition(TEGRA_POWERGATE_PCIE);
err = tegra_pcie_clocks_get();
if (err) {
pr_err("PCIE: failed to get clocks: %d\n", err);
- goto err_clk_get;
+ return err;
}
- err = tegra_pcie_power_on();
+
+ err = tegra_pcie_power_regate();
if (err) {
- pr_err("PCIE: Failed to power on: %d\n", err);
+ pr_err("PCIE: failed to power up: %d\n", err);
goto err_pwr_on;
}
+
+ tegra_pcie.regs = ioremap_nocache(TEGRA_PCIE_BASE, PCIE_IOMAP_SZ);
+ if (tegra_pcie.regs == NULL) {
+ pr_err("PCIE: Failed to map PCI/AFI registers\n");
+ err = -ENOMEM;
+ goto err_map_reg;
+ }
+ res_mmio = &tegra_pcie.res_mmio;
+
+ err = request_resource(&iomem_resource, res_mmio);
+ if (err) {
+ pr_err("PCIE: Failed to request resources: %d\n", err);
+ goto err_req_io;
+ }
+
+ tegra_pcie_io_base = ioremap_nocache(res_mmio->start,
+ resource_size(res_mmio));
+ if (tegra_pcie_io_base == NULL) {
+ pr_err("PCIE: Failed to map IO\n");
+ err = -ENOMEM;
+ goto err_map_io;
+ }
+
err = request_irq(INT_PCIE_INTR, tegra_pcie_isr,
- IRQF_SHARED, "PCIE", &tegra_pcie);
+ IRQF_SHARED, "PCIE", &tegra_pcie);
if (err) {
pr_err("PCIE: Failed to register IRQ: %d\n", err);
- goto err_pwr_on;
+ goto err_irq;
}
set_irq_flags(INT_PCIE_INTR, IRQF_VALID);
+
return 0;
-err_pwr_on:
+err_irq:
+ iounmap(tegra_pcie_io_base);
+err_map_io:
+ release_resource(&tegra_pcie.res_mmio);
+err_req_io:
+ iounmap(tegra_pcie.regs);
+err_map_reg:
tegra_pcie_power_off();
-err_clk_get:
+err_pwr_on:
tegra_pcie_clocks_put();
+err_pwr_on_rail:
+ tegra_pci_disable_regulators();
return err;
}
@@ -1195,42 +1099,19 @@ static bool tegra_pcie_check_link(struct tegra_pcie_port *pp, int idx,
}
retry:
- if (--retries) {
- /* Pulse the PEX reset */
- reg = afi_readl(reset_reg) & ~AFI_PEX_CTRL_RST;
- afi_writel(reg, reset_reg);
- reg = afi_readl(reset_reg) | AFI_PEX_CTRL_RST;
- afi_writel(reg, reset_reg);
- }
+ /* Pulse the PEX reset */
+ reg = afi_readl(reset_reg) & ~AFI_PEX_CTRL_RST;
+ afi_writel(reg, reset_reg);
+ reg = afi_readl(reset_reg) | AFI_PEX_CTRL_RST;
+ afi_writel(reg, reset_reg);
+ retries--;
} while (retries);
return false;
}
-static void tegra_pcie_enable_clock_clamp(int index)
-{
- unsigned int data;
-
- /* Power mangagement settings */
- /* Enable clock clamping by default */
- data = rp_readl(NV_PCIE2_RP_PRIV_MISC, index);
- data |= (PCIE2_RP_PRIV_MISC_CTLR_CLK_CLAMP_ENABLE) |
- (PCIE2_RP_PRIV_MISC_TMS_CLK_CLAMP_ENABLE);
- rp_writel(data, NV_PCIE2_RP_PRIV_MISC, index);
-}
-
-static void tegra_pcie_enable_aspm_l1_support(int index)
-{
- unsigned int data;
-
- /* Enable ASPM - L1 state support by default */
- data = rp_readl(NV_PCIE2_RP_VEND_XP1, index);
- data |= (NV_PCIE2_RP_VEND_XP1_LINK_PVT_CTL_L1_ASPM_SUPPORT_ENABLE);
- rp_writel(data, NV_PCIE2_RP_VEND_XP1, index);
-}
-
-static void tegra_pcie_add_port(int index, u32 offset, u32 reset_reg)
+static void __init tegra_pcie_add_port(int index, u32 offset, u32 reset_reg)
{
struct tegra_pcie_port *pp;
unsigned int data;
@@ -1246,22 +1127,22 @@ static void tegra_pcie_add_port(int index, u32 offset, u32 reset_reg)
printk(KERN_INFO "PCIE: port %d: link down, ignoring\n", index);
return;
}
- tegra_pcie_enable_clock_clamp(index);
- tegra_pcie_enable_aspm_l1_support(index);
+ /* Power mangagement settings */
+ /* Enable clock clamping by default */
+ data = rp_readl(NV_PCIE2_RP_PRIV_MISC, index);
+ data |= (PCIE2_RP_PRIV_MISC_CTLR_CLK_CLAMP_ENABLE) |
+ (PCIE2_RP_PRIV_MISC_TMS_CLK_CLAMP_ENABLE);
+ rp_writel(data, NV_PCIE2_RP_PRIV_MISC, index);
- /*
- * Initialize TXBA1 register to fix the unfair arbitration
- * between downstream reads and completions to upstream reads
- */
- data = rp_readl(RP_TXBA1, index);
- data &= ~(RP_TXBA1_PW_OVER_CM_BURST_MASK);
- data |= RP_TXBA1_PW_OVER_CM_BURST_INIT_VAL;
- data &= ~(RP_TXBA1_CM_OVER_PW_BURST_MASK);
- data |= RP_TXBA1_CM_OVER_PW_BURST_INIT_VAL;
- rp_writel(data, RP_TXBA1, index);
+ /* Initialize TXBA1 register */
+ data = rp_readl(NV_PCIE2_RP_TXBA1, index);
+ data &= 0xffffff00;
+ data |= 0x44;
+ rp_writel(data, NV_PCIE2_RP_TXBA1, index);
tegra_pcie.num_ports++;
pp->index = index;
+ pp->root_bus_nr = -1;
memset(pp->res, 0, sizeof(pp->res));
}
@@ -1279,8 +1160,6 @@ static int tegra_pcie_init(void)
pcibios_min_mem = 0x03000000ul;
pcibios_min_io = 0x10000000ul;
#endif
-
- INIT_WORK(&tegra_pcie.hotplug_detect, work_hotplug_handler);
err = tegra_pcie_get_resources();
if (err)
return err;
@@ -1290,50 +1169,24 @@ static int tegra_pcie_init(void)
tegra_pcie_setup_translations();
for (port = 0; port < MAX_PCIE_SUPPORTED_PORTS; port++) {
ctrl_offset += (port * 8);
- rp_offset = (rp_offset + RP_OFFSET) * port;
+ rp_offset = (rp_offset + 0x1000) * port;
if (tegra_pcie.plat_data->port_status[port])
tegra_pcie_add_port(port, rp_offset, ctrl_offset);
}
- if (tegra_pcie.plat_data->use_dock_detect) {
- unsigned int irq;
-
- pr_info("acquiring dock_detect = %d\n",
- tegra_pcie.plat_data->gpio);
- gpio_request(tegra_pcie.plat_data->gpio, "pcie_dock_detect");
- gpio_direction_input(tegra_pcie.plat_data->gpio);
- irq = gpio_to_irq(tegra_pcie.plat_data->gpio);
- if (irq < 0) {
- pr_err("Unable to get irq number for dock_detect\n");
- goto err_irq;
- }
- err = request_irq(irq,
- gpio_pcie_detect_isr,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- "pcie_dock_detect",
- (void *)tegra_pcie.plat_data);
- if (err < 0) {
- pr_err("Unable to claim irq number for dock_detect\n");
- goto err_irq;
- }
- }
-
+ tegra_pcie.pcie_power_enabled = 1;
if (tegra_pcie.num_ports)
pci_common_init(&tegra_pcie_hw);
- else {
- /* no dock is connected, hotplug will occur after boot */
+ else
err = tegra_pcie_power_off();
- is_dock_conn_at_boot = false;
- }
-
-err_irq:
return err;
}
-static int tegra_pcie_probe(struct platform_device *pdev)
+static int tegra_pci_probe(struct platform_device *pdev)
{
int ret;
+ struct pci_dev *dev = NULL;
tegra_pcie.plat_data = pdev->dev.platform_data;
dev_dbg(&pdev->dev, "PCIE.C: %s : _port_status[0] %d\n",
@@ -1344,137 +1197,125 @@ static int tegra_pcie_probe(struct platform_device *pdev)
__func__, tegra_pcie.plat_data->port_status[2]);
ret = tegra_pcie_init();
+ /* disable async PM of pci devices to ensure right order */
+ /* suspend/resume calls of tegra and bus driver */
+ for_each_pci_dev(dev)
+ device_disable_async_suspend(&dev->dev);
+
return ret;
}
-#ifdef CONFIG_PM
-static int tegra_pcie_suspend(struct device *dev)
+static int tegra_pci_suspend(struct device *dev)
{
struct pci_dev *pdev = NULL;
+ int i, size, ndev = 0;
+
+ for_each_pci_dev(pdev) {
+ /* save state of pcie devices before powering off regulators */
+ pci_save_state(pdev);
+ size = sizeof(pdev->saved_config_space) / sizeof(u32);
+ ndev++;
+ }
+ /* backup config space registers of all devices since it gets reset in
+ save state call from suspend noirq due to disabling of read in it */
+ pbackup_config_space = kzalloc(ndev * size* sizeof(u32), GFP_KERNEL);
+ if (!pbackup_config_space)
+ return -ENODEV;
+ ndev = 0;
for_each_pci_dev(pdev) {
- pci_remove_bus_device(pdev);
- break;
+ for (i = 0;i < size;i++) {
+ memcpy(&pbackup_config_space[i + size*ndev],
+ &pdev->saved_config_space[i], sizeof(u32));
+ }
+ ndev++;
}
/* disable read/write registers before powering off */
is_pcie_noirq_op = true;
- /* reset number of ports since fresh initialization occurs in resume */
- tegra_pcie.num_ports = 0;
return tegra_pcie_power_off();
}
-
-static void tegra_pcie_set_irq(struct pci_bus *bus)
+static int tegra_pci_resume_noirq(struct device *dev)
{
- struct pci_bus *b;
- struct pci_dev *pdev;
-
- list_for_each_entry(pdev, &bus->devices, bus_list) {
- b = pdev->subordinate;
- if (!b) {
- pdev->irq = tegra_pcie_map_irq(pdev,0,0);
- pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, pdev->irq);
- continue;
- }
- tegra_pcie_set_irq(b);
- pdev->irq = tegra_pcie_map_irq(pdev,0,0);
- pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, pdev->irq);
+ struct pci_dev *pdev = NULL;
+
+ for_each_pci_dev(pdev) {
+ /* set this flag to avoid restore state in resume noirq */
+ pdev->state_saved = 0;
}
+ return 0;
}
-static int tegra_pcie_resume(struct device *dev)
+static int tegra_pci_resume(struct device *dev)
{
- int ret = 0;
- struct pci_bus *bus = NULL;
- int port, rp_offset = 0;
- int ctrl_offset = AFI_PEX0_CTRL;
-
- /* return w/o resume if cardhu dock is not connected */
- if (gpio_get_value(tegra_pcie.plat_data->gpio))
- goto exit;
+ int ret;
+ int i, size, ndev = 0;
+ struct pci_dev *pdev = NULL;
ret = tegra_pcie_power_on();
- if (ret) {
- pr_err("PCIE: Failed to power on: %d\n", ret);
- return ret;
- }
- /* enable read/write registers after powering on */
- is_pcie_noirq_op = false;
tegra_pcie_enable_controller();
tegra_pcie_setup_translations();
- msi_enable = false;
-
- for (port = 0; port < MAX_PCIE_SUPPORTED_PORTS; port++) {
- ctrl_offset += (port * 8);
- rp_offset = (rp_offset + 0x1000) * port;
- if (tegra_pcie.plat_data->port_status[port])
- tegra_pcie_add_port(port, rp_offset, ctrl_offset);
- }
- if (!tegra_pcie.num_ports) {
- tegra_pcie_power_off();
- goto exit;
- }
- tegra_pcie_hotplug_init();
- while ((bus = pci_find_next_bus(bus)) != NULL) {
- struct pci_dev *dev;
+ /* enable read/write registers after powering on */
+ is_pcie_noirq_op = false;
- pci_scan_child_bus(bus);
+ for_each_pci_dev(pdev) {
+ /* do fixup here for all dev's since not done in resume noirq */
+ pci_fixup_device(pci_fixup_resume_early, pdev);
- list_for_each_entry(dev, &bus->devices, bus_list)
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
- dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
- if (dev->subordinate)
- pci_bus_size_bridges(dev->subordinate);
+ /* set this flag to force restore state in resume */
+ pdev->state_saved = 1;
- /* set irq for all devices */
- tegra_pcie_set_irq(bus);
- pci_bus_assign_resources(bus);
- pci_enable_bridges(bus);
- pci_bus_add_devices(bus);
+ /* restore config space registers from backup buffer */
+ size = sizeof(pdev->saved_config_space) / sizeof(u32);
+ for (i = 0;i < size;i++) {
+ memcpy(&pdev->saved_config_space[i],
+ &pbackup_config_space[i + size*ndev], sizeof(u32));
+ }
+ ndev++;
}
-exit:
- return 0;
+ kzfree(pbackup_config_space);
+
+ return ret;
}
-#endif
-static int tegra_pcie_remove(struct platform_device *pdev)
+static int tegra_pci_remove(struct platform_device *pdev)
{
return 0;
}
-
#ifdef CONFIG_PM
-static const struct dev_pm_ops tegra_pcie_pm_ops = {
- .suspend = tegra_pcie_suspend,
- .resume = tegra_pcie_resume,
+static const struct dev_pm_ops tegra_pci_pm_ops = {
+ .suspend = tegra_pci_suspend,
+ .resume = tegra_pci_resume,
+ .resume_noirq = tegra_pci_resume_noirq,
};
#endif
-static struct platform_driver tegra_pcie_driver = {
- .probe = tegra_pcie_probe,
- .remove = tegra_pcie_remove,
+static struct platform_driver tegra_pci_driver = {
+ .probe = tegra_pci_probe,
+ .remove = tegra_pci_remove,
.driver = {
.name = "tegra-pcie",
.owner = THIS_MODULE,
#ifdef CONFIG_PM
- .pm = &tegra_pcie_pm_ops,
+ .pm = &tegra_pci_pm_ops,
#endif
},
};
-static int __init tegra_pcie_init_driver(void)
+static int __init tegra_pci_init_driver(void)
{
- return platform_driver_register(&tegra_pcie_driver);
+ return platform_driver_register(&tegra_pci_driver);
}
-static void __exit tegra_pcie_exit_driver(void)
+static void __exit tegra_pci_exit_driver(void)
{
- platform_driver_unregister(&tegra_pcie_driver);
+ platform_driver_unregister(&tegra_pci_driver);
}
-module_init(tegra_pcie_init_driver);
-module_exit(tegra_pcie_exit_driver);
+module_init(tegra_pci_init_driver);
+module_exit(tegra_pci_exit_driver);
static struct irq_chip tegra_irq_chip_msi_pcie = {
.name = "PCIe-MSI",
@@ -1538,7 +1379,7 @@ void msi_map_release(struct msi_map_entry *entry)
}
}
-static irqreturn_t tegra_pcie_msi_isr(int irq, void *arg)
+static irqreturn_t pci_tegra_msi_isr(int irq, void *arg)
{
int i;
int offset;
@@ -1570,28 +1411,31 @@ static irqreturn_t tegra_pcie_msi_isr(int irq, void *arg)
return IRQ_HANDLED;
}
-static bool tegra_pcie_enable_msi(void)
+static bool pci_tegra_enable_msi(void)
{
bool retval = false;
+ static bool already_done;
u32 reg;
u32 msi_base = 0;
u32 msi_aligned = 0;
+ /* enables MSI interrupts. */
/* this only happens once. */
- if (msi_enable) {
+ if (already_done) {
retval = true;
goto exit;
}
+
msi_map_init();
- /* enables MSI interrupts. */
- if (request_irq(INT_PCIE_MSI, tegra_pcie_msi_isr,
+ if (request_irq(INT_PCIE_MSI, pci_tegra_msi_isr,
IRQF_SHARED, "PCIe-MSI",
- tegra_pcie_msi_isr)) {
+ pci_tegra_msi_isr)) {
pr_err("%s: Cannot register IRQ %u\n",
__func__, INT_PCIE_MSI);
goto exit;
}
+
/* setup AFI/FPCI range */
/* FIXME do this better! should be based on PAGE_SIZE */
msi_base = __get_free_pages(GFP_KERNEL, 3);
@@ -1599,14 +1443,14 @@ static bool tegra_pcie_enable_msi(void)
msi_aligned = virt_to_phys((void *)msi_aligned);
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- afi_writel(msi_aligned, AFI_MSI_FPCI_BAR_ST);
+ afi_writel(msi_aligned, AFI_MSI_FPCI_BAR_ST_0);
#else
/* different from T20!*/
- afi_writel(msi_aligned>>8, AFI_MSI_FPCI_BAR_ST);
+ afi_writel(msi_aligned>>8, AFI_MSI_FPCI_BAR_ST_0);
#endif
- afi_writel(msi_aligned, AFI_MSI_AXI_BAR_ST);
+ afi_writel(msi_aligned, AFI_MSI_AXI_BAR_ST_0);
/* this register is in 4K increments */
- afi_writel(1, AFI_MSI_BAR_SZ);
+ afi_writel(1, AFI_MSI_BAR_SZ_0);
/* enable all MSI vectors */
afi_writel(0xffffffff, AFI_MSI_EN_VEC0_0);
@@ -1620,12 +1464,13 @@ static bool tegra_pcie_enable_msi(void)
/* and unmask the MSI interrupt */
reg = 0;
- reg |= (AFI_INTR_MASK_INT_MASK | AFI_INTR_MASK_MSI_MASK);
- afi_writel(reg, AFI_INTR_MASK);
+ reg |= ((1 << AFI_INTR_MASK_0_INT_MASK) |
+ (1 << AFI_INTR_MASK_0_MSI_MASK));
+ afi_writel(reg, AFI_INTR_MASK_0);
set_irq_flags(INT_PCIE_MSI, IRQF_VALID);
- msi_enable = true;
+ already_done = true;
retval = true;
exit:
if (!retval) {
@@ -1643,7 +1488,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
struct msi_msg msg;
struct msi_map_entry *map_entry = NULL;
- if (!tegra_pcie_enable_msi())
+ if (!pci_tegra_enable_msi())
goto exit;
map_entry = msi_map_get();
@@ -1658,7 +1503,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
irq_set_msi_desc(map_entry->irq, desc);
set_irq_flags(map_entry->irq, IRQF_VALID);
- msg.address_lo = afi_readl(AFI_MSI_AXI_BAR_ST);
+ msg.address_lo = afi_readl(AFI_MSI_AXI_BAR_ST_0);
/* 32 bit address only */
msg.address_hi = 0;
msg.data = map_entry->index;
diff --git a/arch/arm/mach-tegra/pm-t3.c b/arch/arm/mach-tegra/pm-t3.c
index 939a9b8ad404..dbc10f229551 100644
--- a/arch/arm/mach-tegra/pm-t3.c
+++ b/arch/arm/mach-tegra/pm-t3.c
@@ -478,9 +478,15 @@ void tegra_lp0_cpu_mode(bool enter)
struct tegra_io_dpd tegra_list_io_dpd[] = {
/* sd dpd bits in dpd2 register */
+#ifndef CONFIG_MACH_APALIS_T30
+/* Hack: fix MMC1 card detection */
IO_DPD_INFO("sdhci-tegra.0", 1, 1), /* SDMMC1 */
+#endif
IO_DPD_INFO("sdhci-tegra.2", 1, 2), /* SDMMC3 */
+#if !defined(CONFIG_MACH_APALIS_T30) && !defined(CONFIG_MACH_COLIBRI_T30)
+/* Hack: fix eMMC detection */
IO_DPD_INFO("sdhci-tegra.3", 1, 3), /* SDMMC4 */
+#endif
};
/* we want to cleanup bootloader io dpd setting in kernel */
diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h
index 401c0aaf061f..284c556d2a93 100644
--- a/arch/arm/mach-tegra/pm.h
+++ b/arch/arm/mach-tegra/pm.h
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/include/mach/pm.h
+ * arch/arm/mach-tegra/pm.h
*
* Copyright (C) 2010 Google, Inc.
* Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved.
diff --git a/arch/arm/mach-tegra/sleep-t2.S b/arch/arm/mach-tegra/sleep-t2.S
index f70360628f34..0b77fd14c7c2 100644
--- a/arch/arm/mach-tegra/sleep-t2.S
+++ b/arch/arm/mach-tegra/sleep-t2.S
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/include/mach/sleep-t2.S
+ * arch/arm/mach-tegra/sleep-t2.S
*
* Copyright (c) 2010-2011, NVIDIA Corporation.
* Copyright (c) 2011, Google, Inc.
diff --git a/arch/arm/mach-tegra/sleep-t3.S b/arch/arm/mach-tegra/sleep-t3.S
index 4ee73d581a08..ae943bde1ce2 100644
--- a/arch/arm/mach-tegra/sleep-t3.S
+++ b/arch/arm/mach-tegra/sleep-t3.S
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/include/mach/sleep-t3.S
+ * arch/arm/mach-tegra/sleep-t3.S
*
* Copyright (c) 2010-2011, NVIDIA Corporation.
*
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index 08359fcc0d31..58d2dcddbfaa 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -65,8 +65,9 @@
#define PERIPH_CLK_SOURCE_NUM \
((PERIPH_CLK_SOURCE_OSC - PERIPH_CLK_SOURCE_I2S1) / 4)
-#define PERIPH_CLK_SOURCE_MASK (3<<30)
-#define PERIPH_CLK_SOURCE_SHIFT 30
+//special handling for pwm clock source, uses 3 bits 30:28 instead of 2 bits 31:30
+#define PERIPH_CLK_SOURCE_MASK ((c->reg) != 0x110 ? (3<<PERIPH_CLK_SOURCE_SHIFT) : (7<<PERIPH_CLK_SOURCE_SHIFT))
+#define PERIPH_CLK_SOURCE_SHIFT ((c->reg) != 0x110 ? 30 : 28)
#define PERIPH_CLK_SOURCE_ENABLE (1<<28)
#define PERIPH_CLK_SOURCE_DIVU71_MASK 0xFF
#define PERIPH_CLK_SOURCE_DIVU16_MASK 0xFFFF
@@ -2103,9 +2104,9 @@ static const struct audio_sources {
{ .name = "spdif_in", .value = 0 },
{ .name = "i2s1", .value = 1 },
{ .name = "i2s2", .value = 2 },
+ { .name = "ac97", .value = 3 },
{ .name = "pll_a_out0", .value = 4 },
#if 0 /* FIXME: not implemented */
- { .name = "ac97", .value = 3 },
{ .name = "ext_audio_clk2", .value = 5 },
{ .name = "ext_audio_clk1", .value = 6 },
{ .name = "ext_vimclk", .value = 7 },
@@ -2428,6 +2429,7 @@ struct clk tegra_list_periph_clks[] = {
PERIPH_CLK("rtc", "rtc-tegra", NULL, 4, 0, 0x31E, 32768, mux_clk_32k, PERIPH_NO_RESET | PERIPH_ON_APB),
PERIPH_CLK("kbc", "tegra-kbc", NULL, 36, 0, 0x31E, 32768, mux_clk_32k, PERIPH_NO_RESET | PERIPH_ON_APB),
PERIPH_CLK("timer", "timer", NULL, 5, 0, 0x31E, 26000000, mux_clk_m, 0),
+ PERIPH_CLK("ac97", "tegra20-ac97", NULL, 3, 0, 0x31E, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
PERIPH_CLK("i2s1", "tegra20-i2s.0", NULL, 11, 0x100, 0x31E, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
PERIPH_CLK("i2s2", "tegra20-i2s.1", NULL, 18, 0x104, 0x31E, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
PERIPH_CLK("fuse", "fuse-tegra", "fuse", 39, 0, 0x31E, 26000000, mux_clk_m, PERIPH_ON_APB),
@@ -2755,7 +2757,7 @@ struct tegra_cpufreq_table_data *tegra_cpufreq_table_get(void)
unsigned long tegra_emc_to_cpu_ratio(unsigned long cpu_rate)
{
/* Vote on memory bus frequency based on cpu frequency */
- if (cpu_rate > 1000000000)
+ if (cpu_rate > 1000000)
return 760000000;
else if (cpu_rate >= 816000)
return 600000000; /* cpu 816 MHz, emc max */
diff --git a/arch/arm/mach-tegra/tegra2_emc.c b/arch/arm/mach-tegra/tegra2_emc.c
index f1ac82ad5c15..4986fffcfed7 100644
--- a/arch/arm/mach-tegra/tegra2_emc.c
+++ b/arch/arm/mach-tegra/tegra2_emc.c
@@ -54,6 +54,7 @@ static inline u32 emc_readl(unsigned long addr)
return readl(emc + addr);
}
+#ifndef CONFIG_MACH_COLIBRI_T20
/* read LPDDR2 memory modes */
static int tegra_emc_read_mrr(unsigned long addr)
{
@@ -82,6 +83,7 @@ static int tegra_emc_read_mrr(unsigned long addr)
return value;
}
+#endif /* !CONFIG_MACH_COLIBRI_T20 */
static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
0x2c, /* RC */
@@ -219,18 +221,25 @@ int tegra_emc_set_rate(unsigned long rate)
void tegra_init_emc(const struct tegra_emc_chip *chips, int chips_size)
{
int i;
+#ifndef CONFIG_MACH_COLIBRI_T20
int vid;
int rev_id1;
int rev_id2;
int pid;
+#endif /* !CONFIG_MACH_COLIBRI_T20 */
int chip_matched = -1;
+#ifndef CONFIG_MACH_COLIBRI_T20
+//somehow this only seems to work for LPDDR2 but we have regular DDR2
vid = tegra_emc_read_mrr(5);
rev_id1 = tegra_emc_read_mrr(6);
rev_id2 = tegra_emc_read_mrr(7);
pid = tegra_emc_read_mrr(8);
+#endif /* !CONFIG_MACH_COLIBRI_T20 */
for (i = 0; i < chips_size; i++) {
+#ifndef CONFIG_MACH_COLIBRI_T20
+//for now just go with the one and only chip table
if (chips[i].mem_manufacturer_id >= 0) {
if (chips[i].mem_manufacturer_id != vid)
continue;
@@ -247,6 +256,7 @@ void tegra_init_emc(const struct tegra_emc_chip *chips, int chips_size)
if (chips[i].mem_pid != pid)
continue;
}
+#endif /* !CONFIG_MACH_COLIBRI_T20 */
chip_matched = i;
break;
@@ -264,9 +274,11 @@ void tegra_init_emc(const struct tegra_emc_chip *chips, int chips_size)
} else {
pr_err("%s: Memory not recognized, memory scaling disabled\n",
__func__);
+#ifndef CONFIG_MACH_COLIBRI_T20
pr_info("%s: Memory vid = 0x%04x", __func__, vid);
pr_info("%s: Memory rev_id1 = 0x%04x", __func__, rev_id1);
pr_info("%s: Memory rev_id2 = 0x%04x", __func__, rev_id2);
pr_info("%s: Memory pid = 0x%04x", __func__, pid);
+#endif /* !CONFIG_MACH_COLIBRI_T20 */
}
}
diff --git a/arch/arm/mach-tegra/tegra2_mc.h b/arch/arm/mach-tegra/tegra2_mc.h
index 211213c5f585..9ff27cbca3f1 100644
--- a/arch/arm/mach-tegra/tegra2_mc.h
+++ b/arch/arm/mach-tegra/tegra2_mc.h
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/tegra2_mc.c
+ * arch/arm/mach-tegra/tegra2_mc.h
*
* Memory controller bandwidth profiling interface
*
diff --git a/arch/arm/mach-tegra/tegra2_usb_phy.c b/arch/arm/mach-tegra/tegra2_usb_phy.c
index 0292ebb75083..121a84b2bcb0 100644
--- a/arch/arm/mach-tegra/tegra2_usb_phy.c
+++ b/arch/arm/mach-tegra/tegra2_usb_phy.c
@@ -629,6 +629,8 @@ static int utmi_phy_irq(struct tegra_usb_phy *phy)
} else if (!phy->phy_clk_on) {
return IRQ_NONE;
}
+ } else if (!phy->phy_clk_on) {
+ return IRQ_NONE;
}
return IRQ_HANDLED;
diff --git a/arch/arm/mach-tegra/tegra3_clocks.c b/arch/arm/mach-tegra/tegra3_clocks.c
index 0bc60869a3d0..fafa5a22157a 100644
--- a/arch/arm/mach-tegra/tegra3_clocks.c
+++ b/arch/arm/mach-tegra/tegra3_clocks.c
@@ -844,12 +844,15 @@ static int tegra3_cpu_clk_set_rate(struct clk *c, unsigned long rate)
if (c->dvfs) {
if (!c->dvfs->dvfs_rail)
return -ENOSYS;
+#if !defined(CONFIG_MACH_APALIS_T30) && !defined(CONFIG_MACH_COLIBRI_T30)
+/* Hack: avoid extensive warnings being logged during boot-up. */
else if ((!c->dvfs->dvfs_rail->reg) &&
(clk_get_rate_locked(c) < rate)) {
WARN(1, "Increasing CPU rate while regulator is not"
" ready may overclock CPU\n");
return -ENOSYS;
}
+#endif /* !CONFIG_MACH_APALIS_T30 & !CONFIG_MACH_COLIBRI_T30 */
}
/*
diff --git a/arch/arm/mach-tegra/tegra_fiq_debugger.c b/arch/arm/mach-tegra/tegra_fiq_debugger.c
index 2a19a214acb5..d164d6b1d949 100644
--- a/arch/arm/mach-tegra/tegra_fiq_debugger.c
+++ b/arch/arm/mach-tegra/tegra_fiq_debugger.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/fiq_debugger.c
+ * arch/arm/mach-tegra/tegra_fiq_debugger.c
*
* Serial Debugger Interface for Tegra
*
diff --git a/arch/arm/mach-tegra/tegra_usb_phy.h b/arch/arm/mach-tegra/tegra_usb_phy.h
index 05aa88296619..ff3b979fe814 100644
--- a/arch/arm/mach-tegra/tegra_usb_phy.h
+++ b/arch/arm/mach-tegra/tegra_usb_phy.h
@@ -1,5 +1,5 @@
/*
- * arch/arm/mach-tegra/include/mach/tegra_usb_phy.h
+ * arch/arm/mach-tegra/tegra_usb_phy.h
*
* Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
*
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c
index 2a7364c12753..b5d3dc575e0c 100644
--- a/arch/arm/mach-tegra/usb_phy.c
+++ b/arch/arm/mach-tegra/usb_phy.c
@@ -79,6 +79,7 @@ static void print_usb_plat_data_info(struct tegra_usb_phy *phy)
? "enabled" : "disabled");
} else {
pr_info("vbus_gpio: %d\n", pdata->u_data.host.vbus_gpio);
+ pr_info("vbus_gpio_inverted: %d\n", pdata->u_data.host.vbus_gpio_inverted);
pr_info("vbus_reg: %s\n", pdata->u_data.host.vbus_reg ?
pdata->u_data.host.vbus_reg : "NULL");
pr_info("hot_plug: %s\n", pdata->u_data.host.hot_plug ?
@@ -99,7 +100,7 @@ static void usb_host_vbus_enable(struct tegra_usb_phy *phy, bool enable)
int gpio = phy->pdata->u_data.host.vbus_gpio;
if (gpio == -1)
return;
- gpio_set_value_cansleep(gpio, enable ? 1 : 0);
+ gpio_set_value_cansleep(gpio, (enable != phy->pdata->u_data.host.vbus_gpio_inverted)? 1 : 0);
}
}
@@ -326,7 +327,7 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct platform_device *pdev)
req failed\n", phy->inst);
goto fail_init;
}
- if (gpio_direction_output(gpio, 1) < 0) {
+ if (gpio_direction_output(gpio, !phy->pdata->u_data.host.vbus_gpio_inverted) < 0) {
ERR("inst:[%d] host vbus gpio \
dir failed\n", phy->inst);
goto fail_init;
@@ -369,7 +370,7 @@ fail_init:
else {
int gpio = phy->pdata->u_data.host.vbus_gpio;
if (gpio != -1) {
- gpio_set_value_cansleep(gpio, 0);
+ gpio_set_value_cansleep(gpio, phy->pdata->u_data.host.vbus_gpio_inverted);
gpio_free(gpio);
}
}
@@ -386,6 +387,7 @@ fail_nomem:
fail_inval:
return ERR_PTR(err);
}
+EXPORT_SYMBOL_GPL(tegra_usb_phy_open);
void tegra_usb_phy_close(struct tegra_usb_phy *phy)
{
@@ -410,7 +412,7 @@ void tegra_usb_phy_close(struct tegra_usb_phy *phy)
else {
int gpio = phy->pdata->u_data.host.vbus_gpio;
if (gpio != -1) {
- gpio_set_value_cansleep(gpio, 0);
+ gpio_set_value_cansleep(gpio, phy->pdata->u_data.host.vbus_gpio_inverted);
gpio_free(gpio);
}
}
@@ -427,6 +429,7 @@ void tegra_usb_phy_close(struct tegra_usb_phy *phy)
devm_kfree(&phy->pdev->dev, phy->pdata);
devm_kfree(&phy->pdev->dev, phy);
}
+EXPORT_SYMBOL_GPL(tegra_usb_phy_close);
irqreturn_t tegra_usb_phy_irq(struct tegra_usb_phy *phy)
{
@@ -452,6 +455,7 @@ int tegra_usb_phy_init(struct tegra_usb_phy *phy)
return status;
}
+EXPORT_SYMBOL_GPL(tegra_usb_phy_init);
int tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
{
@@ -502,6 +506,7 @@ int tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
return err;
}
+EXPORT_SYMBOL_GPL(tegra_usb_phy_power_off);
int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
{
@@ -546,6 +551,7 @@ int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
return status;
}
+EXPORT_SYMBOL_GPL(tegra_usb_phy_power_on);
int tegra_usb_phy_reset(struct tegra_usb_phy *phy)
{
@@ -685,6 +691,7 @@ bool tegra_usb_phy_charger_detected(struct tegra_usb_phy *phy)
return status;
}
+EXPORT_SYMBOL_GPL(tegra_usb_phy_charger_detected);
bool tegra_usb_phy_hw_accessible(struct tegra_usb_phy *phy)
{
@@ -704,11 +711,13 @@ bool tegra_usb_phy_has_hostpc(struct tegra_usb_phy *phy)
{
return phy->pdata->has_hostpc;
}
+EXPORT_SYMBOL_GPL(tegra_usb_phy_has_hostpc);
bool tegra_usb_phy_otg_supported(struct tegra_usb_phy *phy)
{
return phy->pdata->port_otg;
}
+EXPORT_SYMBOL_GPL(tegra_usb_phy_otg_supported);
void tegra_usb_phy_memory_prefetch_on(struct tegra_usb_phy *phy)
{
@@ -724,6 +733,7 @@ void tegra_usb_phy_memory_prefetch_on(struct tegra_usb_phy *phy)
writel(val, ahb_gizmo + AHB_MEM_PREFETCH_CFG2);
}
}
+EXPORT_SYMBOL_GPL(tegra_usb_phy_memory_prefetch_on);
void tegra_usb_phy_memory_prefetch_off(struct tegra_usb_phy *phy)
{
@@ -739,3 +749,4 @@ void tegra_usb_phy_memory_prefetch_off(struct tegra_usb_phy *phy)
writel(val, ahb_gizmo + AHB_MEM_PREFETCH_CFG2);
}
}
+EXPORT_SYMBOL_GPL(tegra_usb_phy_memory_prefetch_off);
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 3b5ea68acbb8..aa33949fef60 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -20,6 +20,7 @@
#include <linux/highmem.h>
#include <linux/perf_event.h>
+#include <asm/exception.h>
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
diff --git a/arch/arm/mm/pageattr.c b/arch/arm/mm/pageattr.c
index c11064517f56..f5519a93147d 100644
--- a/arch/arm/mm/pageattr.c
+++ b/arch/arm/mm/pageattr.c
@@ -35,7 +35,9 @@ extern void __flush_dcache_page(struct address_space *, struct page *);
static void inner_flush_cache_all(void)
{
+#ifdef CONFIG_CPU_CACHE_V7
on_each_cpu(v7_flush_kern_cache_all, NULL, 1);
+#endif
}
#if defined(CONFIG_CPA)
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 978683edfead..3f55d34e3f39 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -946,7 +946,7 @@ shenzhou MACH_SHENZHOU SHENZHOU 3319
cwme9210 MACH_CWME9210 CWME9210 3320
cwme9210js MACH_CWME9210JS CWME9210JS 3321
pgs_v1 MACH_PGS_SITARA PGS_SITARA 3322
-colibri_tegra2 MACH_COLIBRI_TEGRA2 COLIBRI_TEGRA2 3323
+colibri_t20 MACH_COLIBRI_T20 COLIBRI_T20 3323
w21 MACH_W21 W21 3324
polysat1 MACH_POLYSAT1 POLYSAT1 3325
dataway MACH_DATAWAY DATAWAY 3326
@@ -1119,3 +1119,5 @@ kai MACH_KAI KAI 3897
p852 MACH_P852 P852 3667
e1853 MACH_E1853 E1853 4241
tai MACH_TAI TAI 4311
+colibri_t30 MACH_COLIBRI_T30 COLIBRI_T30 4493
+apalis_t30 MACH_APALIS_T30 APALIS_T30 4513
diff --git a/drivers/hwmon/lm95245.c b/drivers/hwmon/lm95245.c
index dce9e68241e6..cea5048b1ba7 100644
--- a/drivers/hwmon/lm95245.c
+++ b/drivers/hwmon/lm95245.c
@@ -34,6 +34,8 @@
#include <linux/mutex.h>
#include <linux/sysfs.h>
+#include <linux/lm95245.h>
+
#define DEVNAME "lm95245"
static const unsigned short normal_i2c[] = {
@@ -93,6 +95,7 @@ static const unsigned short normal_i2c[] = {
#define RATE_CR1000 0x02
#define RATE_CR2500 0x03
+#define STATUS1_ROS 0x10
#define STATUS1_DIODE_FAULT 0x04
#define STATUS1_RTCRIT 0x02
#define STATUS1_LOC 0x01
@@ -107,12 +110,32 @@ static const u8 lm95245_reg_address[] = {
LM95245_REG_R_REMOTE_TEMPL_S,
LM95245_REG_R_REMOTE_TEMPH_U,
LM95245_REG_R_REMOTE_TEMPL_U,
+ LM95245_REG_RW_REMOTE_OS_LIMIT,
LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT,
LM95245_REG_RW_REMOTE_TCRIT_LIMIT,
LM95245_REG_RW_COMMON_HYSTERESIS,
LM95245_REG_R_STATUS1,
};
+/* Indices and offsets into above register array */
+
+enum {
+ INDEX_LOCAL_TEMP = 0,
+ INDEX_REMOTE_TEMP = 2,
+ INDEX_REMOTE_OS_LIMIT = 6,
+ INDEX_LOCAL_OS_TCRIT_LIMIT,
+ INDEX_REMOTE_TCRIT_LIMIT,
+ INDEX_COMMON_HYSTERESIS,
+ INDEX_STATUS1,
+};
+
+enum {
+ OFFSET_HIGH_SIGNED = 0,
+ OFFSET_LOW_SIGNED,
+ OFFSET_HIGH_UNSIGNED,
+ OFFSET_LOW_UNSIGNED,
+};
+
/* Client data (each client gets its own) */
struct lm95245_data {
struct device *hwmon_dev;
@@ -214,24 +237,42 @@ static unsigned long lm95245_set_conversion_rate(struct i2c_client *client,
}
/* Sysfs stuff */
-static ssize_t show_input(struct device *dev, struct device_attribute *attr,
- char *buf)
+void thermal_get_temp(struct device *dev, int *temp, int index)
{
struct lm95245_data *data = lm95245_update_device(dev);
- int temp;
- int index = to_sensor_dev_attr(attr)->index;
/*
- * Index 0 (Local temp) is always signed
- * Index 2 (Remote temp) has both signed and unsigned data
+ * Local temp is always signed
+ * Remote temp has both signed and unsigned data
* use signed calculation for remote if signed bit is set
*/
- if (index == 0 || data->regs[index] & 0x80)
- temp = temp_from_reg_signed(data->regs[index],
- data->regs[index + 1]);
+ if (index == INDEX_LOCAL_TEMP || data->regs[index + OFFSET_HIGH_SIGNED] & 0x80)
+ *temp = temp_from_reg_signed(data->regs[index + OFFSET_HIGH_SIGNED],
+ data->regs[index + OFFSET_LOW_SIGNED]);
else
- temp = temp_from_reg_unsigned(data->regs[index + 2],
- data->regs[index + 3]);
+ *temp = temp_from_reg_unsigned(data->regs[index + OFFSET_HIGH_UNSIGNED],
+ data->regs[index + OFFSET_LOW_UNSIGNED]);
+}
+
+void lm95245_get_local_temp(struct device *dev, int *temp)
+{
+ thermal_get_temp(dev, temp, INDEX_LOCAL_TEMP);
+}
+EXPORT_SYMBOL(lm95245_get_local_temp);
+
+void lm95245_get_remote_temp(struct device *dev, int *temp)
+{
+ thermal_get_temp(dev, temp, INDEX_REMOTE_TEMP);
+}
+EXPORT_SYMBOL(lm95245_get_remote_temp);
+
+static ssize_t show_input(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int temp = 0;
+ int index = to_sensor_dev_attr(attr)->index;
+
+ thermal_get_temp(dev, &temp, index);
return snprintf(buf, PAGE_SIZE - 1, "%d\n", temp);
}
@@ -246,20 +287,14 @@ static ssize_t show_limit(struct device *dev, struct device_attribute *attr,
data->regs[index] * 1000);
}
-static ssize_t set_limit(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+void thermal_set_limit(struct device *dev, int val, int index)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm95245_data *data = i2c_get_clientdata(client);
- int index = to_sensor_dev_attr(attr)->index;
- unsigned long val;
-
- if (strict_strtoul(buf, 10, &val) < 0)
- return -EINVAL;
val /= 1000;
- val = SENSORS_LIMIT(val, 0, (index == 6 ? 127 : 255));
+ val = SENSORS_LIMIT(val, 0, (index == INDEX_LOCAL_OS_TCRIT_LIMIT ? 127 : 255));
mutex_lock(&data->update_lock);
@@ -268,6 +303,30 @@ static ssize_t set_limit(struct device *dev, struct device_attribute *attr,
i2c_smbus_write_byte_data(client, lm95245_reg_address[index], val);
mutex_unlock(&data->update_lock);
+}
+
+void lm95245_set_remote_os_limit(struct device *dev, int val)
+{
+ thermal_set_limit(dev, val, INDEX_REMOTE_OS_LIMIT);
+}
+EXPORT_SYMBOL(lm95245_set_remote_os_limit);
+
+void lm95245_set_remote_critical_limit(struct device *dev, int val)
+{
+ thermal_set_limit(dev, val, INDEX_REMOTE_TCRIT_LIMIT);
+}
+EXPORT_SYMBOL(lm95245_set_remote_critical_limit);
+
+static ssize_t set_limit(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int index = to_sensor_dev_attr(attr)->index;
+ unsigned long val;
+
+ if (strict_strtoul(buf, 10, &val) < 0)
+ return -EINVAL;
+
+ thermal_set_limit(dev, (int)val, index);
return count;
}
@@ -345,7 +404,7 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
int index = to_sensor_dev_attr(attr)->index;
return snprintf(buf, PAGE_SIZE - 1, "%d\n",
- !!(data->regs[9] & index));
+ !!(data->regs[INDEX_STATUS1] & index));
}
static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
@@ -375,19 +434,23 @@ static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
return count;
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_input, NULL, INDEX_LOCAL_TEMP);
static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_limit,
- set_limit, 6);
+ set_limit, INDEX_LOCAL_OS_TCRIT_LIMIT);
static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_limit,
- set_crit_hyst, 8);
+ set_crit_hyst, INDEX_COMMON_HYSTERESIS);
static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL,
STATUS1_LOC);
-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_input, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_input, NULL, INDEX_REMOTE_TEMP);
+static SENSOR_DEVICE_ATTR(temp2_os, S_IWUSR | S_IRUGO, show_limit,
+ set_limit, INDEX_REMOTE_OS_LIMIT);
static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_limit,
- set_limit, 7);
+ set_limit, INDEX_REMOTE_TCRIT_LIMIT);
static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_limit,
- set_crit_hyst, 8);
+ set_crit_hyst, INDEX_COMMON_HYSTERESIS);
+static SENSOR_DEVICE_ATTR(temp2_os_alarm, S_IRUGO, show_alarm, NULL,
+ STATUS1_ROS);
static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL,
STATUS1_RTCRIT);
static SENSOR_DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type,
@@ -404,8 +467,10 @@ static struct attribute *lm95245_attributes[] = {
&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_input.dev_attr.attr,
+ &sensor_dev_attr_temp2_os.dev_attr.attr,
&sensor_dev_attr_temp2_crit.dev_attr.attr,
&sensor_dev_attr_temp2_crit_hyst.dev_attr.attr,
+ &sensor_dev_attr_temp2_os_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_type.dev_attr.attr,
&sensor_dev_attr_temp2_fault.dev_attr.attr,
@@ -454,6 +519,13 @@ static void lm95245_init_client(struct i2c_client *client)
i2c_smbus_write_byte_data(client, LM95245_REG_RW_CONFIG1,
data->config1);
}
+
+ /* Configure over-temperature shutdown (OS) output pin */
+ if (client->dev.platform_data && ((struct lm95245_platform_data*)(client->dev.platform_data))->enable_os_pin) {
+ data->config2 |= CFG2_OS_A0;
+ i2c_smbus_write_byte_data(client, LM95245_REG_RW_CONFIG2,
+ data->config2);
+ }
}
static int lm95245_probe(struct i2c_client *new_client,
@@ -485,6 +557,10 @@ static int lm95245_probe(struct i2c_client *new_client,
goto exit_remove_files;
}
+ /* Notify callback that probe is done */
+ if (new_client->dev.platform_data && ((struct lm95245_platform_data*)(new_client->dev.platform_data))->probe_callback)
+ ((struct lm95245_platform_data*)(new_client->dev.platform_data))->probe_callback(&new_client->dev);
+
return 0;
exit_remove_files:
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index a8fc74f730dd..936f1e71a21f 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -770,4 +770,11 @@ config TOUCHSCREEN_SYN_RMI4_SPI
To compile this driver as a module, choose M here: the
module will be called rmi-spi.
+config TOUCHSCREEN_FUSION_F0710A
+ tristate "TouchRevolution Fusion F0710A Touchscreens"
+ depends on I2C
+ help
+ Say Y here if you want to support the multi-touch input driver for
+ the TouchRevolution Fusion 7 and 10 panels.
+
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 9c42d2100b5c..2fa571b65088 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -64,3 +64,4 @@ obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
obj-$(CONFIG_TOUCHSCREEN_RM31080A) += rm31080a_ts.o
obj-$(CONFIG_TOUCHSCREEN_SYN_RMI4_SPI) += rmi4/
+obj-$(CONFIG_TOUCHSCREEN_FUSION_F0710A) += fusion_F0710A.o
diff --git a/drivers/input/touchscreen/fusion_F0710A.c b/drivers/input/touchscreen/fusion_F0710A.c
new file mode 100644
index 000000000000..ac734abf5368
--- /dev/null
+++ b/drivers/input/touchscreen/fusion_F0710A.c
@@ -0,0 +1,435 @@
+/*
+ * "fusion_F0710A" touchscreen driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <asm/irq.h>
+#include <linux/gpio.h>
+
+#include "fusion_F0710A.h"
+
+#define DRV_NAME "fusion_F0710A"
+
+
+static struct fusion_F0710A_data fusion_F0710A;
+
+static unsigned short normal_i2c[] = { fusion_F0710A_I2C_SLAVE_ADDR, I2C_CLIENT_END };
+
+//I2C_CLIENT_INSMOD;
+
+static int fusion_F0710A_write_u8(u8 addr, u8 data)
+{
+ return i2c_smbus_write_byte_data(fusion_F0710A.client, addr, data);
+}
+
+static int fusion_F0710A_read_u8(u8 addr)
+{
+ return i2c_smbus_read_byte_data(fusion_F0710A.client, addr);
+}
+
+static int fusion_F0710A_read_block(u8 addr, u8 len, u8 *data)
+{
+#if 0
+ /* When i2c_smbus_read_i2c_block_data() takes a block length parameter, we can do
+ * this. lm-sensors lists hints this has been fixed, but I can't tell whether it
+ * was or will be merged upstream. */
+
+ return i2c_smbus_read_i2c_block_data(&fusion_F0710A.client, addr, data);
+#else
+ u8 msgbuf0[1] = { addr };
+ u16 slave = fusion_F0710A.client->addr;
+ u16 flags = fusion_F0710A.client->flags;
+ struct i2c_msg msg[2] = { { slave, flags, 1, msgbuf0 },
+ { slave, flags | I2C_M_RD, len, data }
+ };
+
+ return i2c_transfer(fusion_F0710A.client->adapter, msg, ARRAY_SIZE(msg));
+#endif
+}
+
+
+static int fusion_F0710A_register_input(void)
+{
+ int ret;
+ struct input_dev *dev;
+
+ dev = fusion_F0710A.input = input_allocate_device();
+ if (dev == NULL)
+ return -ENOMEM;
+
+ dev->name = "fusion_F0710A";
+
+ set_bit(EV_KEY, dev->evbit);
+ set_bit(EV_ABS, dev->evbit);
+
+ input_set_abs_params(dev, ABS_MT_POSITION_X, 0, fusion_F0710A.info.xres-1, 0, 0);
+ input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, fusion_F0710A.info.yres-1, 0, 0);
+ input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+ input_set_abs_params(dev, ABS_MT_WIDTH_MAJOR, 0, 15, 0, 0);
+
+ ret = input_register_device(dev);
+ if (ret < 0)
+ goto bail1;
+
+ return 0;
+
+bail1:
+ input_free_device(dev);
+ return ret;
+}
+
+#define WC_RETRY_COUNT 3
+static int fusion_F0710A_write_complete(void)
+{
+ int ret, i;
+
+ for(i=0; i<WC_RETRY_COUNT; i++)
+ {
+ ret = fusion_F0710A_write_u8(fusion_F0710A_SCAN_COMPLETE, 0);
+ if(ret == 0)
+ break;
+ else
+ dev_err(&fusion_F0710A.client->dev, "Write complete failed(%d): %d\n", i, ret);
+ }
+
+ return ret;
+}
+
+#define DATA_START fusion_F0710A_DATA_INFO
+#define DATA_END fusion_F0710A_SEC_TIDTS
+#define DATA_LEN (DATA_END - DATA_START + 1)
+#define DATA_OFF(x) ((x) - DATA_START)
+
+static int fusion_F0710A_read_sensor(void)
+{
+ int ret;
+ u8 data[DATA_LEN];
+
+#define DATA(x) (data[DATA_OFF(x)])
+ /* To ensure data coherency, read the sensor with a single transaction. */
+ ret = fusion_F0710A_read_block(DATA_START, DATA_LEN, data);
+ if (ret < 0) {
+ dev_err(&fusion_F0710A.client->dev,
+ "Read block failed: %d\n", ret);
+ /* Clear fusion_F0710A interrupt */
+ fusion_F0710A_write_complete();
+
+ return ret;
+ }
+
+ fusion_F0710A.f_num = DATA(fusion_F0710A_DATA_INFO)&0x03;
+
+ fusion_F0710A.y1 = DATA(fusion_F0710A_POS_X1_HI) << 8;
+ fusion_F0710A.y1 |= DATA(fusion_F0710A_POS_X1_LO);
+ fusion_F0710A.x1 = DATA(fusion_F0710A_POS_Y1_HI) << 8;
+ fusion_F0710A.x1 |= DATA(fusion_F0710A_POS_Y1_LO);
+ fusion_F0710A.z1 = DATA(fusion_F0710A_FIR_PRESS);
+ fusion_F0710A.tip1 = DATA(fusion_F0710A_FIR_TIDTS)&0x0f;
+ fusion_F0710A.tid1 = (DATA(fusion_F0710A_FIR_TIDTS)&0xf0)>>4;
+
+
+ fusion_F0710A.y2 = DATA(fusion_F0710A_POS_X2_HI) << 8;
+ fusion_F0710A.y2 |= DATA(fusion_F0710A_POS_X2_LO);
+ fusion_F0710A.x2 = DATA(fusion_F0710A_POS_Y2_HI) << 8;
+ fusion_F0710A.x2 |= DATA(fusion_F0710A_POS_Y2_LO);
+ fusion_F0710A.z2 = DATA(fusion_F0710A_SEC_PRESS);
+ fusion_F0710A.tip2 = DATA(fusion_F0710A_SEC_TIDTS)&0x0f;
+ fusion_F0710A.tid2 =(DATA(fusion_F0710A_SEC_TIDTS)&0xf0)>>4;
+
+#undef DATA
+ /* Clear fusion_F0710A interrupt */
+ return fusion_F0710A_write_complete();
+}
+
+#define val_cut_max(x, max, reverse) \
+do \
+{ \
+ if(x > max) \
+ x = max; \
+ if(reverse) \
+ x = (max) - (x); \
+} \
+while(0)
+
+static void fusion_F0710A_wq(struct work_struct *work)
+{
+ struct input_dev *dev = fusion_F0710A.input;
+ int save_points = 0;
+ int x1 = 0, y1 = 0, z1 = 0, x2 = 0, y2 = 0, z2 = 0;
+
+ if (fusion_F0710A_read_sensor() < 0)
+ return;
+
+ printk(KERN_DEBUG "tip1, tid1, x1, y1, z1 (%x,%x,%d,%d,%d); tip2, tid2, x2, y2, z2 (%x,%x,%d,%d,%d)\n",
+ fusion_F0710A.tip1, fusion_F0710A.tid1, fusion_F0710A.x1, fusion_F0710A.y1, fusion_F0710A.z1,
+ fusion_F0710A.tip2, fusion_F0710A.tid2, fusion_F0710A.x2, fusion_F0710A.y2, fusion_F0710A.z2);
+
+ val_cut_max(fusion_F0710A.x1, fusion_F0710A.info.xres-1, fusion_F0710A.info.xy_reverse);
+ val_cut_max(fusion_F0710A.y1, fusion_F0710A.info.yres-1, fusion_F0710A.info.xy_reverse);
+ val_cut_max(fusion_F0710A.x2, fusion_F0710A.info.xres-1, fusion_F0710A.info.xy_reverse);
+ val_cut_max(fusion_F0710A.y2, fusion_F0710A.info.yres-1, fusion_F0710A.info.xy_reverse);
+
+ if(fusion_F0710A.tip1 == 1)
+ {
+ if(fusion_F0710A.tid1 == 1)
+ {
+ /* first point */
+ x1 = fusion_F0710A.x1;
+ y1 = fusion_F0710A.y1;
+ z1 = fusion_F0710A.z1;
+ save_points |= fusion_F0710A_SAVE_PT1;
+ }
+ else if(fusion_F0710A.tid1 == 2)
+ {
+ /* second point ABS_DISTANCE second point pressure, BTN_2 second point touch */
+ x2 = fusion_F0710A.x1;
+ y2 = fusion_F0710A.y1;
+ z2 = fusion_F0710A.z1;
+ save_points |= fusion_F0710A_SAVE_PT2;
+ }
+ }
+
+ if(fusion_F0710A.tip2 == 1)
+ {
+ if(fusion_F0710A.tid2 == 2)
+ {
+ /* second point ABS_DISTANCE second point pressure, BTN_2 second point touch */
+ x2 = fusion_F0710A.x2;
+ y2 = fusion_F0710A.y2;
+ z2 = fusion_F0710A.z2;
+ save_points |= fusion_F0710A_SAVE_PT2;
+ }
+ else if(fusion_F0710A.tid2 == 1)/* maybe this will never happen */
+ {
+ /* first point */
+ x1 = fusion_F0710A.x2;
+ y1 = fusion_F0710A.y2;
+ z1 = fusion_F0710A.z2;
+ save_points |= fusion_F0710A_SAVE_PT1;
+ }
+ }
+
+ input_report_abs(dev, ABS_MT_TOUCH_MAJOR, z1);
+ input_report_abs(dev, ABS_MT_WIDTH_MAJOR, 1);
+ input_report_abs(dev, ABS_MT_POSITION_X, x1);
+ input_report_abs(dev, ABS_MT_POSITION_Y, y1);
+ input_mt_sync(dev);
+ input_report_abs(dev, ABS_MT_TOUCH_MAJOR, z2);
+ input_report_abs(dev, ABS_MT_WIDTH_MAJOR, 2);
+ input_report_abs(dev, ABS_MT_POSITION_X, x2);
+ input_report_abs(dev, ABS_MT_POSITION_Y, y2);
+ input_mt_sync(dev);
+
+ input_sync(dev);
+
+ enable_irq(fusion_F0710A.client->irq);
+
+}
+static DECLARE_WORK(fusion_F0710A_work, fusion_F0710A_wq);
+
+static irqreturn_t fusion_F0710A_interrupt(int irq, void *dev_id)
+{
+ disable_irq_nosync(fusion_F0710A.client->irq);
+
+ queue_work(fusion_F0710A.workq, &fusion_F0710A_work);
+ return IRQ_HANDLED;
+}
+
+const static u8* g_ver_product[4] = {
+ "10Z8", "70Z7", "43Z6", ""
+};
+
+static int fusion_F0710A_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+{
+ int ret;
+ u8 ver_product, ver_id;
+ u32 version;
+
+ if(!i2c->irq)
+ {
+ dev_err(&i2c->dev, "fusion_F0710A irq < 0 \n");
+ ret = -ENOMEM;
+ goto bail1;
+ }
+
+ /* Attach the I2C client */
+ fusion_F0710A.client = i2c;
+ i2c_set_clientdata(i2c, &fusion_F0710A);
+
+ printk(KERN_INFO "fusion_F0710A :Touchscreen registered with bus id (%d) with slave address 0x%x\n",
+ i2c_adapter_id(fusion_F0710A.client->adapter), fusion_F0710A.client->addr);
+
+ /* Read out a lot of registers */
+ ret = fusion_F0710A_read_u8(fusion_F0710A_VIESION_INFO_LO);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "query failed: %d\n", ret);
+ goto bail1;
+ }
+ ver_product = (((u8)ret) & 0xc0) >> 6;
+ version = (10 + ((((u32)ret)&0x30) >> 4)) * 100000;
+ version += (((u32)ret)&0xf) * 1000;
+ /* Read out a lot of registers */
+ ret = fusion_F0710A_read_u8(fusion_F0710A_VIESION_INFO);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "query failed: %d\n", ret);
+ goto bail1;
+ }
+ ver_id = ((u8)(ret) & 0x6) >> 1;
+ version += ((((u32)ret) & 0xf8) >> 3) * 10;
+ version += (((u32)ret) & 0x1) + 1; /* 0 is build 1, 1 is build 2 */
+ printk(KERN_INFO "fusion_F0710A version product %s(%d)\n", g_ver_product[ver_product] ,ver_product);
+ printk(KERN_INFO "fusion_F0710A version id %s(%d)\n", ver_id ? "1.4" : "1.0", ver_id);
+ printk(KERN_INFO "fusion_F0710A version series (%d)\n", version);
+
+ switch(ver_product)
+ {
+ case fusion_F0710A_VIESION_07: /* 7 inch */
+ fusion_F0710A.info.xres = fusion_F0710A07_XMAX;
+ fusion_F0710A.info.yres = fusion_F0710A07_YMAX;
+ fusion_F0710A.info.xy_reverse = fusion_F0710A07_REV;
+ break;
+ case fusion_F0710A_VIESION_43: /* 4.3 inch */
+ fusion_F0710A.info.xres = fusion_F0710A43_XMAX;
+ fusion_F0710A.info.yres = fusion_F0710A43_YMAX;
+ fusion_F0710A.info.xy_reverse = fusion_F0710A43_REV;
+ break;
+ default: /* fusion_F0710A_VIESION_10 10 inch */
+ fusion_F0710A.info.xres = fusion_F0710A10_XMAX;
+ fusion_F0710A.info.yres = fusion_F0710A10_YMAX;
+ fusion_F0710A.info.xy_reverse = fusion_F0710A10_REV;
+ break;
+ }
+
+ /* Register the input device. */
+ ret = fusion_F0710A_register_input();
+ if (ret < 0) {
+ dev_err(&i2c->dev, "can't register input: %d\n", ret);
+ goto bail1;
+ }
+
+ /* Create a worker thread */
+ fusion_F0710A.workq = create_singlethread_workqueue(DRV_NAME);
+ if (fusion_F0710A.workq == NULL) {
+ dev_err(&i2c->dev, "can't create work queue\n");
+ ret = -ENOMEM;
+ goto bail2;
+ }
+
+
+ /* Register for the interrupt and enable it. Our handler will
+ * start getting invoked after this call. */
+ ret = request_irq(i2c->irq, fusion_F0710A_interrupt, IRQF_TRIGGER_RISING,
+ i2c->name, &fusion_F0710A);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "can't get irq %d: %d\n", i2c->irq, ret);
+ goto bail3;
+ }
+ /* clear the irq first */
+ ret = fusion_F0710A_write_u8(fusion_F0710A_SCAN_COMPLETE, 0);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Clear irq failed: %d\n", ret);
+ goto bail4;
+ }
+
+ return 0;
+
+ bail4:
+ free_irq(i2c->irq, &fusion_F0710A);
+
+ bail3:
+ destroy_workqueue(fusion_F0710A.workq);
+ fusion_F0710A.workq = NULL;
+
+
+ bail2:
+ input_unregister_device(fusion_F0710A.input);
+ bail1:
+
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int fusion_F0710A_suspend(struct i2c_client *i2c, pm_message_t mesg)
+{
+ disable_irq(i2c->irq);
+ flush_workqueue(fusion_F0710A.workq);
+
+ return 0;
+}
+
+static int fusion_F0710A_resume(struct i2c_client *i2c)
+{
+ enable_irq(i2c->irq);
+
+ return 0;
+}
+#endif
+
+static int fusion_F0710A_remove(struct i2c_client *i2c)
+{
+ destroy_workqueue(fusion_F0710A.workq);
+ free_irq(i2c->irq, &fusion_F0710A);
+ input_unregister_device(fusion_F0710A.input);
+ i2c_set_clientdata(i2c, NULL);
+
+ printk(KERN_INFO "fusion_F0710A driver removed\n");
+
+ return 0;
+}
+
+static struct i2c_device_id fusion_F0710A_id[] = {
+ {"fusion_F0710A", 0},
+ {},
+};
+
+static struct i2c_driver fusion_F0710A_i2c_drv = {
+ .driver = {
+ .name = DRV_NAME,
+ },
+ .probe = fusion_F0710A_probe,
+ .remove = fusion_F0710A_remove,
+#ifdef CONFIG_PM
+ .suspend = fusion_F0710A_suspend,
+ .resume = fusion_F0710A_resume,
+#endif
+ .id_table = fusion_F0710A_id,
+ .address_list = normal_i2c,
+};
+
+
+static int __init fusion_F0710A_init( void )
+{
+ int ret;
+
+ memset(&fusion_F0710A, 0, sizeof(fusion_F0710A));
+
+ /* Probe for fusion_F0710A on I2C. */
+ ret = i2c_add_driver(&fusion_F0710A_i2c_drv);
+ if (ret < 0) {
+ printk(KERN_ERR "fusion_F0710A_init can't add i2c driver: %d\n", ret);
+ }
+
+ return ret;
+}
+
+static void __exit fusion_F0710A_exit( void )
+{
+ i2c_del_driver(&fusion_F0710A_i2c_drv);
+}
+module_init(fusion_F0710A_init);
+module_exit(fusion_F0710A_exit);
+
+MODULE_DESCRIPTION("fusion_F0710A Touchscreen Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/input/touchscreen/fusion_F0710A.h b/drivers/input/touchscreen/fusion_F0710A.h
new file mode 100644
index 000000000000..85f8210345a9
--- /dev/null
+++ b/drivers/input/touchscreen/fusion_F0710A.h
@@ -0,0 +1,87 @@
+/*
+ * "fusion_F0710A" touchscreen driver
+ *
+ * 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.
+ */
+
+/* I2C slave address */
+#define fusion_F0710A_I2C_SLAVE_ADDR 0x10
+
+/* I2C registers */
+#define fusion_F0710A_DATA_INFO 0x00
+
+/* First Point*/
+#define fusion_F0710A_POS_X1_HI 0x01 /* 16-bit register, MSB */
+#define fusion_F0710A_POS_X1_LO 0x02 /* 16-bit register, LSB */
+#define fusion_F0710A_POS_Y1_HI 0x03 /* 16-bit register, MSB */
+#define fusion_F0710A_POS_Y1_LO 0x04 /* 16-bit register, LSB */
+#define fusion_F0710A_FIR_PRESS 0X05
+#define fusion_F0710A_FIR_TIDTS 0X06
+
+/* Second Point */
+#define fusion_F0710A_POS_X2_HI 0x07 /* 16-bit register, MSB */
+#define fusion_F0710A_POS_X2_LO 0x08 /* 16-bit register, LSB */
+#define fusion_F0710A_POS_Y2_HI 0x09 /* 16-bit register, MSB */
+#define fusion_F0710A_POS_Y2_LO 0x0A /* 16-bit register, LSB */
+#define fusion_F0710A_SEC_PRESS 0x0B
+#define fusion_F0710A_SEC_TIDTS 0x0C
+
+#define fusion_F0710A_VIESION_INFO_LO 0X0E
+#define fusion_F0710A_VIESION_INFO 0X0F
+
+#define fusion_F0710A_RESET 0x10
+#define fusion_F0710A_SCAN_COMPLETE 0x11
+
+
+#define fusion_F0710A_VIESION_10 0
+#define fusion_F0710A_VIESION_07 1
+#define fusion_F0710A_VIESION_43 2
+
+/* fusion_F0710A 10 inch panel */
+#define fusion_F0710A10_XMAX 2275
+#define fusion_F0710A10_YMAX 1275
+#define fusion_F0710A10_REV 1
+
+/* fusion_F0710A 7 inch panel */
+#define fusion_F0710A07_XMAX 1500
+#define fusion_F0710A07_YMAX 900
+#define fusion_F0710A07_REV 0
+
+/* fusion_F0710A 4.3 inch panel */
+#define fusion_F0710A43_XMAX 900
+#define fusion_F0710A43_YMAX 500
+#define fusion_F0710A43_REV 0
+
+#define fusion_F0710A_SAVE_PT1 0x1
+#define fusion_F0710A_SAVE_PT2 0x2
+
+
+
+/* fusion_F0710A touch screen information */
+struct fusion_F0710A_info {
+ int xres; /* x resolution */
+ int yres; /* y resolution */
+ int xy_reverse; /* if need reverse in the x,y value x=xres-1-x, y=yres-1-y*/
+};
+
+struct fusion_F0710A_data {
+ struct fusion_F0710A_info info;
+ struct i2c_client *client;
+ struct workqueue_struct *workq;
+ struct input_dev *input;
+ u16 x1;
+ u16 y1;
+ u8 z1;
+ u8 tip1;
+ u8 tid1;
+ u16 x2;
+ u16 y2;
+ u8 z2;
+ u8 tip2;
+ u8 tid2;
+ u8 f_num;
+ u8 save_points;
+};
+
diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c
index ae88e13c99ff..502c267255b3 100644
--- a/drivers/input/touchscreen/stmpe-ts.c
+++ b/drivers/input/touchscreen/stmpe-ts.c
@@ -118,6 +118,7 @@ static void stmpe_work(struct work_struct *work)
__stmpe_reset_fifo(ts->stmpe);
input_report_abs(ts->idev, ABS_PRESSURE, 0);
+ input_report_key(ts->idev, BTN_TOUCH, 0);
input_sync(ts->idev);
}
@@ -148,9 +149,17 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data)
y = ((data_set[1] & 0xf) << 8) | data_set[2];
z = data_set[3];
+#ifndef CONFIG_ANDROID
input_report_abs(ts->idev, ABS_X, x);
input_report_abs(ts->idev, ABS_Y, y);
+#else /* !CONFIG_ANDROID */
+ /* Hack: rotate touch for now due to missing calibration integration
+ Note: 12-bit touch resolution */
+ input_report_abs(ts->idev, ABS_X, 4096 - x);
+ input_report_abs(ts->idev, ABS_Y, 4096 - y);
+#endif /* !CONFIG_ANDROID */
input_report_abs(ts->idev, ABS_PRESSURE, z);
+ input_report_key(ts->idev, BTN_TOUCH, (z != 0));
input_sync(ts->idev);
/* flush the FIFO after we have read out our values. */
@@ -161,7 +170,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data)
STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN);
/* start polling for touch_det to detect release */
- schedule_delayed_work(&ts->work, HZ / 50);
+ schedule_delayed_work(&ts->work, HZ / 10);
return IRQ_HANDLED;
}
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
index 5dbe73af2f8f..2cca5b5e0b1a 100644
--- a/drivers/input/touchscreen/wm97xx-core.c
+++ b/drivers/input/touchscreen/wm97xx-core.c
@@ -54,6 +54,10 @@
#define WM_CORE_VERSION "1.00"
#define DEFAULT_PRESSURE 0xb0c0
+#ifdef CONFIG_MACH_COLIBRI_T20
+extern void *get_colibri_t20_audio_platform_data(void);
+#endif
+
/*
* Touchscreen absolute values
@@ -671,7 +675,13 @@ static int wm97xx_probe(struct device *dev)
}
platform_set_drvdata(wm->battery_dev, wm);
wm->battery_dev->dev.parent = dev;
+
+#if defined(CONFIG_MACH_COLIBRI_T20) && !defined(CONFIG_ANDROID)
+ wm->battery_dev->dev.platform_data = get_colibri_t20_audio_platform_data();
+#else
wm->battery_dev->dev.platform_data = pdata;
+#endif
+
ret = platform_device_add(wm->battery_dev);
if (ret < 0)
goto batt_reg_err;
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index 9a146c8bba92..1c140e5ace4f 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -96,6 +96,7 @@ struct tps6586x {
struct mutex lock;
struct device *dev;
struct i2c_client *client;
+ enum tps6586x_type type;
struct gpio_chip gpio;
struct irq_chip irq_chip;
@@ -255,6 +256,14 @@ out:
}
EXPORT_SYMBOL_GPL(tps6586x_update);
+enum tps6586x_type tps6586x_gettype(struct device *dev)
+{
+ struct tps6586x *tps6586x = dev_get_drvdata(dev);
+
+ return tps6586x->type;
+}
+EXPORT_SYMBOL_GPL(tps6586x_gettype);
+
static struct i2c_client *tps6586x_i2c_client = NULL;
static void tps6586x_power_off(void)
{
@@ -517,17 +526,36 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
return -ENOTSUPP;
}
+ tps6586x = kzalloc(sizeof(struct tps6586x), GFP_KERNEL);
+ if (tps6586x == NULL)
+ return -ENOMEM;
+
ret = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC);
if (ret < 0) {
dev_err(&client->dev, "Chip ID read failed: %d\n", ret);
- return -EIO;
+ ret = -EIO;
+ goto err_irq_init;
+ }
+ tps6586x->type = (enum tps6586x_type)ret;
+ switch (ret) {
+ case TPS658621A:
+ dev_info(&client->dev, "found TPS658621A, ");
+ break;
+ case TPS658621D:
+ dev_info(&client->dev, "found TPS658621D, ");
+ break;
+ case TPS658623:
+ dev_info(&client->dev, "found TPS658623, ");
+ break;
+ case TPS658643:
+ dev_info(&client->dev, "found TPS658643, ");
+ break;
+ default:
+ dev_info(&client->dev, "unknown TPS6586X found, ");
+ tps6586x->type = TPS6586X_ANY;
}
- dev_info(&client->dev, "VERSIONCRC is %02x\n", ret);
-
- tps6586x = kzalloc(sizeof(struct tps6586x), GFP_KERNEL);
- if (tps6586x == NULL)
- return -ENOMEM;
+ printk("VERSIONCRC is %02x\n", ret);
tps6586x->client = client;
tps6586x->dev = &client->dev;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 3a440dcf0f24..aa03ca7d5226 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -486,7 +486,10 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
if (offset) {
if (data->flags & MMC_DATA_WRITE) {
buffer = sdhci_kmap_atomic(sg, &flags);
+/* Hack to avoid extensive warning messages from Redpine Signals LiteFi driver */
+#ifndef CONFIG_MACH_COLIBRI_T20
WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3));
+#endif
memcpy(align, buffer, offset);
sdhci_kunmap_atomic(buffer, &flags);
}
diff --git a/drivers/mtd/devices/tegra_nand.c b/drivers/mtd/devices/tegra_nand.c
index 38baa40746c6..6034f0b2f239 100644
--- a/drivers/mtd/devices/tegra_nand.c
+++ b/drivers/mtd/devices/tegra_nand.c
@@ -434,6 +434,35 @@ static int nand_cmd_get_status(struct tegra_nand_info *info, uint32_t *status)
return 0;
}
+static int tegra_nand_cmd_reset(struct tegra_nand_info *info,
+ uint32_t *chip_id)
+{
+ int err;
+ uint32_t status = 0;
+
+#ifdef TEGRA_NAND_DEBUG_PEDANTIC
+ BUG_ON(info->chip.curr_chip == -1);
+#endif
+
+ info->command_reg = (COMMAND_CLE |
+ (COMMAND_CE(info->chip.curr_chip)));
+ writel(NAND_CMD_RESET, CMD_REG1);
+ writel(0, CMD_REG2);
+ writel(0, ADDR_REG1);
+ writel(0, ADDR_REG2);
+ writel(0, CONFIG_REG);
+
+ err = tegra_nand_go(info);
+ if (err != 0)
+ return err;
+
+ err = nand_cmd_get_status(info, &status);
+ if (err != 0)
+ return err;
+
+ return 0;
+}
+
/* must be called with lock held */
static int check_block_isbad(struct mtd_info *mtd, loff_t offs)
{
@@ -1400,6 +1429,11 @@ static int tegra_nand_scan(struct mtd_info *mtd, int maxchips)
writel(0, CONFIG_REG);
select_chip(info, 0);
+
+ err = tegra_nand_cmd_reset(info, &tmp);
+ if (err != 0)
+ goto out_error;
+
err = tegra_nand_cmd_readid(info, &tmp);
if (err != 0)
goto out_error;
@@ -1458,7 +1492,7 @@ static int tegra_nand_scan(struct mtd_info *mtd, int maxchips)
/* page_size */
tmp = dev_parms & 0x3;
- mtd->writesize = 1024 << tmp;
+ mtd->writesize = mtd->writebufsize = 1024 << tmp;
info->chip.column_mask = mtd->writesize - 1;
if (mtd->writesize > 4096) {
@@ -1481,6 +1515,11 @@ static int tegra_nand_scan(struct mtd_info *mtd, int maxchips)
/* data block size (erase size) (w/o spare) */
tmp = (dev_parms >> 4) & 0x3;
+ /* work around wrong block size identified for our device
+ Note: ONFI would really be the way to go but has not been supported
+ in Linux prior to version 2.6.37. */
+ if ((vendor_id == 0x2C) && (dev_id == 0x38))
+ tmp += 1;
mtd->erasesize = (64 * 1024) << tmp;
info->chip.block_shift = ffs(mtd->erasesize) - 1;
/* bus width of the nand chip 8/16 */
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index 00cf1b0d6053..a56bf52acf5e 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -104,6 +104,7 @@ struct nand_flash_dev nand_flash_ids[] = {
{"NAND 512MiB 3,3V 16-bit", 0xCC, 0, 512, 0, LP_OPTIONS16},
/* 8 Gigabit */
+ {"NAND 1GiB 1,8V 8-bit", 0x38, 0, 1024, 0, LP_OPTIONS},
{"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, LP_OPTIONS},
{"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, LP_OPTIONS},
{"NAND 1GiB 1,8V 16-bit", 0xB3, 0, 1024, 0, LP_OPTIONS16},
diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c
index 330140ee266d..535e4032da2b 100644
--- a/drivers/net/can/mcp251x.c
+++ b/drivers/net/can/mcp251x.c
@@ -593,6 +593,18 @@ static int mcp251x_do_set_bittiming(struct net_device *net)
return 0;
}
+static int mcp251x_get_berr_counter(const struct net_device *dev, struct can_berr_counter *bec)
+{
+ struct mcp251x_priv *priv = netdev_priv(dev);
+ struct spi_device *spi = priv->spi;
+ uint8_t tec,rec;
+
+ mcp251x_read_2regs(spi, TEC, &tec, &rec);
+ bec->txerr = tec;
+ bec->rxerr = rec;
+ return 0;
+}
+
static int mcp251x_setup(struct net_device *net, struct mcp251x_priv *priv,
struct spi_device *spi)
{
@@ -997,6 +1009,7 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi)
priv = netdev_priv(net);
priv->can.bittiming_const = &mcp251x_bittiming_const;
priv->can.do_set_mode = mcp251x_do_set_mode;
+ priv->can.do_get_berr_counter = mcp251x_get_berr_counter;
priv->can.clock.freq = pdata->oscillator_frequency / 2;
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
diff --git a/drivers/net/igb/Makefile b/drivers/net/igb/Makefile
index c6e4621b6262..01193b8460fc 100644
--- a/drivers/net/igb/Makefile
+++ b/drivers/net/igb/Makefile
@@ -33,5 +33,6 @@
obj-$(CONFIG_IGB) += igb.o
igb-objs := igb_main.o igb_ethtool.o e1000_82575.o \
- e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o
+ e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o \
+ e1000_i210.o
diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c
index c0857bdfb03a..ad3bf1792d7c 100644
--- a/drivers/net/igb/e1000_82575.c
+++ b/drivers/net/igb/e1000_82575.c
@@ -34,6 +34,7 @@
#include "e1000_mac.h"
#include "e1000_82575.h"
+#include "e1000_i210.h"
static s32 igb_get_invariants_82575(struct e1000_hw *);
static s32 igb_acquire_phy_82575(struct e1000_hw *);
@@ -50,6 +51,8 @@ static s32 igb_write_phy_reg_82580(struct e1000_hw *, u32, u16);
static s32 igb_reset_hw_82575(struct e1000_hw *);
static s32 igb_reset_hw_82580(struct e1000_hw *);
static s32 igb_set_d0_lplu_state_82575(struct e1000_hw *, bool);
+static s32 igb_set_d0_lplu_state_82580(struct e1000_hw *, bool);
+static s32 igb_set_d3_lplu_state_82580(struct e1000_hw *, bool);
static s32 igb_setup_copper_link_82575(struct e1000_hw *);
static s32 igb_setup_serdes_link_82575(struct e1000_hw *);
static s32 igb_write_phy_reg_sgmii_82575(struct e1000_hw *, u32, u16);
@@ -98,6 +101,8 @@ static bool igb_sgmii_uses_mdio_82575(struct e1000_hw *hw)
break;
case e1000_82580:
case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
reg = rd32(E1000_MDICNFG);
ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO);
break;
@@ -152,6 +157,17 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
case E1000_DEV_ID_I350_SGMII:
mac->type = e1000_i350;
break;
+ case E1000_DEV_ID_I210_COPPER:
+ case E1000_DEV_ID_I210_COPPER_OEM1:
+ case E1000_DEV_ID_I210_COPPER_IT:
+ case E1000_DEV_ID_I210_FIBER:
+ case E1000_DEV_ID_I210_SERDES:
+ case E1000_DEV_ID_I210_SGMII:
+ mac->type = e1000_i210;
+ break;
+ case E1000_DEV_ID_I211_COPPER:
+ mac->type = e1000_i211;
+ break;
default:
return -E1000_ERR_MAC_INIT;
break;
@@ -184,26 +200,44 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
/* Set mta register count */
mac->mta_reg_count = 128;
/* Set rar entry count */
- mac->rar_entry_count = E1000_RAR_ENTRIES_82575;
- if (mac->type == e1000_82576)
+ switch (mac->type) {
+ case e1000_82576:
mac->rar_entry_count = E1000_RAR_ENTRIES_82576;
- if (mac->type == e1000_82580)
+ break;
+ case e1000_82580:
mac->rar_entry_count = E1000_RAR_ENTRIES_82580;
- if (mac->type == e1000_i350)
+ break;
+ case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
mac->rar_entry_count = E1000_RAR_ENTRIES_I350;
+ break;
+ default:
+ mac->rar_entry_count = E1000_RAR_ENTRIES_82575;
+ break;
+ }
/* reset */
if (mac->type >= e1000_82580)
mac->ops.reset_hw = igb_reset_hw_82580;
else
mac->ops.reset_hw = igb_reset_hw_82575;
+
+ if (mac->type >= e1000_i210) {
+ mac->ops.acquire_swfw_sync = igb_acquire_swfw_sync_i210;
+ mac->ops.release_swfw_sync = igb_release_swfw_sync_i210;
+ } else {
+ mac->ops.acquire_swfw_sync = igb_acquire_swfw_sync_82575;
+ mac->ops.release_swfw_sync = igb_release_swfw_sync_82575;
+ }
+
/* Set if part includes ASF firmware */
mac->asf_firmware_present = true;
/* Set if manageability features are enabled. */
mac->arc_subsystem_valid =
(rd32(E1000_FWSM) & E1000_FWSM_MODE_MASK)
? true : false;
- /* enable EEE on i350 parts */
- if (mac->type == e1000_i350)
+ /* enable EEE on i350 parts and later parts */
+ if (mac->type >= e1000_i350)
dev_spec->eee_disable = false;
else
dev_spec->eee_disable = true;
@@ -215,26 +249,6 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
/* NVM initialization */
eecd = rd32(E1000_EECD);
-
- nvm->opcode_bits = 8;
- nvm->delay_usec = 1;
- switch (nvm->override) {
- case e1000_nvm_override_spi_large:
- nvm->page_size = 32;
- nvm->address_bits = 16;
- break;
- case e1000_nvm_override_spi_small:
- nvm->page_size = 8;
- nvm->address_bits = 8;
- break;
- default:
- nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
- nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8;
- break;
- }
-
- nvm->type = e1000_nvm_eeprom_spi;
-
size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
E1000_EECD_SIZE_EX_SHIFT);
@@ -244,6 +258,33 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
*/
size += NVM_WORD_SIZE_BASE_SHIFT;
+ nvm->word_size = 1 << size;
+ if (hw->mac.type < e1000_i210) {
+ nvm->opcode_bits = 8;
+ nvm->delay_usec = 1;
+ switch (nvm->override) {
+ case e1000_nvm_override_spi_large:
+ nvm->page_size = 32;
+ nvm->address_bits = 16;
+ break;
+ case e1000_nvm_override_spi_small:
+ nvm->page_size = 8;
+ nvm->address_bits = 8;
+ break;
+ default:
+ nvm->page_size = eecd
+ & E1000_EECD_ADDR_BITS ? 32 : 8;
+ nvm->address_bits = eecd
+ & E1000_EECD_ADDR_BITS ? 16 : 8;
+ break;
+ }
+ if (nvm->word_size == (1 << 15))
+ nvm->page_size = 128;
+
+ nvm->type = e1000_nvm_eeprom_spi;
+ } else
+ nvm->type = e1000_nvm_flash_hw;
+
/*
* Check for invalid size
*/
@@ -252,32 +293,60 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
"defaulting to 32K.\n");
size = 15;
}
- nvm->word_size = 1 << size;
- if (nvm->word_size == (1 << 15))
- nvm->page_size = 128;
/* NVM Function Pointers */
- nvm->ops.acquire = igb_acquire_nvm_82575;
- if (nvm->word_size < (1 << 15))
- nvm->ops.read = igb_read_nvm_eerd;
- else
- nvm->ops.read = igb_read_nvm_spi;
-
- nvm->ops.release = igb_release_nvm_82575;
switch (hw->mac.type) {
case e1000_82580:
nvm->ops.validate = igb_validate_nvm_checksum_82580;
nvm->ops.update = igb_update_nvm_checksum_82580;
+ nvm->ops.acquire = igb_acquire_nvm_82575;
+ nvm->ops.release = igb_release_nvm_82575;
+ if (nvm->word_size < (1 << 15))
+ nvm->ops.read = igb_read_nvm_eerd;
+ else
+ nvm->ops.read = igb_read_nvm_spi;
+ nvm->ops.write = igb_write_nvm_spi;
break;
case e1000_i350:
nvm->ops.validate = igb_validate_nvm_checksum_i350;
nvm->ops.update = igb_update_nvm_checksum_i350;
+ nvm->ops.acquire = igb_acquire_nvm_82575;
+ nvm->ops.release = igb_release_nvm_82575;
+ if (nvm->word_size < (1 << 15))
+ nvm->ops.read = igb_read_nvm_eerd;
+ else
+ nvm->ops.read = igb_read_nvm_spi;
+ nvm->ops.write = igb_write_nvm_spi;
+ break;
+ case e1000_i210:
+ nvm->ops.validate = igb_validate_nvm_checksum_i210;
+ nvm->ops.update = igb_update_nvm_checksum_i210;
+ nvm->ops.acquire = igb_acquire_nvm_i210;
+ nvm->ops.release = igb_release_nvm_i210;
+ nvm->ops.read = igb_read_nvm_srrd_i210;
+ nvm->ops.valid_led_default = igb_valid_led_default_i210;
+ break;
+ case e1000_i211:
+ nvm->ops.acquire = igb_acquire_nvm_i210;
+ nvm->ops.release = igb_release_nvm_i210;
+ nvm->ops.read = igb_read_nvm_i211;
+ nvm->ops.valid_led_default = igb_valid_led_default_i210;
+ nvm->ops.validate = NULL;
+ nvm->ops.update = NULL;
+ nvm->ops.write = NULL;
break;
default:
nvm->ops.validate = igb_validate_nvm_checksum;
nvm->ops.update = igb_update_nvm_checksum;
+ nvm->ops.acquire = igb_acquire_nvm_82575;
+ nvm->ops.release = igb_release_nvm_82575;
+ if (nvm->word_size < (1 << 15))
+ nvm->ops.read = igb_read_nvm_eerd;
+ else
+ nvm->ops.read = igb_read_nvm_spi;
+ nvm->ops.write = igb_write_nvm_spi;
+ break;
}
- nvm->ops.write = igb_write_nvm_spi;
/* if part supports SR-IOV then initialize mailbox parameters */
switch (mac->type) {
@@ -315,9 +384,13 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
if (igb_sgmii_active_82575(hw) && !igb_sgmii_uses_mdio_82575(hw)) {
phy->ops.read_reg = igb_read_phy_reg_sgmii_82575;
phy->ops.write_reg = igb_write_phy_reg_sgmii_82575;
- } else if (hw->mac.type >= e1000_82580) {
+ } else if ((hw->mac.type == e1000_82580)
+ || (hw->mac.type == e1000_i350)) {
phy->ops.read_reg = igb_read_phy_reg_82580;
phy->ops.write_reg = igb_write_phy_reg_82580;
+ } else if (hw->phy.type >= e1000_phy_i210) {
+ phy->ops.read_reg = igb_read_phy_reg_gs40g;
+ phy->ops.write_reg = igb_write_phy_reg_gs40g;
} else {
phy->ops.read_reg = igb_read_phy_reg_igp;
phy->ops.write_reg = igb_write_phy_reg_igp;
@@ -346,6 +419,14 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
else
phy->ops.get_cable_length = igb_get_cable_length_m88;
+ if (phy->id == I210_I_PHY_ID) {
+ phy->ops.get_cable_length =
+ igb_get_cable_length_m88_gen2;
+ phy->ops.set_d0_lplu_state =
+ igb_set_d0_lplu_state_82580;
+ phy->ops.set_d3_lplu_state =
+ igb_set_d3_lplu_state_82580;
+ }
phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88;
break;
case IGP03E1000_E_PHY_ID:
@@ -362,6 +443,17 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_82580;
phy->ops.get_cable_length = igb_get_cable_length_82580;
phy->ops.get_phy_info = igb_get_phy_info_82580;
+ phy->ops.set_d0_lplu_state = igb_set_d0_lplu_state_82580;
+ phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state_82580;
+ break;
+ case I210_I_PHY_ID:
+ phy->type = e1000_phy_i210;
+ phy->ops.get_phy_info = igb_get_phy_info_m88;
+ phy->ops.check_polarity = igb_check_polarity_m88;
+ phy->ops.get_cable_length = igb_get_cable_length_m88_gen2;
+ phy->ops.set_d0_lplu_state = igb_set_d0_lplu_state_82580;
+ phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state_82580;
+ phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88;
break;
default:
return -E1000_ERR_PHY;
@@ -388,7 +480,7 @@ static s32 igb_acquire_phy_82575(struct e1000_hw *hw)
else if (hw->bus.func == E1000_FUNC_3)
mask = E1000_SWFW_PHY3_SM;
- return igb_acquire_swfw_sync_82575(hw, mask);
+ return hw->mac.ops.acquire_swfw_sync(hw, mask);
}
/**
@@ -409,7 +501,7 @@ static void igb_release_phy_82575(struct e1000_hw *hw)
else if (hw->bus.func == E1000_FUNC_3)
mask = E1000_SWFW_PHY3_SM;
- igb_release_swfw_sync_82575(hw, mask);
+ hw->mac.ops.release_swfw_sync(hw, mask);
}
/**
@@ -513,6 +605,8 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw)
break;
case e1000_82580:
case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
mdic = rd32(E1000_MDICNFG);
mdic &= E1000_MDICNFG_PHY_MASK;
phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT;
@@ -677,6 +771,96 @@ out:
}
/**
+ * igb_set_d0_lplu_state_82580 - Set Low Power Linkup D0 state
+ * @hw: pointer to the HW structure
+ * @active: true to enable LPLU, false to disable
+ *
+ * Sets the LPLU D0 state according to the active flag. When
+ * activating LPLU this function also disables smart speed
+ * and vice versa. LPLU will not be activated unless the
+ * device autonegotiation advertisement meets standards of
+ * either 10 or 10/100 or 10/100/1000 at all duplexes.
+ * This is a function pointer entry point only called by
+ * PHY setup routines.
+ **/
+static s32 igb_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val = 0;
+ u16 data;
+
+ data = rd32(E1000_82580_PHY_POWER_MGMT);
+
+ if (active) {
+ data |= E1000_82580_PM_D0_LPLU;
+
+ /* When LPLU is enabled, we should disable SmartSpeed */
+ data &= ~E1000_82580_PM_SPD;
+ } else {
+ data &= ~E1000_82580_PM_D0_LPLU;
+
+ /*
+ * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ * during Dx states where the power conservation is most
+ * important. During driver activity we should enable
+ * SmartSpeed, so performance is maintained.
+ */
+ if (phy->smart_speed == e1000_smart_speed_on)
+ data |= E1000_82580_PM_SPD;
+ else if (phy->smart_speed == e1000_smart_speed_off)
+ data &= ~E1000_82580_PM_SPD; }
+
+ wr32(E1000_82580_PHY_POWER_MGMT, data);
+ return ret_val;
+}
+
+/**
+ * igb_set_d3_lplu_state_82580 - Sets low power link up state for D3
+ * @hw: pointer to the HW structure
+ * @active: boolean used to enable/disable lplu
+ *
+ * Success returns 0, Failure returns 1
+ *
+ * The low power link up (lplu) state is set to the power management level D3
+ * and SmartSpeed is disabled when active is true, else clear lplu for D3
+ * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU
+ * is used during Dx states where the power conservation is most important.
+ * During driver activity, SmartSpeed should be enabled so performance is
+ * maintained.
+ **/
+s32 igb_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val = 0;
+ u16 data;
+
+ data = rd32(E1000_82580_PHY_POWER_MGMT);
+
+ if (!active) {
+ data &= ~E1000_82580_PM_D3_LPLU;
+ /*
+ * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ * during Dx states where the power conservation is most
+ * important. During driver activity we should enable
+ * SmartSpeed, so performance is maintained.
+ */
+ if (phy->smart_speed == e1000_smart_speed_on)
+ data |= E1000_82580_PM_SPD;
+ else if (phy->smart_speed == e1000_smart_speed_off)
+ data &= ~E1000_82580_PM_SPD;
+ } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
+ (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
+ (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
+ data |= E1000_82580_PM_D3_LPLU;
+ /* When LPLU is enabled, we should disable SmartSpeed */
+ data &= ~E1000_82580_PM_SPD;
+ }
+
+ wr32(E1000_82580_PHY_POWER_MGMT, data);
+ return ret_val;
+}
+
+/**
* igb_acquire_nvm_82575 - Request for access to EEPROM
* @hw: pointer to the HW structure
*
@@ -689,14 +873,14 @@ static s32 igb_acquire_nvm_82575(struct e1000_hw *hw)
{
s32 ret_val;
- ret_val = igb_acquire_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
+ ret_val = hw->mac.ops.acquire_swfw_sync(hw, E1000_SWFW_EEP_SM);
if (ret_val)
goto out;
ret_val = igb_acquire_nvm(hw);
if (ret_val)
- igb_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
+ hw->mac.ops.release_swfw_sync(hw, E1000_SWFW_EEP_SM);
out:
return ret_val;
@@ -712,7 +896,7 @@ out:
static void igb_release_nvm_82575(struct e1000_hw *hw)
{
igb_release_nvm(hw);
- igb_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
+ hw->mac.ops.release_swfw_sync(hw, E1000_SWFW_EEP_SM);
}
/**
@@ -1080,7 +1264,6 @@ static s32 igb_init_hw_82575(struct e1000_hw *hw)
* is no link.
*/
igb_clear_hw_cntrs_82575(hw);
-
return ret_val;
}
@@ -1117,6 +1300,7 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw)
}
}
switch (hw->phy.type) {
+ case e1000_phy_i210:
case e1000_phy_m88:
if (hw->phy.id == I347AT4_E_PHY_ID ||
hw->phy.id == M88E1112_E_PHY_ID)
@@ -1740,7 +1924,7 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw)
/* Determine whether or not a global dev reset is requested */
if (global_device_reset &&
- igb_acquire_swfw_sync_82575(hw, swmbsw_mask))
+ hw->mac.ops.acquire_swfw_sync(hw, swmbsw_mask))
global_device_reset = false;
if (global_device_reset &&
@@ -1786,7 +1970,7 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw)
/* Release semaphore */
if (global_device_reset)
- igb_release_swfw_sync_82575(hw, swmbsw_mask);
+ hw->mac.ops.release_swfw_sync(hw, swmbsw_mask);
return ret_val;
}
diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h
index 786e110011a3..b477b20a2b05 100644
--- a/drivers/net/igb/e1000_82575.h
+++ b/drivers/net/igb/e1000_82575.h
@@ -55,10 +55,11 @@ extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw);
#define E1000_SRRCTL_DROP_EN 0x80000000
#define E1000_SRRCTL_TIMESTAMP 0x40000000
+
#define E1000_MRQC_ENABLE_RSS_4Q 0x00000002
#define E1000_MRQC_ENABLE_VMDQ 0x00000003
-#define E1000_MRQC_ENABLE_VMDQ_RSS_2Q 0x00000005
#define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
+#define E1000_MRQC_ENABLE_VMDQ_RSS_2Q 0x00000005
#define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
#define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000
diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h
index 7b8ddd830f19..e32e3a71eff1 100644
--- a/drivers/net/igb/e1000_defines.h
+++ b/drivers/net/igb/e1000_defines.h
@@ -452,6 +452,7 @@
#define E1000_ERR_INVALID_ARGUMENT 16
#define E1000_ERR_NO_SPACE 17
#define E1000_ERR_NVM_PBA_SECTION 18
+#define E1000_ERR_INVM_VALUE_NOT_FOUND 19
/* Loop limit on how long we wait for auto-negotiation to complete */
#define COPPER_LINK_UP_LIMIT 10
@@ -589,6 +590,25 @@
#define E1000_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */
#define E1000_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */
#define E1000_EECD_SIZE_EX_SHIFT 11
+#define E1000_EECD_FLUPD_I210 0x00800000 /* Update FLASH */
+#define E1000_EECD_FLUDONE_I210 0x04000000 /* Update FLASH done*/
+#define E1000_FLUDONE_ATTEMPTS 20000
+#define E1000_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */
+#define E1000_I210_FIFO_SEL_RX 0x00
+#define E1000_I210_FIFO_SEL_TX_QAV(_i) (0x02 + (_i))
+#define E1000_I210_FIFO_SEL_TX_LEGACY E1000_I210_FIFO_SEL_TX_QAV(0)
+#define E1000_I210_FIFO_SEL_BMC2OS_TX 0x06
+#define E1000_I210_FIFO_SEL_BMC2OS_RX 0x01
+#define E1000_EECD_FLUPD_I210 0x00800000 /* Update FLASH */
+#define E1000_EECD_FLUDONE_I210 0x04000000 /* Update FLASH done*/
+#define E1000_FLUDONE_ATTEMPTS 20000
+#define E1000_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */
+#define E1000_I210_FIFO_SEL_RX 0x00
+#define E1000_I210_FIFO_SEL_TX_QAV(_i) (0x02 + (_i))
+#define E1000_I210_FIFO_SEL_TX_LEGACY E1000_I210_FIFO_SEL_TX_QAV(0)
+#define E1000_I210_FIFO_SEL_BMC2OS_TX 0x06
+#define E1000_I210_FIFO_SEL_BMC2OS_RX 0x01
+
/* Offset to data in NVM read/write registers */
#define E1000_NVM_RW_REG_DATA 16
@@ -607,6 +627,16 @@
#define NVM_CHECKSUM_REG 0x003F
#define NVM_COMPATIBILITY_REG_3 0x0003
#define NVM_COMPATIBILITY_BIT_MASK 0x8000
+#define NVM_MAC_ADDR 0x0000
+#define NVM_SUB_DEV_ID 0x000B
+#define NVM_SUB_VEN_ID 0x000C
+#define NVM_DEV_ID 0x000D
+#define NVM_VEN_ID 0x000E
+#define NVM_INIT_CTRL_2 0x000F
+#define NVM_INIT_CTRL_4 0x0013
+#define NVM_LED_1_CFG 0x001C
+#define NVM_LED_0_2_CFG 0x001F
+
#define E1000_NVM_CFG_DONE_PORT_0 0x040000 /* MNG config cycle done */
#define E1000_NVM_CFG_DONE_PORT_1 0x080000 /* ...for second port */
@@ -633,6 +663,7 @@
#define NVM_PBA_OFFSET_0 8
#define NVM_PBA_OFFSET_1 9
+#define NVM_RESERVED_WORD 0xFFFF
#define NVM_PBA_PTR_GUARD 0xFAFA
#define NVM_WORD_SIZE_BASE_SHIFT 6
@@ -690,6 +721,7 @@
#define I82580_I_PHY_ID 0x015403A0
#define I350_I_PHY_ID 0x015403B0
#define M88_VENDOR 0x0141
+#define I210_I_PHY_ID 0x01410C00
/* M88E1000 Specific Registers */
#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */
@@ -809,6 +841,7 @@
#define E1000_IPCNFG_EEE_100M_AN 0x00000004 /* EEE Enable 100M AN */
#define E1000_EEER_TX_LPI_EN 0x00010000 /* EEE Tx LPI Enable */
#define E1000_EEER_RX_LPI_EN 0x00020000 /* EEE Rx LPI Enable */
+#define E1000_EEER_FRC_AN 0x10000000 /* Enable EEE in loopback */
#define E1000_EEER_LPI_FC 0x00040000 /* EEE Enable on FC */
/* SerDes Control */
diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h
index 4519a1367170..2c7a3e130dc8 100644
--- a/drivers/net/igb/e1000_hw.h
+++ b/drivers/net/igb/e1000_hw.h
@@ -63,6 +63,18 @@ struct e1000_hw;
#define E1000_DEV_ID_I350_FIBER 0x1522
#define E1000_DEV_ID_I350_SERDES 0x1523
#define E1000_DEV_ID_I350_SGMII 0x1524
+#ifdef CONFIG_MACH_APALIS_T30
+/* Hack: Springville with a blank Flash (tools only, not for driver) */
+#define E1000_DEV_ID_I210_COPPER 0x1531
+#else
+#define E1000_DEV_ID_I210_COPPER 0x1533
+#endif
+#define E1000_DEV_ID_I210_COPPER_OEM1 0x1534
+#define E1000_DEV_ID_I210_COPPER_IT 0x1535
+#define E1000_DEV_ID_I210_FIBER 0x1536
+#define E1000_DEV_ID_I210_SERDES 0x1537
+#define E1000_DEV_ID_I210_SGMII 0x1538
+#define E1000_DEV_ID_I211_COPPER 0x1539
#define E1000_REVISION_2 2
#define E1000_REVISION_4 4
@@ -83,6 +95,8 @@ enum e1000_mac_type {
e1000_82576,
e1000_82580,
e1000_i350,
+ e1000_i210,
+ e1000_i211,
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
};
@@ -117,6 +131,7 @@ enum e1000_phy_type {
e1000_phy_igp_3,
e1000_phy_ife,
e1000_phy_82580,
+ e1000_phy_i210,
};
enum e1000_bus_type {
@@ -313,6 +328,9 @@ struct e1000_mac_operations {
void (*rar_set)(struct e1000_hw *, u8 *, u32);
s32 (*read_mac_addr)(struct e1000_hw *);
s32 (*get_speed_and_duplex)(struct e1000_hw *, u16 *, u16 *);
+ s32 (*acquire_swfw_sync)(struct e1000_hw *, u16);
+ void (*release_swfw_sync)(struct e1000_hw *, u16);
+
};
struct e1000_phy_operations {
@@ -338,6 +356,7 @@ struct e1000_nvm_operations {
s32 (*write)(struct e1000_hw *, u16, u16, u16 *);
s32 (*update)(struct e1000_hw *);
s32 (*validate)(struct e1000_hw *);
+ s32 (*valid_led_default)(struct e1000_hw *, u16 *);
};
struct e1000_info {
diff --git a/drivers/net/igb/e1000_i210.c b/drivers/net/igb/e1000_i210.c
new file mode 100644
index 000000000000..77a5f939bc74
--- /dev/null
+++ b/drivers/net/igb/e1000_i210.c
@@ -0,0 +1,603 @@
+/*******************************************************************************
+
+ Intel(R) Gigabit Ethernet Linux driver
+ Copyright(c) 2007-2012 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope 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.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+
+/* e1000_i210
+ * e1000_i211
+ */
+
+#include <linux/types.h>
+#include <linux/if_ether.h>
+
+#include "e1000_hw.h"
+#include "e1000_i210.h"
+
+static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw);
+static void igb_put_hw_semaphore_i210(struct e1000_hw *hw);
+static s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data);
+static s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw);
+
+/**
+ * igb_acquire_nvm_i210 - Request for access to EEPROM
+ * @hw: pointer to the HW structure
+ *
+ * Acquire the necessary semaphores for exclusive access to the EEPROM.
+ * Set the EEPROM access request bit and wait for EEPROM access grant bit.
+ * Return successful if access grant bit set, else clear the request for
+ * EEPROM access and return -E1000_ERR_NVM (-1).
+ **/
+s32 igb_acquire_nvm_i210(struct e1000_hw *hw)
+{
+ return igb_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
+}
+
+/**
+ * igb_release_nvm_i210 - Release exclusive access to EEPROM
+ * @hw: pointer to the HW structure
+ *
+ * Stop any current commands to the EEPROM and clear the EEPROM request bit,
+ * then release the semaphores acquired.
+ **/
+void igb_release_nvm_i210(struct e1000_hw *hw)
+{
+ igb_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
+}
+
+/**
+ * igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
+ * @hw: pointer to the HW structure
+ * @mask: specifies which semaphore to acquire
+ *
+ * Acquire the SW/FW semaphore to access the PHY or NVM. The mask
+ * will also specify which port we're acquiring the lock for.
+ **/
+s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
+{
+ u32 swfw_sync;
+ u32 swmask = mask;
+ u32 fwmask = mask << 16;
+ s32 ret_val = E1000_SUCCESS;
+ s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
+
+ while (i < timeout) {
+ if (igb_get_hw_semaphore_i210(hw)) {
+ ret_val = -E1000_ERR_SWFW_SYNC;
+ goto out;
+ }
+
+ swfw_sync = rd32(E1000_SW_FW_SYNC);
+ if (!(swfw_sync & fwmask))
+ break;
+
+ /*
+ * Firmware currently using resource (fwmask)
+ */
+ igb_put_hw_semaphore_i210(hw);
+ mdelay(5);
+ i++;
+ }
+
+ if (i == timeout) {
+ hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n");
+ ret_val = -E1000_ERR_SWFW_SYNC;
+ goto out;
+ }
+
+ swfw_sync |= swmask;
+ wr32(E1000_SW_FW_SYNC, swfw_sync);
+
+ igb_put_hw_semaphore_i210(hw);
+out:
+ return ret_val;
+}
+
+/**
+ * igb_release_swfw_sync_i210 - Release SW/FW semaphore
+ * @hw: pointer to the HW structure
+ * @mask: specifies which semaphore to acquire
+ *
+ * Release the SW/FW semaphore used to access the PHY or NVM. The mask
+ * will also specify which port we're releasing the lock for.
+ **/
+void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
+{
+ u32 swfw_sync;
+
+ while (igb_get_hw_semaphore_i210(hw) != E1000_SUCCESS)
+ ; /* Empty */
+
+ swfw_sync = rd32(E1000_SW_FW_SYNC);
+ swfw_sync &= ~mask;
+ wr32(E1000_SW_FW_SYNC, swfw_sync);
+
+ igb_put_hw_semaphore_i210(hw);
+}
+
+/**
+ * igb_get_hw_semaphore_i210 - Acquire hardware semaphore
+ * @hw: pointer to the HW structure
+ *
+ * Acquire the HW semaphore to access the PHY or NVM
+ **/
+static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw)
+{
+ u32 swsm;
+ s32 ret_val = E1000_SUCCESS;
+ s32 timeout = hw->nvm.word_size + 1;
+ s32 i = 0;
+
+ /* Get the FW semaphore. */
+ for (i = 0; i < timeout; i++) {
+ swsm = rd32(E1000_SWSM);
+ wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
+
+ /* Semaphore acquired if bit latched */
+ if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI)
+ break;
+
+ udelay(50);
+ }
+
+ if (i == timeout) {
+ /* Release semaphores */
+ igb_put_hw_semaphore(hw);
+ hw_dbg("Driver can't access the NVM\n");
+ ret_val = -E1000_ERR_NVM;
+ goto out;
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * igb_put_hw_semaphore_i210 - Release hardware semaphore
+ * @hw: pointer to the HW structure
+ *
+ * Release hardware semaphore used to access the PHY or NVM
+ **/
+static void igb_put_hw_semaphore_i210(struct e1000_hw *hw)
+{
+ u32 swsm;
+
+ swsm = rd32(E1000_SWSM);
+
+ swsm &= ~E1000_SWSM_SWESMBI;
+
+ wr32(E1000_SWSM, swsm);
+}
+
+/**
+ * igb_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register
+ * @hw: pointer to the HW structure
+ * @offset: offset of word in the Shadow Ram to read
+ * @words: number of words to read
+ * @data: word read from the Shadow Ram
+ *
+ * Reads a 16 bit word from the Shadow Ram using the EERD register.
+ * Uses necessary synchronization semaphores.
+ **/
+s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
+{
+ s32 status = E1000_SUCCESS;
+ u16 i, count;
+
+ /* We cannot hold synchronization semaphores for too long,
+ * because of forceful takeover procedure. However it is more efficient
+ * to read in bursts than synchronizing access for each word. */
+ for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
+ count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
+ E1000_EERD_EEWR_MAX_COUNT : (words - i);
+ if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
+ status = igb_read_nvm_eerd(hw, offset, count,
+ data + i);
+ hw->nvm.ops.release(hw);
+ } else {
+ status = E1000_ERR_SWFW_SYNC;
+ }
+
+ if (status != E1000_SUCCESS)
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR
+ * @hw: pointer to the HW structure
+ * @offset: offset within the Shadow RAM to be written to
+ * @words: number of words to write
+ * @data: 16 bit word(s) to be written to the Shadow RAM
+ *
+ * Writes data to Shadow RAM at offset using EEWR register.
+ *
+ * If e1000_update_nvm_checksum is not called after this function , the
+ * data will not be committed to FLASH and also Shadow RAM will most likely
+ * contain an invalid checksum.
+ *
+ * If error code is returned, data and Shadow RAM may be inconsistent - buffer
+ * partially written.
+ **/
+s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
+{
+ s32 status = E1000_SUCCESS;
+ u16 i, count;
+
+ /* We cannot hold synchronization semaphores for too long,
+ * because of forceful takeover procedure. However it is more efficient
+ * to write in bursts than synchronizing access for each word. */
+ for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
+ count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
+ E1000_EERD_EEWR_MAX_COUNT : (words - i);
+ if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
+ status = igb_write_nvm_srwr(hw, offset, count,
+ data + i);
+ hw->nvm.ops.release(hw);
+ } else {
+ status = E1000_ERR_SWFW_SYNC;
+ }
+
+ if (status != E1000_SUCCESS)
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * igb_write_nvm_srwr - Write to Shadow Ram using EEWR
+ * @hw: pointer to the HW structure
+ * @offset: offset within the Shadow Ram to be written to
+ * @words: number of words to write
+ * @data: 16 bit word(s) to be written to the Shadow Ram
+ *
+ * Writes data to Shadow Ram at offset using EEWR register.
+ *
+ * If igb_update_nvm_checksum is not called after this function , the
+ * Shadow Ram will most likely contain an invalid checksum.
+ **/
+static s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
+{
+ struct e1000_nvm_info *nvm = &hw->nvm;
+ u32 i, k, eewr = 0;
+ u32 attempts = 100000;
+ s32 ret_val = E1000_SUCCESS;
+
+ /*
+ * A check for invalid values: offset too large, too many words,
+ * too many words for the offset, and not enough words.
+ */
+ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
+ (words == 0)) {
+ hw_dbg("nvm parameter(s) out of bounds\n");
+ ret_val = -E1000_ERR_NVM;
+ goto out;
+ }
+
+ for (i = 0; i < words; i++) {
+ eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) |
+ (data[i] << E1000_NVM_RW_REG_DATA) |
+ E1000_NVM_RW_REG_START;
+
+ wr32(E1000_SRWR, eewr);
+
+ for (k = 0; k < attempts; k++) {
+ if (E1000_NVM_RW_REG_DONE &
+ rd32(E1000_SRWR)) {
+ ret_val = E1000_SUCCESS;
+ break;
+ }
+ udelay(5);
+ }
+
+ if (ret_val != E1000_SUCCESS) {
+ hw_dbg("Shadow RAM write EEWR timed out\n");
+ break;
+ }
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * igb_read_nvm_i211 - Read NVM wrapper function for I211
+ * @hw: pointer to the HW structure
+ * @address: the word address (aka eeprom offset) to read
+ * @data: pointer to the data read
+ *
+ * Wrapper function to return data formerly found in the NVM.
+ **/
+s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
+{
+ s32 ret_val = E1000_SUCCESS;
+
+ /* Only the MAC addr is required to be present in the iNVM */
+ switch (offset) {
+ case NVM_MAC_ADDR:
+ ret_val = igb_read_invm_i211(hw, offset, &data[0]);
+ ret_val |= igb_read_invm_i211(hw, offset+1, &data[1]);
+ ret_val |= igb_read_invm_i211(hw, offset+2, &data[2]);
+ if (ret_val != E1000_SUCCESS)
+ hw_dbg("MAC Addr not found in iNVM\n");
+ break;
+ case NVM_ID_LED_SETTINGS:
+ case NVM_INIT_CTRL_2:
+ case NVM_INIT_CTRL_4:
+ case NVM_LED_1_CFG:
+ case NVM_LED_0_2_CFG:
+ igb_read_invm_i211(hw, offset, data);
+ break;
+ case NVM_COMPAT:
+ *data = ID_LED_DEFAULT_I210;
+ break;
+ case NVM_SUB_DEV_ID:
+ *data = hw->subsystem_device_id;
+ break;
+ case NVM_SUB_VEN_ID:
+ *data = hw->subsystem_vendor_id;
+ break;
+ case NVM_DEV_ID:
+ *data = hw->device_id;
+ break;
+ case NVM_VEN_ID:
+ *data = hw->vendor_id;
+ break;
+ default:
+ hw_dbg("NVM word 0x%02x is not mapped.\n", offset);
+ *data = NVM_RESERVED_WORD;
+ break;
+ }
+ return ret_val;
+}
+
+/**
+ * igb_read_invm_i211 - Reads OTP
+ * @hw: pointer to the HW structure
+ * @address: the word address (aka eeprom offset) to read
+ * @data: pointer to the data read
+ *
+ * Reads 16-bit words from the OTP. Return error when the word is not
+ * stored in OTP.
+ **/
+s32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data)
+{
+ s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
+ u32 invm_dword;
+ u16 i;
+ u8 record_type, word_address;
+
+ for (i = 0; i < E1000_INVM_SIZE; i++) {
+ invm_dword = rd32(E1000_INVM_DATA_REG(i));
+ /* Get record type */
+ record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
+ if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE)
+ break;
+ if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE)
+ i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
+ if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE)
+ i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
+ if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) {
+ word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
+ if (word_address == (u8)address) {
+ *data = INVM_DWORD_TO_WORD_DATA(invm_dword);
+ hw_dbg("Read INVM Word 0x%02x = %x",
+ address, *data);
+ status = E1000_SUCCESS;
+ break;
+ }
+ }
+ }
+ if (status != E1000_SUCCESS)
+ hw_dbg("Requested word 0x%02x not found in OTP\n", address);
+ return status;
+}
+
+/**
+ * igb_validate_nvm_checksum_i210 - Validate EEPROM checksum
+ * @hw: pointer to the HW structure
+ *
+ * Calculates the EEPROM checksum by reading/adding each word of the EEPROM
+ * and then verifies that the sum of the EEPROM is equal to 0xBABA.
+ **/
+s32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw)
+{
+ s32 status = E1000_SUCCESS;
+ s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *);
+
+ if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
+
+ /*
+ * Replace the read function with semaphore grabbing with
+ * the one that skips this for a while.
+ * We have semaphore taken already here.
+ */
+ read_op_ptr = hw->nvm.ops.read;
+ hw->nvm.ops.read = igb_read_nvm_eerd;
+
+ status = igb_validate_nvm_checksum(hw);
+
+ /* Revert original read operation. */
+ hw->nvm.ops.read = read_op_ptr;
+
+ hw->nvm.ops.release(hw);
+ } else {
+ status = E1000_ERR_SWFW_SYNC;
+ }
+
+ return status;
+}
+
+
+/**
+ * igb_update_nvm_checksum_i210 - Update EEPROM checksum
+ * @hw: pointer to the HW structure
+ *
+ * Updates the EEPROM checksum by reading/adding each word of the EEPROM
+ * up to the checksum. Then calculates the EEPROM checksum and writes the
+ * value to the EEPROM. Next commit EEPROM data onto the Flash.
+ **/
+s32 igb_update_nvm_checksum_i210(struct e1000_hw *hw)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u16 checksum = 0;
+ u16 i, nvm_data;
+
+ /*
+ * Read the first word from the EEPROM. If this times out or fails, do
+ * not continue or we could be in for a very long wait while every
+ * EEPROM read fails
+ */
+ ret_val = igb_read_nvm_eerd(hw, 0, 1, &nvm_data);
+ if (ret_val != E1000_SUCCESS) {
+ hw_dbg("EEPROM read failed\n");
+ goto out;
+ }
+
+ if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
+ /*
+ * Do not use hw->nvm.ops.write, hw->nvm.ops.read
+ * because we do not want to take the synchronization
+ * semaphores twice here.
+ */
+
+ for (i = 0; i < NVM_CHECKSUM_REG; i++) {
+ ret_val = igb_read_nvm_eerd(hw, i, 1, &nvm_data);
+ if (ret_val) {
+ hw->nvm.ops.release(hw);
+ hw_dbg("NVM Read Error while updating checksum.\n");
+ goto out;
+ }
+ checksum += nvm_data;
+ }
+ checksum = (u16) NVM_SUM - checksum;
+ ret_val = igb_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1,
+ &checksum);
+ if (ret_val != E1000_SUCCESS) {
+ hw->nvm.ops.release(hw);
+ hw_dbg("NVM Write Error while updating checksum.\n");
+ goto out;
+ }
+
+ hw->nvm.ops.release(hw);
+
+ ret_val = igb_update_flash_i210(hw);
+ } else {
+ ret_val = -E1000_ERR_SWFW_SYNC;
+ }
+out:
+ return ret_val;
+}
+
+/**
+ * igb_update_flash_i210 - Commit EEPROM to the flash
+ * @hw: pointer to the HW structure
+ *
+ **/
+s32 igb_update_flash_i210(struct e1000_hw *hw)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u32 flup;
+
+ ret_val = igb_pool_flash_update_done_i210(hw);
+ if (ret_val == -E1000_ERR_NVM) {
+ hw_dbg("Flash update time out\n");
+ goto out;
+ }
+
+ flup = rd32(E1000_EECD) | E1000_EECD_FLUPD_I210;
+ wr32(E1000_EECD, flup);
+
+ ret_val = igb_pool_flash_update_done_i210(hw);
+ if (ret_val == E1000_SUCCESS)
+ hw_dbg("Flash update complete\n");
+ else
+ hw_dbg("Flash update time out\n");
+
+out:
+ return ret_val;
+}
+
+/**
+ * igb_pool_flash_update_done_i210 - Pool FLUDONE status.
+ * @hw: pointer to the HW structure
+ *
+ **/
+s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw)
+{
+ s32 ret_val = -E1000_ERR_NVM;
+ u32 i, reg;
+
+ for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
+ reg = rd32(E1000_EECD);
+ if (reg & E1000_EECD_FLUDONE_I210) {
+ ret_val = E1000_SUCCESS;
+ break;
+ }
+ udelay(5);
+ }
+
+ return ret_val;
+}
+
+/**
+ * igb_valid_led_default_i210 - Verify a valid default LED config
+ * @hw: pointer to the HW structure
+ * @data: pointer to the NVM (EEPROM)
+ *
+ * Read the EEPROM for the current default LED configuration. If the
+ * LED configuration is not valid, set to a valid LED configuration.
+ **/
+s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data)
+{
+ s32 ret_val;
+
+ ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
+ if (ret_val) {
+ hw_dbg("NVM Read Error\n");
+ goto out;
+ }
+
+ if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
+ switch (hw->phy.media_type) {
+ case e1000_media_type_internal_serdes:
+ *data = ID_LED_DEFAULT_I210_SERDES;
+ break;
+ case e1000_media_type_copper:
+ default:
+ *data = ID_LED_DEFAULT_I210;
+ break;
+ }
+ }
+out:
+ return ret_val;
+}
diff --git a/drivers/net/igb/e1000_i210.h b/drivers/net/igb/e1000_i210.h
new file mode 100644
index 000000000000..5dc2bd3f50bc
--- /dev/null
+++ b/drivers/net/igb/e1000_i210.h
@@ -0,0 +1,76 @@
+/*******************************************************************************
+
+ Intel(R) Gigabit Ethernet Linux driver
+ Copyright(c) 2007-2012 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope 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.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#ifndef _E1000_I210_H_
+#define _E1000_I210_H_
+
+extern s32 igb_update_flash_i210(struct e1000_hw *hw);
+extern s32 igb_update_nvm_checksum_i210(struct e1000_hw *hw);
+extern s32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw);
+extern s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset,
+ u16 words, u16 *data);
+extern s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset,
+ u16 words, u16 *data);
+extern s32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data);
+extern s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
+extern void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
+extern s32 igb_acquire_nvm_i210(struct e1000_hw *hw);
+extern void igb_release_nvm_i210(struct e1000_hw *hw);
+extern s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data);
+extern s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data);
+
+#define E1000_STM_OPCODE 0xDB00
+#define E1000_EEPROM_FLASH_SIZE_WORD 0x11
+
+#define INVM_DWORD_TO_RECORD_TYPE(invm_dword) \
+ (u8)((invm_dword) & 0x7)
+#define INVM_DWORD_TO_WORD_ADDRESS(invm_dword) \
+ (u8)(((invm_dword) & 0x0000FE00) >> 9)
+#define INVM_DWORD_TO_WORD_DATA(invm_dword) \
+ (u16)(((invm_dword) & 0xFFFF0000) >> 16)
+
+enum E1000_INVM_STRUCTURE_TYPE {
+ E1000_INVM_UNINITIALIZED_STRUCTURE = 0x00,
+ E1000_INVM_WORD_AUTOLOAD_STRUCTURE = 0x01,
+ E1000_INVM_CSR_AUTOLOAD_STRUCTURE = 0x02,
+ E1000_INVM_PHY_REGISTER_AUTOLOAD_STRUCTURE = 0x03,
+ E1000_INVM_RSA_KEY_SHA256_STRUCTURE = 0x04,
+ E1000_INVM_INVALIDATED_STRUCTURE = 0x0F,
+};
+
+#define E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS 8
+#define E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS 1
+
+#define ID_LED_DEFAULT_I210 ((ID_LED_OFF1_ON2 << 8) | \
+ (ID_LED_OFF1_OFF2 << 4) | \
+ (ID_LED_DEF1_DEF2))
+#define ID_LED_DEFAULT_I210_SERDES ((ID_LED_DEF1_DEF2 << 8) | \
+ (ID_LED_DEF1_DEF2 << 4) | \
+ (ID_LED_DEF1_DEF2))
+
+#endif
diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c
index 2b5ef761d2ab..c3ee7b21ab4e 100644
--- a/drivers/net/igb/e1000_mac.c
+++ b/drivers/net/igb/e1000_mac.c
@@ -596,6 +596,7 @@ s32 igb_setup_link(struct e1000_hw *hw)
ret_val = igb_set_fc_watermarks(hw);
out:
+
return ret_val;
}
diff --git a/drivers/net/igb/e1000_nvm.c b/drivers/net/igb/e1000_nvm.c
index 40407124e722..38047a584605 100644
--- a/drivers/net/igb/e1000_nvm.c
+++ b/drivers/net/igb/e1000_nvm.c
@@ -710,4 +710,3 @@ s32 igb_update_nvm_checksum(struct e1000_hw *hw)
out:
return ret_val;
}
-
diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c
index e662554c62d6..d9e0ec065cf7 100644
--- a/drivers/net/igb/e1000_phy.c
+++ b/drivers/net/igb/e1000_phy.c
@@ -35,6 +35,7 @@ static s32 igb_phy_setup_autoneg(struct e1000_hw *hw);
static void igb_phy_force_speed_duplex_setup(struct e1000_hw *hw,
u16 *phy_ctrl);
static s32 igb_wait_autoneg(struct e1000_hw *hw);
+static s32 igb_set_master_slave_mode(struct e1000_hw *hw);
/* Cable length tables */
static const u16 e1000_m88_cable_length_table[] =
@@ -564,6 +565,11 @@ s32 igb_copper_link_setup_m88(struct e1000_hw *hw)
hw_dbg("Error committing the PHY changes\n");
goto out;
}
+ if (phy->type == e1000_phy_i210) {
+ ret_val = igb_set_master_slave_mode(hw);
+ if (ret_val)
+ return ret_val;
+ }
out:
return ret_val;
@@ -1207,12 +1213,22 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw)
goto out;
if (!link) {
- if (hw->phy.type != e1000_phy_m88 ||
- hw->phy.id == I347AT4_E_PHY_ID ||
- hw->phy.id == M88E1112_E_PHY_ID) {
+ bool reset_dsp = true;
+
+ switch (hw->phy.id) {
+ case I347AT4_E_PHY_ID:
+ case M88E1112_E_PHY_ID:
+ case I210_I_PHY_ID:
+ reset_dsp = false;
+ break;
+ default:
+ if (hw->phy.type != e1000_phy_m88)
+ reset_dsp = false;
+ break;
+ }
+ if (!reset_dsp)
hw_dbg("Link taking longer than expected.\n");
- } else {
-
+ else {
/*
* We didn't get link.
* Reset the DSP and cross our fingers.
@@ -1237,7 +1253,8 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw)
if (hw->phy.type != e1000_phy_m88 ||
hw->phy.id == I347AT4_E_PHY_ID ||
- hw->phy.id == M88E1112_E_PHY_ID)
+ hw->phy.id == M88E1112_E_PHY_ID ||
+ hw->phy.id == I210_I_PHY_ID)
goto out;
ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
@@ -1435,6 +1452,7 @@ s32 igb_check_downshift(struct e1000_hw *hw)
u16 phy_data, offset, mask;
switch (phy->type) {
+ case e1000_phy_i210:
case e1000_phy_m88:
case e1000_phy_gg82563:
offset = M88E1000_PHY_SPEC_STATUS;
@@ -1470,7 +1488,7 @@ out:
*
* Polarity is determined based on the PHY specific status register.
**/
-static s32 igb_check_polarity_m88(struct e1000_hw *hw)
+s32 igb_check_polarity_m88(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
s32 ret_val;
@@ -1659,6 +1677,7 @@ s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw)
u16 phy_data, phy_data2, index, default_page, is_cm;
switch (hw->phy.id) {
+ case I210_I_PHY_ID:
case I347AT4_E_PHY_ID:
/* Remember the original page select and set it to 7 */
ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
@@ -2123,10 +2142,16 @@ s32 igb_phy_init_script_igp3(struct e1000_hw *hw)
void igb_power_up_phy_copper(struct e1000_hw *hw)
{
u16 mii_reg = 0;
+ u16 power_reg = 0;
/* The PHY will retain its settings across a power down/up cycle */
hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
mii_reg &= ~MII_CR_POWER_DOWN;
+ if (hw->phy.type == e1000_phy_i210) {
+ hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg);
+ power_reg &= ~GS40G_CS_POWER_DOWN;
+ hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg);
+ }
hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
}
@@ -2140,10 +2165,18 @@ void igb_power_up_phy_copper(struct e1000_hw *hw)
void igb_power_down_phy_copper(struct e1000_hw *hw)
{
u16 mii_reg = 0;
+ u16 power_reg = 0;
/* The PHY will retain its settings across a power down/up cycle */
hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
mii_reg |= MII_CR_POWER_DOWN;
+
+ /* i210 Phy requires an additional bit for power up/down */
+ if (hw->phy.type == e1000_phy_i210) {
+ hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg);
+ power_reg |= GS40G_CS_POWER_DOWN;
+ hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg);
+ }
hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
msleep(1);
}
@@ -2339,3 +2372,103 @@ s32 igb_get_cable_length_82580(struct e1000_hw *hw)
out:
return ret_val;
}
+
+/**
+ * igb_write_phy_reg_gs40g - Write GS40G PHY register
+ * @hw: pointer to the HW structure
+ * @offset: lower half is register offset to write to
+ * upper half is page to use.
+ * @data: data to write at register offset
+ *
+ * Acquires semaphore, if necessary, then writes the data to PHY register
+ * at the offset. Release any acquired semaphores before exiting.
+ **/
+s32 igb_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ s32 ret_val;
+ u16 page = offset >> GS40G_PAGE_SHIFT;
+
+ offset = offset & GS40G_OFFSET_MASK;
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = igb_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
+ if (ret_val)
+ goto release;
+ ret_val = igb_write_phy_reg_mdic(hw, offset, data);
+
+release:
+ hw->phy.ops.release(hw);
+ return ret_val;
+}
+
+/**
+ * igb_read_phy_reg_gs40g - Read GS40G PHY register
+ * @hw: pointer to the HW structure
+ * @offset: lower half is register offset to read to
+ * upper half is page to use.
+ * @data: data to read at register offset
+ *
+ * Acquires semaphore, if necessary, then reads the data in the PHY register
+ * at the offset. Release any acquired semaphores before exiting.
+ **/
+s32 igb_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ s32 ret_val;
+ u16 page = offset >> GS40G_PAGE_SHIFT;
+
+ offset = offset & GS40G_OFFSET_MASK;
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = igb_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
+ if (ret_val)
+ goto release;
+ ret_val = igb_read_phy_reg_mdic(hw, offset, data);
+
+release:
+ hw->phy.ops.release(hw);
+ return ret_val;
+}
+
+/**
+ * igb_set_master_slave_mode - Setup PHY for Master/slave mode
+ * @hw: pointer to the HW structure
+ *
+ * Sets up Master/slave mode
+ **/
+static s32 igb_set_master_slave_mode(struct e1000_hw *hw)
+{
+ s32 ret_val;
+ u16 phy_data;
+
+ /* Resolve Master/Slave mode */
+ ret_val = hw->phy.ops.read_reg(hw, PHY_1000T_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* load defaults for future use */
+ hw->phy.original_ms_type = (phy_data & CR_1000T_MS_ENABLE) ?
+ ((phy_data & CR_1000T_MS_VALUE) ?
+ e1000_ms_force_master :
+ e1000_ms_force_slave) : e1000_ms_auto;
+
+ switch (hw->phy.ms_type) {
+ case e1000_ms_force_master:
+ phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
+ break;
+ case e1000_ms_force_slave:
+ phy_data |= CR_1000T_MS_ENABLE;
+ phy_data &= ~(CR_1000T_MS_VALUE);
+ break;
+ case e1000_ms_auto:
+ phy_data &= ~CR_1000T_MS_ENABLE;
+ /* fall-through */
+ default:
+ break;
+ }
+
+ return hw->phy.ops.write_reg(hw, PHY_1000T_CTRL, phy_data);
+}
diff --git a/drivers/net/igb/e1000_phy.h b/drivers/net/igb/e1000_phy.h
index 8510797b9d81..3b813a8bdf1a 100644
--- a/drivers/net/igb/e1000_phy.h
+++ b/drivers/net/igb/e1000_phy.h
@@ -73,6 +73,9 @@ s32 igb_copper_link_setup_82580(struct e1000_hw *hw);
s32 igb_get_phy_info_82580(struct e1000_hw *hw);
s32 igb_phy_force_speed_duplex_82580(struct e1000_hw *hw);
s32 igb_get_cable_length_82580(struct e1000_hw *hw);
+s32 igb_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data);
+s32 igb_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data);
+s32 igb_check_polarity_m88(struct e1000_hw *hw);
/* IGP01E1000 Specific Registers */
#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */
@@ -114,6 +117,13 @@ s32 igb_get_cable_length_82580(struct e1000_hw *hw);
/* I82580 PHY Diagnostics Status */
#define I82580_DSTATUS_CABLE_LENGTH 0x03FC
#define I82580_DSTATUS_CABLE_LENGTH_SHIFT 2
+
+/* 82580 PHY Power Management */
+#define E1000_82580_PHY_POWER_MGMT 0xE14
+#define E1000_82580_PM_SPD 0x0001 /* Smart Power Down */
+#define E1000_82580_PM_D0_LPLU 0x0002 /* For D0a states */
+#define E1000_82580_PM_D3_LPLU 0x0004 /* For all other states */
+
/* Enable flexible speed on link-up */
#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */
#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */
@@ -133,4 +143,16 @@ s32 igb_get_cable_length_82580(struct e1000_hw *hw);
#define E1000_CABLE_LENGTH_UNDEFINED 0xFF
+/* GS40G - I210 PHY defines */
+#define GS40G_PAGE_SELECT 0x16
+#define GS40G_PAGE_SHIFT 16
+#define GS40G_OFFSET_MASK 0xFFFF
+#define GS40G_PAGE_2 0x20000
+#define GS40G_MAC_REG2 0x15
+#define GS40G_MAC_LB 0x4140
+#define GS40G_MAC_SPEED_1G 0X0006
+#define GS40G_COPPER_SPEC 0x0010
+#define GS40G_CS_POWER_DOWN 0x0002
+#define GS40G_LINE_LB 0x4000
+
#endif
diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h
index 0990f6d860c7..bb62cf641318 100644
--- a/drivers/net/igb/e1000_regs.h
+++ b/drivers/net/igb/e1000_regs.h
@@ -351,4 +351,18 @@
#define E1000_O2BGPTC 0x08FE4 /* OS2BMC packets received by BMC */
#define E1000_O2BSPC 0x0415C /* OS2BMC packets transmitted by host */
+#define E1000_SRWR 0x12018 /* Shadow Ram Write Register - RW */
+#define E1000_I210_FLMNGCTL 0x12038
+#define E1000_I210_FLMNGDATA 0x1203C
+#define E1000_I210_FLMNGCNT 0x12040
+
+#define E1000_I210_FLSWCTL 0x12048
+#define E1000_I210_FLSWDATA 0x1204C
+#define E1000_I210_FLSWCNT 0x12050
+
+#define E1000_I210_FLA 0x1201C
+
+#define E1000_INVM_DATA_REG(_n) (0x12120 + 4*(_n))
+#define E1000_INVM_SIZE 64 /* Number of INVM Data Registers */
+
#endif
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index 265e151b66c4..111236008d16 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -61,11 +61,14 @@ struct igb_adapter;
#define MAX_Q_VECTORS 8
/* Transmit and receive queues */
-#define IGB_MAX_RX_QUEUES (adapter->vfs_allocated_count ? 2 : \
- (hw->mac.type > e1000_82575 ? 8 : 4))
+#define IGB_MAX_RX_QUEUES ((adapter->vfs_allocated_count ? 2 : \
+ (hw->mac.type > e1000_82575 ? 8 : 4)))
+#define IGB_MAX_RX_QUEUES_I210 4
+#define IGB_MAX_RX_QUEUES_I211 2
#define IGB_ABS_MAX_TX_QUEUES 8
-#define IGB_MAX_TX_QUEUES IGB_MAX_RX_QUEUES
-
+#define IGB_MAX_TX_QUEUES 16
+#define IGB_MAX_TX_QUEUES_I210 4
+#define IGB_MAX_TX_QUEUES_I211 2
#define IGB_MAX_VF_MC_ENTRIES 30
#define IGB_MAX_VF_FUNCTIONS 8
#define IGB_MAX_VFTA_ENTRIES 128
@@ -227,8 +230,9 @@ struct igb_ring {
};
};
-#define IGB_RING_FLAG_RX_CSUM 0x00000001 /* RX CSUM enabled */
-#define IGB_RING_FLAG_RX_SCTP_CSUM 0x00000002 /* SCTP CSUM offload enabled */
+#define IGB_RING_FLAG_RX_CSUM 0x00000001 /* RX CSUM enabled */
+#define IGB_RING_FLAG_RX_SCTP_CSUM 0x00000002 /* SCTP CSUM offload enabled */
+#define IGB_RING_FLAG_RX_LB_VLAN_BSWAP 0x00000003
#define IGB_RING_FLAG_TX_CTX_IDX 0x00000001 /* HW requires context index */
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index 414b0225be89..c9e3d65bd71d 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -549,10 +549,13 @@ static void igb_get_regs(struct net_device *netdev,
regs_buff[548] = rd32(E1000_TDFT);
regs_buff[549] = rd32(E1000_TDFHS);
regs_buff[550] = rd32(E1000_TDFPC);
- regs_buff[551] = adapter->stats.o2bgptc;
- regs_buff[552] = adapter->stats.b2ospc;
- regs_buff[553] = adapter->stats.o2bspc;
- regs_buff[554] = adapter->stats.b2ogprc;
+
+ if (hw->mac.type > e1000_82580) {
+ regs_buff[551] = adapter->stats.o2bgptc;
+ regs_buff[552] = adapter->stats.b2ospc;
+ regs_buff[553] = adapter->stats.o2bspc;
+ regs_buff[554] = adapter->stats.b2ogprc;
+ }
}
static int igb_get_eeprom_len(struct net_device *netdev)
@@ -621,6 +624,9 @@ static int igb_set_eeprom(struct net_device *netdev,
if (eeprom->len == 0)
return -EOPNOTSUPP;
+ if (hw->mac.type == e1000_i211)
+ return -EOPNOTSUPP;
+
if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
return -EFAULT;
@@ -855,6 +861,36 @@ struct igb_reg_test {
#define TABLE64_TEST_LO 5
#define TABLE64_TEST_HI 6
+/* i210 reg test */
+static struct igb_reg_test reg_test_i210[] = {
+ { E1000_FCAL, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+ { E1000_FCAH, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
+ { E1000_FCT, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
+ { E1000_RDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
+ { E1000_RDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+ { E1000_RDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
+ /* RDH is read-only for i210, only test RDT. */
+ { E1000_RDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
+ { E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 },
+ { E1000_FCTTV, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
+ { E1000_TIPG, 0x100, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF },
+ { E1000_TDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
+ { E1000_TDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+ { E1000_TDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
+ { E1000_TDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
+ { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
+ { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0x003FFFFB },
+ { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0xFFFFFFFF },
+ { E1000_TCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
+ { E1000_RA, 0, 16, TABLE64_TEST_LO,
+ 0xFFFFFFFF, 0xFFFFFFFF },
+ { E1000_RA, 0, 16, TABLE64_TEST_HI,
+ 0x900FFFFF, 0xFFFFFFFF },
+ { E1000_MTA, 0, 128, TABLE32_TEST,
+ 0xFFFFFFFF, 0xFFFFFFFF },
+ { 0, 0, 0, 0, 0 }
+};
+
/* i350 reg test */
static struct igb_reg_test reg_test_i350[] = {
{ E1000_FCAL, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
@@ -1077,6 +1113,11 @@ static int igb_reg_test(struct igb_adapter *adapter, u64 *data)
test = reg_test_i350;
toggle = 0x7FEFF3FF;
break;
+ case e1000_i210:
+ case e1000_i211:
+ test = reg_test_i210;
+ toggle = 0x7FEFF3FF;
+ break;
case e1000_82580:
test = reg_test_82580;
toggle = 0x7FEFF3FF;
@@ -1158,23 +1199,13 @@ static int igb_reg_test(struct igb_adapter *adapter, u64 *data)
static int igb_eeprom_test(struct igb_adapter *adapter, u64 *data)
{
- u16 temp;
- u16 checksum = 0;
- u16 i;
-
*data = 0;
- /* Read and add up the contents of the EEPROM */
- for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
- if ((adapter->hw.nvm.ops.read(&adapter->hw, i, 1, &temp)) < 0) {
- *data = 1;
- break;
- }
- checksum += temp;
- }
- /* If Checksum is not Correct return error else test passed */
- if ((checksum != (u16) NVM_SUM) && !(*data))
- *data = 2;
+ /* Validate eeprom on all parts but i211 */
+ if (adapter->hw.mac.type != e1000_i211) {
+ if (adapter->hw.nvm.ops.validate(&adapter->hw) < 0)
+ *data = 2;
+ }
return *data;
}
@@ -1240,6 +1271,8 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data)
ics_mask = 0x77DCFED5;
break;
case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
ics_mask = 0x77DCFED5;
break;
default:
@@ -1407,23 +1440,35 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
u32 ctrl_reg = 0;
+ u16 phy_reg = 0;
hw->mac.autoneg = false;
- if (hw->phy.type == e1000_phy_m88) {
+ switch (hw->phy.type) {
+ case e1000_phy_m88:
/* Auto-MDI/MDIX Off */
igb_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, 0x0808);
/* reset to update Auto-MDI/MDIX */
igb_write_phy_reg(hw, PHY_CONTROL, 0x9140);
/* autoneg off */
igb_write_phy_reg(hw, PHY_CONTROL, 0x8140);
- } else if (hw->phy.type == e1000_phy_82580) {
+ break;
+ case e1000_phy_82580:
/* enable MII loopback */
igb_write_phy_reg(hw, I82580_PHY_LBK_CTRL, 0x8041);
+ break;
+ case e1000_phy_i210:
+ /* set loopback speed in PHY */
+ igb_read_phy_reg(hw, (GS40G_PAGE_SELECT & GS40G_PAGE_2),
+ &phy_reg);
+ phy_reg |= GS40G_MAC_SPEED_1G;
+ igb_write_phy_reg(hw, (GS40G_PAGE_SELECT & GS40G_PAGE_2),
+ phy_reg);
+ ctrl_reg = rd32(E1000_CTRL_EXT);
+ default:
+ break;
}
- ctrl_reg = rd32(E1000_CTRL);
-
/* force 1000, set loopback */
igb_write_phy_reg(hw, PHY_CONTROL, 0x4140);
@@ -1436,7 +1481,7 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter)
E1000_CTRL_FD | /* Force Duplex to FULL */
E1000_CTRL_SLU); /* Set link up enable bit */
- if (hw->phy.type == e1000_phy_m88)
+ if ((hw->phy.type == e1000_phy_m88) || (hw->phy.type == e1000_phy_i210))
ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
wr32(E1000_CTRL, ctrl_reg);
@@ -1444,7 +1489,7 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter)
/* Disable the receiver on the PHY so when a cable is plugged in, the
* PHY does not begin to autoneg when a cable is reconnected to the NIC.
*/
- if (hw->phy.type == e1000_phy_m88)
+ if ((hw->phy.type == e1000_phy_m88) || (hw->phy.type == e1000_phy_i210))
igb_phy_disable_receiver(adapter);
udelay(500);
@@ -1703,6 +1748,14 @@ static int igb_loopback_test(struct igb_adapter *adapter, u64 *data)
*data = 0;
goto out;
}
+ if ((adapter->hw.mac.type == e1000_i210)
+ || (adapter->hw.mac.type == e1000_i210)) {
+ dev_err(&adapter->pdev->dev,
+ "Loopback test not supported "
+ "on this part at this time.\n");
+ *data = 0;
+ goto out;
+ }
*data = igb_setup_desc_rings(adapter);
if (*data)
goto out;
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 40d4c405fd7e..220183dfe33f 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -68,6 +68,11 @@ static const struct e1000_info *igb_info_tbl[] = {
};
static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = {
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I211_COPPER), board_82575 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER), board_82575 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_FIBER), board_82575 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SERDES), board_82575 },
+ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SGMII), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_COPPER), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_FIBER), board_82575 },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_SERDES), board_82575 },
@@ -647,6 +652,8 @@ static void igb_cache_ring_register(struct igb_adapter *adapter)
case e1000_82575:
case e1000_82580:
case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
default:
for (; i < adapter->num_rx_queues; i++)
adapter->rx_ring[i]->reg_idx = rbase_offset + i;
@@ -711,6 +718,14 @@ static int igb_alloc_queues(struct igb_adapter *adapter)
/* set flag indicating ring supports SCTP checksum offload */
if (adapter->hw.mac.type >= e1000_82576)
ring->flags |= IGB_RING_FLAG_RX_SCTP_CSUM;
+
+ /*
+ * On i350, i210, and i211, loopback VLAN packets
+ * have the tag byte-swapped.
+ * */
+ if (adapter->hw.mac.type >= e1000_i350)
+ ring->flags |= IGB_RING_FLAG_RX_LB_VLAN_BSWAP;
+
adapter->rx_ring[i] = ring;
}
@@ -791,6 +806,8 @@ static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector)
break;
case e1000_82580:
case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
/* 82580 uses the same table-based approach as 82576 but has fewer
entries as a result we carry over for queues greater than 4. */
if (rx_queue > IGB_N0_QUEUE) {
@@ -872,6 +889,8 @@ static void igb_configure_msix(struct igb_adapter *adapter)
case e1000_82576:
case e1000_82580:
case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
/* Turn on MSI-X capability first, or our settings
* won't stick. And it will take days to debug. */
wr32(E1000_GPIE, E1000_GPIE_MSIX_MODE |
@@ -1018,6 +1037,11 @@ static int igb_set_interrupt_capability(struct igb_adapter *adapter)
if (!(adapter->flags & IGB_FLAG_QUEUE_PAIRS))
numvecs += adapter->num_tx_queues;
+ /* i210 and i211 can only have 4 MSIX vectors for rx/tx queues. */
+ if ((adapter->hw.mac.type == e1000_i210)
+ || (adapter->hw.mac.type == e1000_i211))
+ numvecs = 4;
+
/* store the number of vectors reserved for queues */
adapter->num_q_vectors = numvecs;
@@ -1025,6 +1049,7 @@ static int igb_set_interrupt_capability(struct igb_adapter *adapter)
numvecs++;
adapter->msix_entries = kcalloc(numvecs, sizeof(struct msix_entry),
GFP_KERNEL);
+
if (!adapter->msix_entries)
goto msi_only;
@@ -1599,6 +1624,8 @@ void igb_reset(struct igb_adapter *adapter)
pba &= E1000_RXPBS_SIZE_MASK_82576;
break;
case e1000_82575:
+ case e1000_i210:
+ case e1000_i211:
default:
pba = E1000_PBA_34K;
break;
@@ -1839,7 +1866,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
*/
if (pdev->is_virtfn) {
WARN(1, KERN_ERR "%s (%hx:%hx) should not be a VF!\n",
- pci_name(pdev), pdev->vendor, pdev->device);
+ pci_name(pdev), pdev->vendor, pdev->device);
return -EINVAL;
}
@@ -1979,17 +2006,35 @@ static int __devinit igb_probe(struct pci_dev *pdev,
* known good starting state */
hw->mac.ops.reset_hw(hw);
- /* make sure the NVM is good */
- if (hw->nvm.ops.validate(hw) < 0) {
- dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n");
- err = -EIO;
- goto err_eeprom;
+#ifndef CONFIG_MACH_APALIS_T30
+/* Hack: skip NVM validation on Apalis T30 for now */
+ /*
+ * make sure the NVM is good , i211 parts have special NVM that
+ * doesn't contain a checksum
+ */
+ if (hw->mac.type != e1000_i211) {
+ if (hw->nvm.ops.validate(hw) < 0) {
+ dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n");
+ err = -EIO;
+ goto err_eeprom;
+ }
}
+#endif /* CONFIG_MACH_APALIS_T30 */
/* copy the MAC address out of the NVM */
if (hw->mac.ops.read_mac_addr(hw))
dev_err(&pdev->dev, "NVM Read Error\n");
+#ifdef CONFIG_MACH_APALIS_T30
+ /* Hack: hard-code MAC address on Apalis T30 for now */
+ hw->mac.addr[0] = 0x00;
+ hw->mac.addr[1] = 0x0e;
+ hw->mac.addr[2] = 0xc6;
+ hw->mac.addr[3] = 0x87;
+ hw->mac.addr[4] = 0x72;
+ hw->mac.addr[5] = 0x01;
+#endif /* CONFIG_MACH_APALIS_T30 */
+
memcpy(netdev->dev_addr, hw->mac.addr, netdev->addr_len);
memcpy(netdev->perm_addr, hw->mac.addr, netdev->addr_len);
@@ -2117,6 +2162,8 @@ static int __devinit igb_probe(struct pci_dev *pdev,
adapter->num_rx_queues, adapter->num_tx_queues);
switch (hw->mac.type) {
case e1000_i350:
+ case e1000_i210:
+ case e1000_i211:
igb_set_eee_i350(hw);
break;
default:
@@ -2231,11 +2278,17 @@ static void __devinit igb_probe_vfs(struct igb_adapter * adapter)
{
#ifdef CONFIG_PCI_IOV
struct pci_dev *pdev = adapter->pdev;
+ struct e1000_hw *hw = &adapter->hw;
+
+ /* Virtualization features not supported on i210 family. */
+ if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211))
+ return;
if (adapter->vfs_allocated_count) {
adapter->vf_data = kcalloc(adapter->vfs_allocated_count,
sizeof(struct vf_data_storage),
GFP_KERNEL);
+
/* if allocation failed then we do not support SR-IOV */
if (!adapter->vf_data) {
adapter->vfs_allocated_count = 0;
@@ -2409,11 +2462,28 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
} else
adapter->vfs_allocated_count = max_vfs;
break;
+ case e1000_i210:
+ case e1000_i211:
+ adapter->vfs_allocated_count = 0;
+ break;
default:
break;
}
#endif /* CONFIG_PCI_IOV */
- adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus());
+ switch (hw->mac.type) {
+ case e1000_i210:
+ adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES_I210,
+ num_online_cpus());
+ break;
+ case e1000_i211:
+ adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES_I211,
+ num_online_cpus());
+ break;
+ default:
+ adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES,
+ num_online_cpus());
+ break;
+ }
/* i350 cannot do RSS and SR-IOV at the same time */
if (hw->mac.type == e1000_i350 && adapter->vfs_allocated_count)
adapter->rss_queues = 1;
@@ -2438,7 +2508,7 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
/* Explicitly disable IRQ since the NIC can be in any state. */
igb_irq_disable(adapter);
- if (hw->mac.type == e1000_i350)
+ if (hw->mac.type >= e1000_i350)
adapter->flags &= ~IGB_FLAG_DMAC;
set_bit(__IGB_DOWN, &adapter->state);
@@ -2852,6 +2922,17 @@ static void igb_setup_mrqc(struct igb_adapter *adapter)
/* Don't need to set TUOFL or IPOFL, they default to 1 */
wr32(E1000_RXCSUM, rxcsum);
+ /*
+ * Generate RSS hash based on TCP port numbers and/or
+ * IPv4/v6 src and dst addresses since UDP cannot be
+ * hashed reliably due to IP fragmentation
+ */
+
+ mrqc = E1000_MRQC_RSS_FIELD_IPV4 |
+ E1000_MRQC_RSS_FIELD_IPV4_TCP |
+ E1000_MRQC_RSS_FIELD_IPV6 |
+ E1000_MRQC_RSS_FIELD_IPV6_TCP |
+ E1000_MRQC_RSS_FIELD_IPV6_TCP_EX;
/* If VMDq is enabled then we set the appropriate mode for that, else
* we default to RSS so that an RSS hash is calculated per packet even
@@ -2867,25 +2948,15 @@ static void igb_setup_mrqc(struct igb_adapter *adapter)
wr32(E1000_VT_CTL, vtctl);
}
if (adapter->rss_queues > 1)
- mrqc = E1000_MRQC_ENABLE_VMDQ_RSS_2Q;
+ mrqc |= E1000_MRQC_ENABLE_VMDQ_RSS_2Q;
else
- mrqc = E1000_MRQC_ENABLE_VMDQ;
+ mrqc |= E1000_MRQC_ENABLE_VMDQ;
} else {
- mrqc = E1000_MRQC_ENABLE_RSS_4Q;
+ if (hw->mac.type != e1000_i211)
+ mrqc |= E1000_MRQC_ENABLE_RSS_4Q;
}
igb_vmm_control(adapter);
- /*
- * Generate RSS hash based on TCP port numbers and/or
- * IPv4/v6 src and dst addresses since UDP cannot be
- * hashed reliably due to IP fragmentation
- */
- mrqc |= E1000_MRQC_RSS_FIELD_IPV4 |
- E1000_MRQC_RSS_FIELD_IPV4_TCP |
- E1000_MRQC_RSS_FIELD_IPV6 |
- E1000_MRQC_RSS_FIELD_IPV6_TCP |
- E1000_MRQC_RSS_FIELD_IPV6_TCP_EX;
-
wr32(E1000_MRQC, mrqc);
}
@@ -3484,7 +3555,7 @@ static void igb_set_rx_mode(struct net_device *netdev)
* we will have issues with VLAN tag stripping not being done for frames
* that are only arriving because we are the default pool
*/
- if (hw->mac.type < e1000_82576)
+ if ((hw->mac.type < e1000_82576) || (hw->mac.type > e1000_i350))
return;
vmolr |= rd32(E1000_VMOLR(vfn)) &
@@ -3581,7 +3652,7 @@ static bool igb_thermal_sensor_event(struct e1000_hw *hw, u32 event)
bool ret = false;
u32 ctrl_ext, thstat;
- /* check for thermal sensor event on i350, copper only */
+ /* check for thermal sensor event on i350 copper only */
if (hw->mac.type == e1000_i350) {
thstat = rd32(E1000_THSTAT);
ctrl_ext = rd32(E1000_CTRL_EXT);
@@ -6858,6 +6929,8 @@ static void igb_vmm_control(struct igb_adapter *adapter)
switch (hw->mac.type) {
case e1000_82575:
+ case e1000_i210:
+ case e1000_i211:
default:
/* replication is not supported for 82575 */
return;
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index 710557700095..3218f52b3a3d 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -1,8 +1,7 @@
/*
* ASIX AX8817X based USB 2.0 Ethernet Devices
- * Copyright (C) 2003-2006 David Hollis <dhollis@davehollis.com>
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
* Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
- * Copyright (C) 2006 James Painter <jamie.painter@iname.com>
* Copyright (c) 2002-2003 TiVo Inc.
*
* This program is free software; you can redistribute it and/or modify
@@ -20,11 +19,16 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-// #define DEBUG // error path messages, extra info
-// #define VERBOSE // more; success messages
+//#define DEBUG // debug messages, extra info
+#include <linux/version.h>
+//#include <linux/config.h>
+#ifdef CONFIG_USB_DEBUG
+# define DEBUG
+#endif
#include <linux/module.h>
#include <linux/kmod.h>
+#include <linux/sched.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -33,690 +37,863 @@
#include <linux/mii.h>
#include <linux/usb.h>
#include <linux/crc32.h>
-#include <linux/usb/usbnet.h>
-#include <linux/slab.h>
-#define DRIVER_VERSION "14-Jun-2006"
-static const char driver_name [] = "asix";
-
-/* ASIX AX8817X based USB 2.0 Ethernet Devices */
+#include "axusbnet.c"
+#include "asix.h"
+
+#define DRV_VERSION "4.4.0"
+
+static char version[] =
+KERN_INFO "ASIX USB Ethernet Adapter:v" DRV_VERSION
+ " " __TIME__ " " __DATE__ "\n"
+KERN_INFO " http://www.asix.com.tw\n";
+
+static char g_mac_addr[ETH_ALEN];
+static int g_usr_mac = 0;
+
+/* configuration of maximum bulk in size */
+static int bsize = AX88772B_MAX_BULKIN_16K;
+module_param (bsize, int, 0);
+MODULE_PARM_DESC (bsize, "Maximum transfer size per bulk");
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+static void ax88772b_link_reset (void *data);
+static void ax88772a_link_reset (void *data);
+static void ax88772_link_reset (void *data);
+#else
+static void ax88772b_link_reset (struct work_struct *work);
+static void ax88772a_link_reset (struct work_struct *work);
+static void ax88772_link_reset (struct work_struct *work);
+#endif
+static int ax88772a_phy_powerup (struct usbnet *dev);
+
+/* Retrieve user set MAC address */
+static int __init setup_asix_mac(char *macstr)
+{
+ int i, j;
+ unsigned char result, value;
+
+ for (i = 0; i < ETH_ALEN; i++) {
+ result = 0;
+
+ if (i != 5 && *(macstr + 2) != ':')
+ return -1;
+
+ for (j = 0; j < 2; j++) {
+ if (isxdigit(*macstr)
+ && (value =
+ isdigit(*macstr) ? *macstr -
+ '0' : toupper(*macstr) - 'A' + 10) < 16) {
+ result = result * 16 + value;
+ macstr++;
+ } else
+ return -1;
+ }
-#define AX_CMD_SET_SW_MII 0x06
-#define AX_CMD_READ_MII_REG 0x07
-#define AX_CMD_WRITE_MII_REG 0x08
-#define AX_CMD_SET_HW_MII 0x0a
-#define AX_CMD_READ_EEPROM 0x0b
-#define AX_CMD_WRITE_EEPROM 0x0c
-#define AX_CMD_WRITE_ENABLE 0x0d
-#define AX_CMD_WRITE_DISABLE 0x0e
-#define AX_CMD_READ_RX_CTL 0x0f
-#define AX_CMD_WRITE_RX_CTL 0x10
-#define AX_CMD_READ_IPG012 0x11
-#define AX_CMD_WRITE_IPG0 0x12
-#define AX_CMD_WRITE_IPG1 0x13
-#define AX_CMD_READ_NODE_ID 0x13
-#define AX_CMD_WRITE_NODE_ID 0x14
-#define AX_CMD_WRITE_IPG2 0x14
-#define AX_CMD_WRITE_MULTI_FILTER 0x16
-#define AX88172_CMD_READ_NODE_ID 0x17
-#define AX_CMD_READ_PHY_ID 0x19
-#define AX_CMD_READ_MEDIUM_STATUS 0x1a
-#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
-#define AX_CMD_READ_MONITOR_MODE 0x1c
-#define AX_CMD_WRITE_MONITOR_MODE 0x1d
-#define AX_CMD_READ_GPIOS 0x1e
-#define AX_CMD_WRITE_GPIOS 0x1f
-#define AX_CMD_SW_RESET 0x20
-#define AX_CMD_SW_PHY_STATUS 0x21
-#define AX_CMD_SW_PHY_SELECT 0x22
-
-#define AX_MONITOR_MODE 0x01
-#define AX_MONITOR_LINK 0x02
-#define AX_MONITOR_MAGIC 0x04
-#define AX_MONITOR_HSFS 0x10
-
-/* AX88172 Medium Status Register values */
-#define AX88172_MEDIUM_FD 0x02
-#define AX88172_MEDIUM_TX 0x04
-#define AX88172_MEDIUM_FC 0x10
-#define AX88172_MEDIUM_DEFAULT \
- ( AX88172_MEDIUM_FD | AX88172_MEDIUM_TX | AX88172_MEDIUM_FC )
-
-#define AX_MCAST_FILTER_SIZE 8
-#define AX_MAX_MCAST 64
-
-#define AX_SWRESET_CLEAR 0x00
-#define AX_SWRESET_RR 0x01
-#define AX_SWRESET_RT 0x02
-#define AX_SWRESET_PRTE 0x04
-#define AX_SWRESET_PRL 0x08
-#define AX_SWRESET_BZ 0x10
-#define AX_SWRESET_IPRL 0x20
-#define AX_SWRESET_IPPD 0x40
-
-#define AX88772_IPG0_DEFAULT 0x15
-#define AX88772_IPG1_DEFAULT 0x0c
-#define AX88772_IPG2_DEFAULT 0x12
-
-/* AX88772 & AX88178 Medium Mode Register */
-#define AX_MEDIUM_PF 0x0080
-#define AX_MEDIUM_JFE 0x0040
-#define AX_MEDIUM_TFC 0x0020
-#define AX_MEDIUM_RFC 0x0010
-#define AX_MEDIUM_ENCK 0x0008
-#define AX_MEDIUM_AC 0x0004
-#define AX_MEDIUM_FD 0x0002
-#define AX_MEDIUM_GM 0x0001
-#define AX_MEDIUM_SM 0x1000
-#define AX_MEDIUM_SBP 0x0800
-#define AX_MEDIUM_PS 0x0200
-#define AX_MEDIUM_RE 0x0100
-
-#define AX88178_MEDIUM_DEFAULT \
- (AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \
- AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \
- AX_MEDIUM_RE )
-
-#define AX88772_MEDIUM_DEFAULT \
- (AX_MEDIUM_FD | AX_MEDIUM_RFC | \
- AX_MEDIUM_TFC | AX_MEDIUM_PS | \
- AX_MEDIUM_AC | AX_MEDIUM_RE )
-
-/* AX88772 & AX88178 RX_CTL values */
-#define AX_RX_CTL_SO 0x0080
-#define AX_RX_CTL_AP 0x0020
-#define AX_RX_CTL_AM 0x0010
-#define AX_RX_CTL_AB 0x0008
-#define AX_RX_CTL_SEP 0x0004
-#define AX_RX_CTL_AMALL 0x0002
-#define AX_RX_CTL_PRO 0x0001
-#define AX_RX_CTL_MFB_2048 0x0000
-#define AX_RX_CTL_MFB_4096 0x0100
-#define AX_RX_CTL_MFB_8192 0x0200
-#define AX_RX_CTL_MFB_16384 0x0300
-
-#define AX_DEFAULT_RX_CTL \
- (AX_RX_CTL_SO | AX_RX_CTL_AB )
-
-/* GPIO 0 .. 2 toggles */
-#define AX_GPIO_GPO0EN 0x01 /* GPIO0 Output enable */
-#define AX_GPIO_GPO_0 0x02 /* GPIO0 Output value */
-#define AX_GPIO_GPO1EN 0x04 /* GPIO1 Output enable */
-#define AX_GPIO_GPO_1 0x08 /* GPIO1 Output value */
-#define AX_GPIO_GPO2EN 0x10 /* GPIO2 Output enable */
-#define AX_GPIO_GPO_2 0x20 /* GPIO2 Output value */
-#define AX_GPIO_RESERVED 0x40 /* Reserved */
-#define AX_GPIO_RSE 0x80 /* Reload serial EEPROM */
-
-#define AX_EEPROM_MAGIC 0xdeadbeef
-#define AX88172_EEPROM_LEN 0x40
-#define AX88772_EEPROM_LEN 0xff
-
-#define PHY_MODE_MARVELL 0x0000
-#define MII_MARVELL_LED_CTRL 0x0018
-#define MII_MARVELL_STATUS 0x001b
-#define MII_MARVELL_CTRL 0x0014
-
-#define MARVELL_LED_MANUAL 0x0019
-
-#define MARVELL_STATUS_HWCFG 0x0004
-
-#define MARVELL_CTRL_TXDELAY 0x0002
-#define MARVELL_CTRL_RXDELAY 0x0080
-
-/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
-struct asix_data {
- u8 multi_filter[AX_MCAST_FILTER_SIZE];
- u8 mac_addr[ETH_ALEN];
- u8 phymode;
- u8 ledmode;
- u8 eeprom_len;
-};
+ macstr++;
+ g_mac_addr[i] = result;
+ }
-struct ax88172_int_data {
- __le16 res1;
- u8 link;
- __le16 res2;
- u8 status;
- __le16 res3;
-} __packed;
+ g_usr_mac = 1;
-static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
- u16 size, void *data)
-{
- void *buf;
- int err = -ENOMEM;
+ return 0;
+}
- netdev_dbg(dev->net, "asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
- cmd, value, index, size);
+__setup("asix_mac=", setup_asix_mac);
- buf = kmalloc(size, GFP_KERNEL);
- if (!buf)
- goto out;
+/* ASIX AX8817X based USB 2.0 Ethernet Devices */
- err = usb_control_msg(
+static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+ u16 size, void *data)
+{
+ return usb_control_msg(
dev->udev,
usb_rcvctrlpipe(dev->udev, 0),
cmd,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value,
index,
- buf,
+ data,
size,
USB_CTRL_GET_TIMEOUT);
- if (err == size)
- memcpy(data, buf, size);
- else if (err >= 0)
- err = -EINVAL;
- kfree(buf);
-
-out:
- return err;
}
-static int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
u16 size, void *data)
{
- void *buf = NULL;
- int err = -ENOMEM;
-
- netdev_dbg(dev->net, "asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
- cmd, value, index, size);
-
- if (data) {
- buf = kmemdup(data, size, GFP_KERNEL);
- if (!buf)
- goto out;
- }
-
- err = usb_control_msg(
+ return usb_control_msg(
dev->udev,
usb_sndctrlpipe(dev->udev, 0),
cmd,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value,
index,
- buf,
+ data,
size,
USB_CTRL_SET_TIMEOUT);
- kfree(buf);
-
-out:
- return err;
}
-static void asix_async_cmd_callback(struct urb *urb)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+static void ax8817x_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
+#else
+static void ax8817x_async_cmd_callback(struct urb *urb)
+#endif
{
struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
- int status = urb->status;
- if (status < 0)
- printk(KERN_DEBUG "asix_async_cmd_callback() failed with %d",
- status);
+ if (urb->status < 0)
+ printk(KERN_DEBUG "ax8817x_async_cmd_callback() failed with %d",
+ urb->status);
kfree(req);
usb_free_urb(urb);
}
-static void
-asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
- u16 size, void *data)
+static int ax8817x_set_mac_addr (struct net_device *net, void *p)
{
- struct usb_ctrlrequest *req;
- int status;
- struct urb *urb;
+ struct usbnet *dev = netdev_priv(net);
+ struct sockaddr *addr = p;
- netdev_dbg(dev->net, "asix_write_cmd_async() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
- cmd, value, index, size);
- if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) {
- netdev_err(dev->net, "Error allocating URB in write_cmd_async!\n");
+ memcpy (net->dev_addr, addr->sa_data, ETH_ALEN);
+
+ /* Set the MAC address */
+ return ax8817x_write_cmd (dev, AX88772_CMD_WRITE_NODE_ID,
+ 0, 0, ETH_ALEN, net->dev_addr);
+
+}
+
+static void ax88178_status(struct usbnet *dev, struct urb *urb)
+{
+ struct ax88172_int_data *event;
+ struct ax88178_data *ax178dataptr = (struct ax88178_data *)dev->priv;
+ int link;
+
+ if (urb->actual_length < 8)
return;
- }
- if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) {
- netdev_err(dev->net, "Failed to allocate memory for control request\n");
- usb_free_urb(urb);
+ if (ax178dataptr->EepromData == PHY_MODE_MAC_TO_MAC_GMII)
return;
+
+ event = urb->transfer_buffer;
+ link = event->link & 0x01;
+ if (netif_carrier_ok(dev->net) != link) {
+ if (link) {
+ netif_carrier_on(dev->net);
+ axusbnet_defer_kevent (dev, EVENT_LINK_RESET);
+ } else
+ netif_carrier_off(dev->net);
+ devwarn(dev, "ax88178 - Link status is: %d", link);
}
+}
- req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
- req->bRequest = cmd;
- req->wValue = cpu_to_le16(value);
- req->wIndex = cpu_to_le16(index);
- req->wLength = cpu_to_le16(size);
+static void ax8817x_status(struct usbnet *dev, struct urb *urb)
+{
+ struct ax88172_int_data *event;
+ int link;
- usb_fill_control_urb(urb, dev->udev,
- usb_sndctrlpipe(dev->udev, 0),
- (void *)req, data, size,
- asix_async_cmd_callback, req);
+ if (urb->actual_length < 8)
+ return;
- if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
- netdev_err(dev->net, "Error submitting the control message: status=%d\n",
- status);
- kfree(req);
- usb_free_urb(urb);
+ event = urb->transfer_buffer;
+ link = event->link & 0x01;
+ if (netif_carrier_ok(dev->net) != link) {
+ if (link) {
+ netif_carrier_on(dev->net);
+ axusbnet_defer_kevent (dev, EVENT_LINK_RESET );
+ } else
+ netif_carrier_off(dev->net);
+ devwarn(dev, "ax8817x - Link status is: %d", link);
}
}
-static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+static void ax88772_status(struct usbnet *dev, struct urb *urb)
{
- u8 *head;
- u32 header;
- char *packet;
- struct sk_buff *ax_skb;
- u16 size;
+ struct ax88172_int_data *event;
+ struct ax88772_data *ax772_data = (struct ax88772_data *)dev->priv;
+ int link;
+
+ if (urb->actual_length < 8)
+ return;
- head = (u8 *) skb->data;
- memcpy(&header, head, sizeof(header));
- le32_to_cpus(&header);
- packet = head + sizeof(header);
+ event = urb->transfer_buffer;
+ link = event->link & 0x01;
+
+ if (netif_carrier_ok(dev->net) != link) {
+ if (link) {
+ netif_carrier_on(dev->net);
+ ax772_data->Event = AX_SET_RX_CFG;
+ } else {
+ netif_carrier_off(dev->net);
+ if (ax772_data->Event == AX_NOP) {
+ ax772_data->Event = PHY_POWER_DOWN;
+ ax772_data->TickToExpire = 25;
+ }
+ }
- skb_pull(skb, 4);
+ devwarn(dev, "ax88772 - Link status is: %d", link);
+ }
+
+ if (ax772_data->Event)
+ queue_work (ax772_data->ax_work, &ax772_data->check_link);
+}
- while (skb->len > 0) {
- if ((header & 0x07ff) != ((~header >> 16) & 0x07ff))
- netdev_err(dev->net, "asix_rx_fixup() Bad Header Length\n");
+static void ax88772a_status(struct usbnet *dev, struct urb *urb)
+{
+ struct ax88172_int_data *event;
+ struct ax88772a_data *ax772a_data = (struct ax88772a_data *)dev->priv;
+ int link;
+ int PowSave = (ax772a_data->EepromData >> 14);
- /* get the packet length */
- size = (u16) (header & 0x000007ff);
+ if (urb->actual_length < 8)
+ return;
- if ((skb->len) - ((size + 1) & 0xfffe) == 0) {
- u8 alignment = (unsigned long)skb->data & 0x3;
- if (alignment != 0x2) {
- /*
- * not 16bit aligned so use the room provided by
- * the 32 bit header to align the data
- *
- * note we want 16bit alignment as MAC header is
- * 14bytes thus ip header will be aligned on
- * 32bit boundary so accessing ipheader elements
- * using a cast to struct ip header wont cause
- * an unaligned accesses.
- */
- u8 realignment = (alignment + 2) & 0x3;
- memmove(skb->data - realignment,
- skb->data,
- size);
- skb->data -= realignment;
- skb_set_tail_pointer(skb, size);
- }
- return 2;
- }
+ event = urb->transfer_buffer;
+ link = event->link & 0x01;
- if (size > dev->net->mtu + ETH_HLEN) {
- netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
- size);
- return 0;
- }
- ax_skb = skb_clone(skb, GFP_ATOMIC);
- if (ax_skb) {
- u8 alignment = (unsigned long)packet & 0x3;
- ax_skb->len = size;
+ if (netif_carrier_ok(dev->net) != link) {
- if (alignment != 0x2) {
- /*
- * not 16bit aligned use the room provided by
- * the 32 bit header to align the data
- */
- u8 realignment = (alignment + 2) & 0x3;
- memmove(packet - realignment, packet, size);
- packet -= realignment;
+ if (link) {
+ netif_carrier_on(dev->net);
+ ax772a_data->Event = AX_SET_RX_CFG;
+ } else if ((PowSave == 0x3) || (PowSave == 0x1)) {
+ netif_carrier_off(dev->net);
+ if (ax772a_data->Event == AX_NOP) {
+ ax772a_data->Event = CHK_CABLE_EXIST;
+ ax772a_data->TickToExpire = 14;
}
- ax_skb->data = packet;
- skb_set_tail_pointer(ax_skb, size);
- usbnet_skb_return(dev, ax_skb);
} else {
- return 0;
+ netif_carrier_off(dev->net);
+ ax772a_data->Event = AX_NOP;
}
- skb_pull(skb, (size + 1) & 0xfffe);
-
- if (skb->len < sizeof(header))
- break;
-
- head = (u8 *) skb->data;
- memcpy(&header, head, sizeof(header));
- le32_to_cpus(&header);
- packet = head + sizeof(header);
- skb_pull(skb, 4);
- }
-
- if (skb->len < 0) {
- netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d\n",
- skb->len);
- return 0;
+ devwarn(dev, "ax88772a - Link status is: %d", link);
}
- return 1;
+
+ if (ax772a_data->Event)
+ queue_work (ax772a_data->ax_work, &ax772a_data->check_link);
}
-static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
- gfp_t flags)
+static int ax88772b_stop(struct usbnet *dev)
{
- int padlen;
- int headroom = skb_headroom(skb);
- int tailroom = skb_tailroom(skb);
- u32 packet_len;
- u32 padbytes = 0xffff0000;
+ u16 *medium;
- padlen = ((skb->len + 4) % 512) ? 0 : 4;
+ medium = kmalloc (2, GFP_ATOMIC);
+ if (medium) {
+ ax8817x_read_cmd (dev, AX_CMD_READ_MEDIUM_MODE, 0, 0, 2, medium);
+ ax8817x_write_cmd (dev, AX_CMD_WRITE_MEDIUM_MODE,
+ (*medium & ~AX88772_MEDIUM_RX_ENABLE), 0, 0, NULL);
- if ((!skb_cloned(skb)) &&
- ((headroom + tailroom) >= (4 + padlen))) {
- if ((headroom < 4) || (tailroom < padlen)) {
- skb->data = memmove(skb->head + 4, skb->data, skb->len);
- skb_set_tail_pointer(skb, skb->len);
- }
- } else {
- struct sk_buff *skb2;
- skb2 = skb_copy_expand(skb, 4, padlen, flags);
- dev_kfree_skb_any(skb);
- skb = skb2;
- if (!skb)
- return NULL;
+ kfree (medium);
+ return 0;
}
+ return -EINVAL;
+
+}
- skb_push(skb, 4);
- packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
- cpu_to_le32s(&packet_len);
- skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
+static int ax88772b_reset(struct usbnet *dev)
+{
+ int ret;
- if ((skb->len % 512) == 0) {
- cpu_to_le32s(&padbytes);
- memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
- skb_put(skb, sizeof(padbytes));
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
+ AX88772_MEDIUM_DEFAULT, 0, 0, NULL)) < 0) {
+ deverr(dev, "Write medium mode register: %d", ret);
}
- return skb;
+ return ret;
+
}
-static void asix_status(struct usbnet *dev, struct urb *urb)
+
+static void ax88772b_status(struct usbnet *dev, struct urb *urb)
{
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
struct ax88172_int_data *event;
int link;
if (urb->actual_length < 8)
return;
+ if (ax772b_data->OperationMode == OPERATION_PHY_MODE)
+ return;
+
event = urb->transfer_buffer;
- link = event->link & 0x01;
+ if (ax772b_data->PhySelect == 0 && ax772b_data->OperationMode
+ == OPERATION_MAC_MODE)
+ link = event->link & AX_INT_SPLS_LINK;
+ else
+ link = event->link & AX_INT_PPLS_LINK;
+
if (netif_carrier_ok(dev->net) != link) {
if (link) {
netif_carrier_on(dev->net);
- usbnet_defer_kevent (dev, EVENT_LINK_RESET );
- } else
+ ax772b_data->Event = AX_SET_RX_CFG;
+ } else {
netif_carrier_off(dev->net);
- netdev_dbg(dev->net, "Link Status is: %d\n", link);
+ ax772b_data->time_to_chk = jiffies;
+ }
+ devwarn(dev, "ax88772b - Link status is: %d", link);
}
-}
-
-static inline int asix_set_sw_mii(struct usbnet *dev)
-{
- int ret;
- ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
- if (ret < 0)
- netdev_err(dev->net, "Failed to enable software MII access\n");
- return ret;
-}
-static inline int asix_set_hw_mii(struct usbnet *dev)
-{
- int ret;
- ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL);
- if (ret < 0)
- netdev_err(dev->net, "Failed to enable hardware MII access\n");
- return ret;
-}
+ if (!link) {
-static inline int asix_get_phy_addr(struct usbnet *dev)
-{
- u8 buf[2];
- int ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
-
- netdev_dbg(dev->net, "asix_get_phy_addr()\n");
+ int no_cable = (event->link & AX_INT_CABOFF_UNPLUG) ? 1 : 0;
- if (ret < 0) {
- netdev_err(dev->net, "Error reading PHYID register: %02x\n", ret);
- goto out;
+ if (no_cable) {
+ if ((ax772b_data->psc &
+ (AX_SWRESET_IPPSL_0 | AX_SWRESET_IPPSL_1)) &&
+ !ax772b_data->pw_enabled) {
+ /*
+ * AX88772B already entered power saving state
+ */
+ ax772b_data->pw_enabled = 1;
+ }
+/* Disable failing auto detach stuff for now */
+#if 0
+ ax772b_data->Event = AX_CHK_AUTODETACH;
+#endif
+ } else {
+ /* AX88772B resumed from power saving state */
+ if (ax772b_data->pw_enabled ||
+ (jiffies > (ax772b_data->time_to_chk +
+ AX88772B_WATCHDOG))) {
+ if (ax772b_data->pw_enabled)
+ ax772b_data->pw_enabled = 0;
+ ax772b_data->Event = PHY_POWER_UP;
+ ax772b_data->time_to_chk = jiffies;
+ }
+ }
}
- netdev_dbg(dev->net, "asix_get_phy_addr() returning 0x%04x\n",
- *((__le16 *)buf));
- ret = buf[1];
-out:
- return ret;
+ if (ax772b_data->Event)
+ queue_work (ax772b_data->ax_work, &ax772b_data->check_link);
}
-static int asix_sw_reset(struct usbnet *dev, u8 flags)
+void
+ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+ u16 size, void *data)
{
- int ret;
+ struct usb_ctrlrequest *req;
+ int status;
+ struct urb *urb;
- ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL);
- if (ret < 0)
- netdev_err(dev->net, "Failed to send software reset: %02x\n", ret);
+ if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) {
+ deverr(dev, "Error allocating URB in write_cmd_async!");
+ return;
+ }
- return ret;
-}
+ if ((req = kmalloc (sizeof (struct usb_ctrlrequest),
+ GFP_ATOMIC)) == NULL) {
+ deverr(dev, "Failed to allocate memory for control request");
+ usb_free_urb(urb);
+ return;
+ }
-static u16 asix_read_rx_ctl(struct usbnet *dev)
-{
- __le16 v;
- int ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, &v);
+ req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+ req->bRequest = cmd;
+ req->wValue = cpu_to_le16(value);
+ req->wIndex = cpu_to_le16(index);
+ req->wLength = cpu_to_le16(size);
+
+ usb_fill_control_urb(urb, dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
+ (void *)req, data, size,
+ ax8817x_async_cmd_callback, req);
- if (ret < 0) {
- netdev_err(dev->net, "Error reading RX_CTL register: %02x\n", ret);
- goto out;
+ if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+ deverr(dev, "Error submitting the control message: status=%d",
+ status);
+ kfree(req);
+ usb_free_urb(urb);
}
- ret = le16_to_cpu(v);
-out:
- return ret;
}
-static int asix_write_rx_ctl(struct usbnet *dev, u16 mode)
+static void ax8817x_set_multicast(struct net_device *net)
{
- int ret;
+ struct usbnet *dev = netdev_priv(net);
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
+ u8 rx_ctl = AX_RX_CTL_START | AX_RX_CTL_AB;
+ int mc_count;
- netdev_dbg(dev->net, "asix_write_rx_ctl() - mode = 0x%04x\n", mode);
- ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL);
- if (ret < 0)
- netdev_err(dev->net, "Failed to write RX_CTL mode to 0x%04x: %02x\n",
- mode, ret);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
+ mc_count = net->mc_count;
+#else
+ mc_count = netdev_mc_count (net);
+#endif
- return ret;
-}
+ if (net->flags & IFF_PROMISC) {
+ rx_ctl |= AX_RX_CTL_PRO;
+ } else if (net->flags & IFF_ALLMULTI
+ || mc_count > AX_MAX_MCAST) {
+ rx_ctl |= AX_RX_CTL_AMALL;
+ } else if (mc_count == 0) {
+ /* just broadcast and directed */
+ } else {
+ /* We use the 20 byte dev->data
+ * for our 8 byte filter buffer
+ * to avoid allocating memory that
+ * is tricky to free later */
+ u32 crc_bits;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
+ struct dev_mc_list *mc_list = net->mc_list;
+ int i;
-static u16 asix_read_medium_status(struct usbnet *dev)
-{
- __le16 v;
- int ret = asix_read_cmd(dev, AX_CMD_READ_MEDIUM_STATUS, 0, 0, 2, &v);
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
+
+ /* Build the multicast hash filter. */
+ for (i = 0; i < net->mc_count; i++) {
+ crc_bits =
+ ether_crc(ETH_ALEN,
+ mc_list->dmi_addr) >> 26;
+ data->multi_filter[crc_bits >> 3] |=
+ 1 << (crc_bits & 7);
+ mc_list = mc_list->next;
+ }
+#else
+ struct netdev_hw_addr *ha;
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
+ netdev_for_each_mc_addr (ha, net) {
+ crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
+ data->multi_filter[crc_bits >> 3] |=
+ 1 << (crc_bits & 7);
+ }
+#endif
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
+ AX_MCAST_FILTER_SIZE, data->multi_filter);
- if (ret < 0) {
- netdev_err(dev->net, "Error reading Medium Status register: %02x\n",
- ret);
- goto out;
+ rx_ctl |= AX_RX_CTL_AM;
}
- ret = le16_to_cpu(v);
-out:
- return ret;
+
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
}
-static int asix_write_medium_mode(struct usbnet *dev, u16 mode)
+static void ax88178_set_multicast(struct net_device *net)
{
- int ret;
+ struct usbnet *dev = netdev_priv(net);
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
+ u16 rx_ctl = (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_CTL_MFB);
+ int mc_count;
- netdev_dbg(dev->net, "asix_write_medium_mode() - mode = 0x%04x\n", mode);
- ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
- if (ret < 0)
- netdev_err(dev->net, "Failed to write Medium Mode mode to 0x%04x: %02x\n",
- mode, ret);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
+ mc_count = net->mc_count;
+#else
+ mc_count = netdev_mc_count (net);
+#endif
- return ret;
-}
+ if (net->flags & IFF_PROMISC) {
+ rx_ctl |= AX_RX_CTL_PRO;
+ } else if (net->flags & IFF_ALLMULTI
+ || mc_count > AX_MAX_MCAST) {
+ rx_ctl |= AX_RX_CTL_AMALL;
+ } else if (mc_count == 0) {
+ /* just broadcast and directed */
+ } else {
+ /* We use the 20 byte dev->data
+ * for our 8 byte filter buffer
+ * to avoid allocating memory that
+ * is tricky to free later */
+ u32 crc_bits;
-static int asix_write_gpio(struct usbnet *dev, u16 value, int sleep)
-{
- int ret;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
+ struct dev_mc_list *mc_list = net->mc_list;
+ int i;
- netdev_dbg(dev->net, "asix_write_gpio() - value = 0x%04x\n", value);
- ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, value, 0, 0, NULL);
- if (ret < 0)
- netdev_err(dev->net, "Failed to write GPIO value 0x%04x: %02x\n",
- value, ret);
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
+
+ /* Build the multicast hash filter. */
+ for (i = 0; i < net->mc_count; i++) {
+ crc_bits =
+ ether_crc(ETH_ALEN,
+ mc_list->dmi_addr) >> 26;
+ data->multi_filter[crc_bits >> 3] |=
+ 1 << (crc_bits & 7);
+ mc_list = mc_list->next;
+ }
+#else
+ struct netdev_hw_addr *ha;
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
+ netdev_for_each_mc_addr (ha, net) {
+ crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
+ data->multi_filter[crc_bits >> 3] |=
+ 1 << (crc_bits & 7);
+ }
+#endif
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
+ AX_MCAST_FILTER_SIZE, data->multi_filter);
- if (sleep)
- msleep(sleep);
+ rx_ctl |= AX_RX_CTL_AM;
+ }
- return ret;
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
}
-/*
- * AX88772 & AX88178 have a 16-bit RX_CTL value
- */
-static void asix_set_multicast(struct net_device *net)
+static void ax88772b_set_multicast(struct net_device *net)
{
struct usbnet *dev = netdev_priv(net);
- struct asix_data *data = (struct asix_data *)&dev->data;
- u16 rx_ctl = AX_DEFAULT_RX_CTL;
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
+ u16 rx_ctl = (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_HEADER_DEFAULT);
+ int mc_count;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
+ mc_count = net->mc_count;
+#else
+ mc_count = netdev_mc_count (net);
+#endif
if (net->flags & IFF_PROMISC) {
rx_ctl |= AX_RX_CTL_PRO;
- } else if (net->flags & IFF_ALLMULTI ||
- netdev_mc_count(net) > AX_MAX_MCAST) {
+ } else if (net->flags & IFF_ALLMULTI
+ || mc_count > AX_MAX_MCAST) {
rx_ctl |= AX_RX_CTL_AMALL;
- } else if (netdev_mc_empty(net)) {
+ } else if (mc_count == 0) {
/* just broadcast and directed */
} else {
/* We use the 20 byte dev->data
* for our 8 byte filter buffer
* to avoid allocating memory that
* is tricky to free later */
- struct netdev_hw_addr *ha;
u32 crc_bits;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
+ struct dev_mc_list *mc_list = net->mc_list;
+ int i;
+
memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
/* Build the multicast hash filter. */
- netdev_for_each_mc_addr(ha, net) {
- crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
+ for (i = 0; i < net->mc_count; i++) {
+ crc_bits =
+ ether_crc(ETH_ALEN,
+ mc_list->dmi_addr) >> 26;
data->multi_filter[crc_bits >> 3] |=
1 << (crc_bits & 7);
+ mc_list = mc_list->next;
}
-
- asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
+#else
+ struct netdev_hw_addr *ha;
+ memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
+ netdev_for_each_mc_addr (ha, net) {
+ crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
+ data->multi_filter[crc_bits >> 3] |=
+ 1 << (crc_bits & 7);
+ }
+#endif
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
AX_MCAST_FILTER_SIZE, data->multi_filter);
rx_ctl |= AX_RX_CTL_AM;
}
- asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
+ ax8817x_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
+}
+
+static int ax8817x_mdio_read(struct net_device *netdev, int phy_id, int loc)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+ u16 *res;
+ u16 ret;
+
+ res = kmalloc (2, GFP_ATOMIC);
+ if (!res)
+ return 0;
+
+ ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
+ ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, res);
+ ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, NULL);
+
+ ret = *res & 0xffff;
+ kfree (res);
+
+ return ret;
}
-static int asix_mdio_read(struct net_device *netdev, int phy_id, int loc)
+static int
+ax8817x_swmii_mdio_read(struct net_device *netdev, int phy_id, int loc)
{
struct usbnet *dev = netdev_priv(netdev);
- __le16 res;
+ u16 *res;
+ u16 ret;
+
+ res = kmalloc (2, GFP_ATOMIC);
+ if (!res)
+ return 0;
+
+ ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
+ (__u16)loc, 2, res);
- mutex_lock(&dev->phy_mutex);
- asix_set_sw_mii(dev);
- asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
- (__u16)loc, 2, &res);
- asix_set_hw_mii(dev);
- mutex_unlock(&dev->phy_mutex);
+ ret = *res & 0xffff;
+ kfree (res);
- netdev_dbg(dev->net, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
- phy_id, loc, le16_to_cpu(res));
+ return ret;
+}
- return le16_to_cpu(res);
+/* same as above, but converts resulting value to cpu byte order */
+static int ax8817x_mdio_read_le(struct net_device *netdev, int phy_id, int loc)
+{
+ return le16_to_cpu(ax8817x_mdio_read(netdev,phy_id, loc));
+}
+
+static int
+ax8817x_swmii_mdio_read_le(struct net_device *netdev, int phy_id, int loc)
+{
+ return le16_to_cpu(ax8817x_swmii_mdio_read(netdev,phy_id, loc));
}
static void
-asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
+ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
{
struct usbnet *dev = netdev_priv(netdev);
- __le16 res = cpu_to_le16(val);
+ u16 *res;
+
+ res = kmalloc (2, GFP_ATOMIC);
+ if (!res)
+ return;
+ *res = val;
+
+ ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
+ (__u16)loc, 2, res);
+ ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, NULL);
- netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
- phy_id, loc, val);
- mutex_lock(&dev->phy_mutex);
- asix_set_sw_mii(dev);
- asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res);
- asix_set_hw_mii(dev);
- mutex_unlock(&dev->phy_mutex);
+ kfree (res);
}
-/* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */
-static u32 asix_get_phyid(struct usbnet *dev)
+static void ax8817x_swmii_mdio_write(struct net_device *netdev,
+ int phy_id, int loc, int val)
{
- int phy_reg;
- u32 phy_id;
+ struct usbnet *dev = netdev_priv(netdev);
+ u16 *res;
- phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1);
- if (phy_reg < 0)
- return 0;
+ res = kmalloc (2, GFP_ATOMIC);
+ if (!res)
+ return;
+ *res = val;
- phy_id = (phy_reg & 0xffff) << 16;
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
+ (__u16)loc, 2, res);
- phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID2);
- if (phy_reg < 0)
- return 0;
+ kfree (res);
+}
+
+static void
+ax88772b_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+ u16 *res;
+
+ res = kmalloc (2, GFP_ATOMIC);
+ if (!res)
+ return;
+ *res = val;
+
+ ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
+ (__u16)loc, 2, res);
+
+ if (loc == MII_ADVERTISE) {
+ *res = cpu_to_le16(BMCR_ANENABLE | BMCR_ANRESTART);
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
+ (__u16)MII_BMCR, 2, res);
+ }
+
+ ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, NULL);
+
+ kfree (res);
+}
+
+/* same as above, but converts new value to le16 byte order before writing */
+static void
+ax8817x_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val)
+{
+ ax8817x_mdio_write( netdev, phy_id, loc, cpu_to_le16(val) );
+}
+
+static void ax8817x_swmii_mdio_write_le(struct net_device *netdev,
+ int phy_id, int loc, int val)
+{
+ ax8817x_swmii_mdio_write( netdev, phy_id, loc, cpu_to_le16(val) );
+}
+
+static void
+ax88772b_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val)
+{
+ ax88772b_mdio_write( netdev, phy_id, loc, cpu_to_le16(val) );
+}
+
+static int ax88772_suspend (struct usb_interface *intf,
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
+ pm_message_t message)
+#else
+ u32 message)
+#endif
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+ u16 *medium;
+
+ medium = kmalloc (2, GFP_ATOMIC);
+ if (!medium)
+ return axusbnet_suspend (intf, message);
+
+ ax8817x_read_cmd (dev, AX_CMD_READ_MEDIUM_MODE, 0, 0, 2, medium);
+ ax8817x_write_cmd (dev, AX_CMD_WRITE_MEDIUM_MODE,
+ (*medium & ~AX88772_MEDIUM_RX_ENABLE), 0, 0, NULL);
+
+ kfree (medium);
+ return axusbnet_suspend (intf, message);
+}
+
+static int ax88772b_suspend (struct usb_interface *intf,
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
+ pm_message_t message)
+#else
+ u32 message)
+#endif
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
+ u16 *tmp16;
+ u8 *opt;
+
+ tmp16 = kmalloc (2, GFP_ATOMIC);
+ if (!tmp16)
+ return axusbnet_suspend (intf, message);
+ opt = (u8 *)tmp16;
+
+ ax8817x_read_cmd (dev, AX_CMD_READ_MEDIUM_MODE, 0, 0, 2, tmp16);
+ ax8817x_write_cmd (dev, AX_CMD_WRITE_MEDIUM_MODE,
+ (*tmp16 & ~AX88772_MEDIUM_RX_ENABLE), 0, 0, NULL);
+
+ ax8817x_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, opt);
+ if (!(*opt & AX_MONITOR_LINK) && !(*opt & AX_MONITOR_MAGIC)) {
+ ax8817x_write_cmd (dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPRL | AX_SWRESET_IPPD, 0, 0, NULL);
+ } else {
+
+ if (ax772b_data->psc & AX_SWRESET_WOLLP) {
+ *tmp16 = ax8817x_mdio_read_le (dev->net,
+ dev->mii.phy_id, MII_BMCR);
+ ax8817x_mdio_write_le (dev->net, dev->mii.phy_id,
+ MII_BMCR, *tmp16 | BMCR_ANENABLE);
+
+ ax8817x_write_cmd (dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPRL | ax772b_data->psc, 0, 0, NULL);
+ }
+
+ if (ax772b_data->psc &
+ (AX_SWRESET_IPPSL_0 | AX_SWRESET_IPPSL_1)) {
+ *opt |= AX_MONITOR_LINK;
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE,
+ *opt, 0, 0, NULL);
+ }
+ }
+
+ kfree (tmp16);
+ return axusbnet_suspend (intf, message);
+}
- phy_id |= (phy_reg & 0xffff);
+static int ax88772_resume (struct usb_interface *intf)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+
+ netif_carrier_off (dev->net);
+
+ return axusbnet_resume (intf);
+}
+
+static int ax88772b_resume (struct usb_interface *intf)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
+
+ if (ax772b_data->psc & AX_SWRESET_WOLLP) {
+ ax8817x_write_cmd (dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPRL | (ax772b_data->psc & 0x7FFF),
+ 0, 0, NULL);
+ }
+
+ if (ax772b_data->psc & (AX_SWRESET_IPPSL_0 | AX_SWRESET_IPPSL_1)) {
+ ax88772a_phy_powerup (dev);
+ }
+
+ netif_carrier_off (dev->net);
+
+ return axusbnet_resume (intf);
+}
+
+static int ax88172_link_reset(struct usbnet *dev)
+{
+ u16 lpa;
+ u16 adv;
+ u16 res;
+ u8 mode;
+
+ mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN;
+ lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
+ adv = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
+ res = mii_nway_result(lpa|adv);
+ if (res & LPA_DUPLEX)
+ mode |= AX_MEDIUM_FULL_DUPLEX;
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
- return phy_id;
+ return 0;
}
static void
-asix_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
+ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
{
struct usbnet *dev = netdev_priv(net);
- u8 opt;
+ u8 *opt;
+
+ wolinfo->supported = 0;
+ wolinfo->wolopts = 0;
- if (asix_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
- wolinfo->supported = 0;
- wolinfo->wolopts = 0;
+ opt = kmalloc (1, GFP_KERNEL);
+ if (!opt)
return;
- }
+
+ if (ax8817x_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, opt) < 0)
+ return;
+
wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
- wolinfo->wolopts = 0;
- if (opt & AX_MONITOR_MODE) {
- if (opt & AX_MONITOR_LINK)
- wolinfo->wolopts |= WAKE_PHY;
- if (opt & AX_MONITOR_MAGIC)
- wolinfo->wolopts |= WAKE_MAGIC;
- }
+
+ if (*opt & AX_MONITOR_LINK)
+ wolinfo->wolopts |= WAKE_PHY;
+ if (*opt & AX_MONITOR_MAGIC)
+ wolinfo->wolopts |= WAKE_MAGIC;
+
+ kfree (opt);
}
static int
-asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
+ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
{
struct usbnet *dev = netdev_priv(net);
- u8 opt = 0;
+ u8 *opt;
+
+ opt = kmalloc (1, GFP_KERNEL);
+ if (!opt)
+ return -ENOMEM;
+ *opt = 0;
if (wolinfo->wolopts & WAKE_PHY)
- opt |= AX_MONITOR_LINK;
+ *opt |= AX_MONITOR_LINK;
if (wolinfo->wolopts & WAKE_MAGIC)
- opt |= AX_MONITOR_MAGIC;
- if (opt != 0)
- opt |= AX_MONITOR_MODE;
+ *opt |= AX_MONITOR_MAGIC;
- if (asix_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE,
- opt, 0, 0, NULL) < 0)
- return -EINVAL;
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE, *opt, 0, 0, NULL);
+ kfree (opt);
return 0;
}
-static int asix_get_eeprom_len(struct net_device *net)
+static int ax8817x_get_eeprom_len(struct net_device *net)
{
- struct usbnet *dev = netdev_priv(net);
- struct asix_data *data = (struct asix_data *)&dev->data;
-
- return data->eeprom_len;
+ return AX_EEPROM_LEN;
}
-static int asix_get_eeprom(struct net_device *net,
+static int ax8817x_get_eeprom(struct net_device *net,
struct ethtool_eeprom *eeprom, u8 *data)
{
struct usbnet *dev = netdev_priv(net);
- __le16 *ebuf = (__le16 *)data;
+ u16 *ebuf = (u16 *)data;
int i;
/* Crude hack to ensure that we don't overwrite memory
@@ -729,722 +906,2753 @@ static int asix_get_eeprom(struct net_device *net,
/* ax8817x returns 2 bytes from eeprom on read */
for (i=0; i < eeprom->len / 2; i++) {
- if (asix_read_cmd(dev, AX_CMD_READ_EEPROM,
+ if (ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM,
eeprom->offset + i, 0, 2, &ebuf[i]) < 0)
return -EINVAL;
}
return 0;
}
-static void asix_get_drvinfo (struct net_device *net,
+static void ax8817x_get_drvinfo (struct net_device *net,
struct ethtool_drvinfo *info)
{
- struct usbnet *dev = netdev_priv(net);
- struct asix_data *data = (struct asix_data *)&dev->data;
-
/* Inherit standard device info */
- usbnet_get_drvinfo(net, info);
- strncpy (info->driver, driver_name, sizeof info->driver);
- strncpy (info->version, DRIVER_VERSION, sizeof info->version);
- info->eedump_len = data->eeprom_len;
+ axusbnet_get_drvinfo(net, info);
+ info->eedump_len = 0x3e;
}
-static u32 asix_get_link(struct net_device *net)
+static int ax8817x_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
{
struct usbnet *dev = netdev_priv(net);
+ return mii_ethtool_gset(&dev->mii,cmd);
+}
- return mii_link_ok(&dev->mii);
+static int ax8817x_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
+{
+ struct usbnet *dev = netdev_priv(net);
+ return mii_ethtool_sset(&dev->mii,cmd);
}
-static int asix_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
+/* We need to override some ethtool_ops so we require our
+ own structure so we don't interfere with other usbnet
+ devices that may be connected at the same time. */
+static struct ethtool_ops ax8817x_ethtool_ops = {
+ .get_drvinfo = ax8817x_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_msglevel = axusbnet_get_msglevel,
+ .set_msglevel = axusbnet_set_msglevel,
+ .get_wol = ax8817x_get_wol,
+ .set_wol = ax8817x_set_wol,
+ .get_eeprom_len = ax8817x_get_eeprom_len,
+ .get_eeprom = ax8817x_get_eeprom,
+ .get_settings = ax8817x_get_settings,
+ .set_settings = ax8817x_set_settings,
+};
+
+static int ax8817x_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
{
struct usbnet *dev = netdev_priv(net);
return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
}
-static int asix_set_mac_address(struct net_device *net, void *p)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
+static const struct net_device_ops ax88x72_netdev_ops = {
+ .ndo_open = axusbnet_open,
+ .ndo_stop = axusbnet_stop,
+ .ndo_start_xmit = axusbnet_start_xmit,
+ .ndo_tx_timeout = axusbnet_tx_timeout,
+ .ndo_change_mtu = axusbnet_change_mtu,
+ .ndo_get_stats = axusbnet_get_stats,
+ .ndo_do_ioctl = ax8817x_ioctl,
+ .ndo_set_mac_address = ax8817x_set_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,2,0)
+ .ndo_set_multicast_list = ax8817x_set_multicast,
+#else
+ .ndo_set_rx_mode = ax8817x_set_multicast,
+#endif
+};
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
+static const struct net_device_ops ax88178_netdev_ops = {
+ .ndo_open = axusbnet_open,
+ .ndo_stop = axusbnet_stop,
+ .ndo_start_xmit = axusbnet_start_xmit,
+ .ndo_tx_timeout = axusbnet_tx_timeout,
+ .ndo_change_mtu = axusbnet_change_mtu,
+ .ndo_get_stats = axusbnet_get_stats,
+ .ndo_do_ioctl = ax8817x_ioctl,
+ .ndo_set_mac_address = ax8817x_set_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,2,0)
+ .ndo_set_multicast_list = ax88178_set_multicast,
+#else
+ .ndo_set_rx_mode = ax88178_set_multicast,
+#endif
+};
+#endif
+
+static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
{
- struct usbnet *dev = netdev_priv(net);
- struct asix_data *data = (struct asix_data *)&dev->data;
- struct sockaddr *addr = p;
+ int ret = 0;
+ void *buf;
+ int i;
+ unsigned long gpio_bits = dev->driver_info->data;
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
+
+ axusbnet_get_endpoints(dev,intf);
+
+ buf = kmalloc(ETH_ALEN, GFP_KERNEL);
+ if(!buf) {
+ ret = -ENOMEM;
+ goto out1;
+ }
+
+ /* Toggle the GPIOs in a manufacturer/model specific way */
+ for (i = 2; i >= 0; i--) {
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
+ (gpio_bits >> (i * 8)) & 0xff, 0, 0,
+ NULL)) < 0)
+ goto out2;
+ msleep(5);
+ }
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
+ 0x80, 0, 0, NULL)) < 0) {
+ deverr(dev, "send AX_CMD_WRITE_RX_CTL failed: %d", ret);
+ goto out2;
+ }
+
+ /* Get the MAC address */
+ memset(buf, 0, ETH_ALEN);
+ if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_NODE_ID,
+ 0, 0, 6, buf)) < 0) {
+ deverr(dev, "read AX_CMD_READ_NODE_ID failed: %d", ret);
+ goto out2;
+ }
+ memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+
+ /* Get the PHY id */
+ if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID,
+ 0, 0, 2, buf)) < 0) {
+ deverr(dev, "error on read AX_CMD_READ_PHY_ID: %02x", ret);
+ goto out2;
+ } else if (ret < 2) {
+ /* this should always return 2 bytes */
+ deverr(dev, "Read PHYID returned less than 2 bytes: ret=%02x",
+ ret);
+ ret = -EIO;
+ goto out2;
+ }
- if (netif_running(net))
- return -EBUSY;
- if (!is_valid_ether_addr(addr->sa_data))
- return -EADDRNOTAVAIL;
+ /* Initialize MII structure */
+ dev->mii.dev = dev->net;
+ dev->mii.mdio_read = ax8817x_mdio_read_le;
+ dev->mii.mdio_write = ax8817x_mdio_write_le;
+ dev->mii.phy_id_mask = 0x3f;
+ dev->mii.reg_num_mask = 0x1f;
+ dev->mii.phy_id = *((u8 *)buf + 1);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
+ dev->net->do_ioctl = ax8817x_ioctl;
+ dev->net->set_multicast_list = ax8817x_set_multicast;
+ dev->net->set_mac_address = ax8817x_set_mac_addr;
+#else
+ dev->net->netdev_ops = &ax88x72_netdev_ops;
+#endif
- memcpy(net->dev_addr, addr->sa_data, ETH_ALEN);
+ dev->net->ethtool_ops = &ax8817x_ethtool_ops;
+
+ /* Register suspend and resume functions */
+ data->suspend = axusbnet_suspend;
+ data->resume = axusbnet_resume;
+
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+ ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
+ mii_nway_restart(&dev->mii);
- /* We use the 20 byte dev->data
- * for our 6 byte mac buffer
- * to avoid allocating memory that
- * is tricky to free later */
- memcpy(data->mac_addr, addr->sa_data, ETH_ALEN);
- asix_write_cmd_async(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
- data->mac_addr);
+ printk (version);
return 0;
+out2:
+ kfree(buf);
+out1:
+ return ret;
}
-/* We need to override some ethtool_ops so we require our
- own structure so we don't interfere with other usbnet
- devices that may be connected at the same time. */
-static const struct ethtool_ops ax88172_ethtool_ops = {
- .get_drvinfo = asix_get_drvinfo,
- .get_link = asix_get_link,
- .get_msglevel = usbnet_get_msglevel,
- .set_msglevel = usbnet_set_msglevel,
- .get_wol = asix_get_wol,
- .set_wol = asix_set_wol,
- .get_eeprom_len = asix_get_eeprom_len,
- .get_eeprom = asix_get_eeprom,
- .get_settings = usbnet_get_settings,
- .set_settings = usbnet_set_settings,
- .nway_reset = usbnet_nway_reset,
+static struct ethtool_ops ax88772_ethtool_ops = {
+ .get_drvinfo = ax8817x_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_msglevel = axusbnet_get_msglevel,
+ .set_msglevel = axusbnet_set_msglevel,
+ .get_wol = ax8817x_get_wol,
+ .set_wol = ax8817x_set_wol,
+ .get_eeprom_len = ax8817x_get_eeprom_len,
+ .get_eeprom = ax8817x_get_eeprom,
+ .get_settings = ax8817x_get_settings,
+ .set_settings = ax8817x_set_settings,
};
-static void ax88172_set_multicast(struct net_device *net)
+static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
{
- struct usbnet *dev = netdev_priv(net);
- struct asix_data *data = (struct asix_data *)&dev->data;
- u8 rx_ctl = 0x8c;
+ int ret;
+ void *buf;
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
+ struct ax88772_data *ax772_data = NULL;
- if (net->flags & IFF_PROMISC) {
- rx_ctl |= 0x01;
- } else if (net->flags & IFF_ALLMULTI ||
- netdev_mc_count(net) > AX_MAX_MCAST) {
- rx_ctl |= 0x02;
- } else if (netdev_mc_empty(net)) {
- /* just broadcast and directed */
- } else {
- /* We use the 20 byte dev->data
- * for our 8 byte filter buffer
- * to avoid allocating memory that
- * is tricky to free later */
- struct netdev_hw_addr *ha;
- u32 crc_bits;
+ axusbnet_get_endpoints(dev,intf);
- memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
+ buf = kmalloc(6, GFP_KERNEL);
+ if(!buf) {
+ deverr(dev, "Cannot allocate memory for buffer");
+ ret = -ENOMEM;
+ goto out1;
+ }
- /* Build the multicast hash filter. */
- netdev_for_each_mc_addr(ha, net) {
- crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
- data->multi_filter[crc_bits >> 3] |=
- 1 << (crc_bits & 7);
+ ax772_data = kmalloc (sizeof(*ax772_data), GFP_KERNEL);
+ if (!ax772_data) {
+ deverr(dev, "Cannot allocate memory for AX88772 data");
+ kfree (buf);
+ return -ENOMEM;
+ }
+ memset (ax772_data, 0, sizeof(*ax772_data));
+ dev->priv = ax772_data;
+
+ ax772_data->ax_work = create_singlethread_workqueue ("ax88772");
+ if (!ax772_data->ax_work) {
+ kfree (ax772_data);
+ kfree (buf);
+ return -ENOMEM;
+ }
+
+ ax772_data->dev = dev;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ INIT_WORK (&ax772_data->check_link, ax88772_link_reset, dev);
+#else
+ INIT_WORK (&ax772_data->check_link, ax88772_link_reset);
+#endif
+
+ /* reload eeprom data */
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
+ 0x00B0, 0, 0, NULL)) < 0)
+ goto out2;
+
+ msleep(5);
+
+ /* Initialize MII structure */
+ dev->mii.dev = dev->net;
+ dev->mii.mdio_read = ax8817x_mdio_read_le;
+ dev->mii.mdio_write = ax8817x_mdio_write_le;
+ dev->mii.phy_id_mask = 0xff;
+ dev->mii.reg_num_mask = 0xff;
+
+ /* Get the PHY id */
+ if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID,
+ 0, 0, 2, buf)) < 0) {
+ deverr(dev, "Error reading PHY ID: %02x", ret);
+ goto out2;
+ } else if (ret < 2) {
+ /* this should always return 2 bytes */
+ deverr(dev, "Read PHYID returned less than 2 bytes: ret=%02x",
+ ret);
+ ret = -EIO;
+ goto out2;
+ }
+ dev->mii.phy_id = *((u8 *)buf + 1);
+
+ if (dev->mii.phy_id == 0x10)
+ {
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
+ 0x0001, 0, 0, NULL)) < 0) {
+ deverr(dev, "Select PHY #1 failed: %d", ret);
+ goto out2;
}
- asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
- AX_MCAST_FILTER_SIZE, data->multi_filter);
+ if ((ret = ax8817x_write_cmd (dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPPD,
+ 0, 0, NULL)) < 0) {
+ deverr(dev, "Failed to power down PHY: %d", ret);
+ goto out2;
+ }
+
+ msleep(150);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_CLEAR,
+ 0, 0, NULL)) < 0) {
+ deverr(dev,
+ "Failed to perform software reset: %d", ret);
+ goto out2;
+ }
+
+ msleep(150);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPRL | AX_SWRESET_PRL,
+ 0, 0, NULL)) < 0) {
+ deverr(dev,
+ "Failed to set PHY reset control: %d", ret);
+ goto out2;
+ }
+ }
+ else
+ {
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
+ 0x0000, 0, 0, NULL)) < 0) {
+ deverr(dev, "Select PHY #1 failed: %d", ret);
+ goto out2;
+ }
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPPD | AX_SWRESET_PRL,
+ 0, 0, NULL)) < 0) {
+ deverr(dev,
+ "Failed to power down internal PHY: %d", ret);
+ goto out2;
+ }
+ }
+
+ msleep(150);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
+ 0x0000, 0, 0, NULL)) < 0) {
+ deverr(dev, "Failed to reset RX_CTL: %d", ret);
+ goto out2;
+ }
+
+ /* Get the MAC address */
+ memset(buf, 0, ETH_ALEN);
+ if ((ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID,
+ 0, 0, ETH_ALEN, buf)) < 0) {
+ deverr(dev, "Failed to read MAC address: %d", ret);
+ goto out2;
+ }
+ memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII,
+ 0, 0, 0, NULL)) < 0) {
+ deverr(dev, "Enabling software MII failed: %d", ret);
+ goto out2;
+ }
+
+ if (dev->mii.phy_id == 0x10)
+ {
+ if ((ret = ax8817x_mdio_read_le(dev->net,
+ dev->mii.phy_id, 2)) != 0x003b) {
+ deverr(dev, "Read PHY register 2 must be 0x3b00: %d",
+ ret);
+ goto out2;
+ }
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_PRL,
+ 0, 0, NULL)) < 0) {
+ deverr(dev, "Set external PHY reset pin level: %d", ret);
+ goto out2;
+ }
+ msleep(150);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPRL | AX_SWRESET_PRL,
+ 0, 0, NULL)) < 0) {
+ deverr(dev,
+ "Set Internal/External PHY reset control: %d",
+ ret);
+ goto out2;
+ }
+ msleep(150);
+ }
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
+ dev->net->do_ioctl = ax8817x_ioctl;
+ dev->net->set_multicast_list = ax8817x_set_multicast;
+ dev->net->set_mac_address = ax8817x_set_mac_addr;
+#else
+ dev->net->netdev_ops = &ax88x72_netdev_ops;
+#endif
+
+ dev->net->ethtool_ops = &ax88772_ethtool_ops;
+
+ /* Register suspend and resume functions */
+ data->suspend = ax88772_suspend;
+ data->resume = ax88772_resume;
+
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+ ADVERTISE_ALL | ADVERTISE_CSMA);
- rx_ctl |= 0x10;
+ mii_nway_restart(&dev->mii);
+ ax772_data->autoneg_start = jiffies;
+ ax772_data->Event = WAIT_AUTONEG_COMPLETE;
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
+ 0, 0, 0, NULL)) < 0) {
+ deverr(dev, "Write medium mode register: %d", ret);
+ goto out2;
+ }
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
+ AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT << 8,
+ AX88772_IPG2_DEFAULT, 0, NULL)) < 0) {
+ deverr(dev, "Write IPG,IPG1,IPG2 failed: %d", ret);
+ goto out2;
+ }
+ if ((ret =
+ ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, NULL)) < 0) {
+ deverr(dev, "Failed to set hardware MII: %02x", ret);
+ goto out2;
+ }
+
+ /* Set RX_CTL to default values with 2k buffer, and enable cactus */
+ if ((ret =
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0088, 0, 0,
+ NULL)) < 0) {
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
+ goto out2;
+ }
+
+ /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
+ if (dev->driver_info->flags & FLAG_FRAMING_AX) {
+ /* hard_mtu is still the default - the device does not support
+ jumbo eth frames */
+ dev->rx_urb_size = 2048;
}
- asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
+ kfree (buf);
+ printk (version);
+ return 0;
+
+out2:
+ destroy_workqueue (ax772_data->ax_work);
+ kfree (ax772_data);
+ kfree(buf);
+out1:
+ return ret;
}
-static int ax88172_link_reset(struct usbnet *dev)
+static void ax88772_unbind(struct usbnet *dev, struct usb_interface *intf)
{
- u8 mode;
- struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
+ struct ax88772_data *ax772_data = (struct ax88772_data *)dev->priv;
- mii_check_media(&dev->mii, 1, 1);
- mii_ethtool_gset(&dev->mii, &ecmd);
- mode = AX88172_MEDIUM_DEFAULT;
+ if (ax772_data) {
- if (ecmd.duplex != DUPLEX_FULL)
- mode |= ~AX88172_MEDIUM_FD;
+ flush_workqueue (ax772_data->ax_work);
+ destroy_workqueue (ax772_data->ax_work);
- netdev_dbg(dev->net, "ax88172_link_reset() speed: %u duplex: %d setting mode to 0x%04x\n",
- ethtool_cmd_speed(&ecmd), ecmd.duplex, mode);
+ /* stop MAC operation */
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
+ AX_RX_CTL_STOP, 0, 0, NULL);
- asix_write_medium_mode(dev, mode);
+ /* Power down PHY */
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPPD, 0, 0, NULL);
- return 0;
+ kfree (ax772_data);
+ }
}
-static const struct net_device_ops ax88172_netdev_ops = {
- .ndo_open = usbnet_open,
- .ndo_stop = usbnet_stop,
- .ndo_start_xmit = usbnet_start_xmit,
- .ndo_tx_timeout = usbnet_tx_timeout,
- .ndo_change_mtu = usbnet_change_mtu,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_do_ioctl = asix_ioctl,
- .ndo_set_multicast_list = ax88172_set_multicast,
-};
+static int ax88772a_phy_powerup (struct usbnet *dev)
+{
+ int ret;
+ /* set the embedded Ethernet PHY in power-down state */
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPPD | AX_SWRESET_IPRL, 0, 0, NULL)) < 0) {
+ deverr(dev, "Failed to power down PHY: %d", ret);
+ return ret;
+ }
+
+ msleep(10);
+
+
+ /* set the embedded Ethernet PHY in power-up state */
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPRL, 0, 0, NULL)) < 0) {
+ deverr(dev, "Failed to reset PHY: %d", ret);
+ return ret;
+ }
+
+ msleep(600);
+
+ /* set the embedded Ethernet PHY in reset state */
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_CLEAR, 0, 0, NULL)) < 0) {
+ deverr(dev, "Failed to power up PHY: %d", ret);
+ return ret;
+ }
+
+ /* set the embedded Ethernet PHY in power-up state */
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPRL, 0, 0, NULL)) < 0) {
+ deverr(dev, "Failed to reset PHY: %d", ret);
+ return ret;
+ }
+
+ return 0;
+}
-static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
+static int ax88772a_bind(struct usbnet *dev, struct usb_interface *intf)
{
- int ret = 0;
- u8 buf[ETH_ALEN];
- int i;
- unsigned long gpio_bits = dev->driver_info->data;
- struct asix_data *data = (struct asix_data *)&dev->data;
+ int ret = -EIO;
+ void *buf;
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
+ struct ax88772a_data *ax772a_data = NULL;
- data->eeprom_len = AX88172_EEPROM_LEN;
+ axusbnet_get_endpoints(dev,intf);
- usbnet_get_endpoints(dev,intf);
+ buf = kmalloc(6, GFP_KERNEL);
+ if(!buf) {
+ deverr(dev, "Cannot allocate memory for buffer");
+ ret = -ENOMEM;
+ goto out1;
+ }
- /* Toggle the GPIOs in a manufacturer/model specific way */
- for (i = 2; i >= 0; i--) {
- if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS,
- (gpio_bits >> (i * 8)) & 0xff, 0, 0,
- NULL)) < 0)
- goto out;
- msleep(5);
+ ax772a_data = kmalloc (sizeof(*ax772a_data), GFP_KERNEL);
+ if (!ax772a_data) {
+ deverr(dev, "Cannot allocate memory for AX88772A data");
+ kfree (buf);
+ return -ENOMEM;
+ }
+ memset (ax772a_data, 0, sizeof(*ax772a_data));
+ dev->priv = ax772a_data;
+
+ ax772a_data->ax_work = create_singlethread_workqueue ("ax88772a");
+ if (!ax772a_data->ax_work) {
+ kfree (ax772a_data);
+ kfree (buf);
+ return -ENOMEM;
+ }
+
+ ax772a_data->dev = dev;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ INIT_WORK (&ax772a_data->check_link, ax88772a_link_reset, dev);
+#else
+ INIT_WORK (&ax772a_data->check_link, ax88772a_link_reset);
+#endif
+
+ /* Get the EEPROM data*/
+ if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM,
+ 0x0017, 0, 2, (void *)&ax772a_data->EepromData)) < 0) {
+ deverr(dev, "read SROM address 17h failed: %d", ret);
+ goto out2;
+ }
+ le16_to_cpus (&ax772a_data->EepromData);
+ /* End of get EEPROM data */
+
+ /* reload eeprom data */
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
+ AXGPIOS_RSE, 0, 0, NULL)) < 0)
+ goto out2;
+
+ msleep(5);
+
+ /* Initialize MII structure */
+ dev->mii.dev = dev->net;
+ dev->mii.mdio_read = ax8817x_mdio_read_le;
+ dev->mii.mdio_write = ax8817x_mdio_write_le;
+ dev->mii.phy_id_mask = 0xff;
+ dev->mii.reg_num_mask = 0xff;
+
+ /* Get the PHY id */
+ if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID,
+ 0, 0, 2, buf)) < 0) {
+ deverr(dev, "Error reading PHY ID: %02x", ret);
+ goto out2;
+ } else if (ret < 2) {
+ /* this should always return 2 bytes */
+ deverr(dev, "Read PHYID returned less than 2 bytes: ret=%02x",
+ ret);
+ goto out2;
+ }
+ dev->mii.phy_id = *((u8 *)buf + 1);
+
+ if(dev->mii.phy_id != 0x10) {
+ deverr(dev, "Got wrong PHY ID: %02x", dev->mii.phy_id);
+ goto out2;
+ }
+
+ /* select the embedded 10/100 Ethernet PHY */
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
+ AX_PHYSEL_SSEN | AX_PHYSEL_PSEL | AX_PHYSEL_SSMII,
+ 0, 0, NULL)) < 0) {
+ deverr(dev, "Select PHY #1 failed: %d", ret);
+ goto out2;
}
- if ((ret = asix_write_rx_ctl(dev, 0x80)) < 0)
- goto out;
+ if ((ret = ax88772a_phy_powerup (dev)) < 0)
+ goto out2;
+
+ /* stop MAC operation */
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
+ AX_RX_CTL_STOP, 0, 0, NULL)) < 0) {
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
+ goto out2;
+ }
/* Get the MAC address */
- if ((ret = asix_read_cmd(dev, AX88172_CMD_READ_NODE_ID,
+ memset(buf, 0, ETH_ALEN);
+ if ((ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID,
0, 0, ETH_ALEN, buf)) < 0) {
- dbg("read AX_CMD_READ_NODE_ID failed: %d", ret);
- goto out;
+ deverr(dev, "Failed to read MAC address: %d", ret);
+ goto out2;
}
memcpy(dev->net->dev_addr, buf, ETH_ALEN);
- /* Initialize MII structure */
- dev->mii.dev = dev->net;
- dev->mii.mdio_read = asix_mdio_read;
- dev->mii.mdio_write = asix_mdio_write;
- dev->mii.phy_id_mask = 0x3f;
- dev->mii.reg_num_mask = 0x1f;
- dev->mii.phy_id = asix_get_phy_addr(dev);
+ /* make sure the driver can enable sw mii operation */
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII,
+ 0, 0, 0, NULL)) < 0) {
+ deverr(dev, "Enabling software MII failed: %d", ret);
+ goto out2;
+ }
- dev->net->netdev_ops = &ax88172_netdev_ops;
- dev->net->ethtool_ops = &ax88172_ethtool_ops;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
+ dev->net->do_ioctl = ax8817x_ioctl;
+ dev->net->set_multicast_list = ax8817x_set_multicast;
+ dev->net->set_mac_address = ax8817x_set_mac_addr;
+#else
+ dev->net->netdev_ops = &ax88x72_netdev_ops;
+#endif
+
+ dev->net->ethtool_ops = &ax88772_ethtool_ops;
+
+ /* Register suspend and resume functions */
+ data->suspend = ax88772_suspend;
+ data->resume = ax88772_resume;
+
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+ ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
- asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
- asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
- ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
mii_nway_restart(&dev->mii);
+ ax772a_data->autoneg_start = jiffies;
+ ax772a_data->Event = WAIT_AUTONEG_COMPLETE;
- return 0;
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
+ 0, 0, 0, NULL)) < 0) {
+ deverr(dev, "Write medium mode register: %d", ret);
+ goto out2;
+ }
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
+ AX88772A_IPG0_DEFAULT | AX88772A_IPG1_DEFAULT << 8,
+ AX88772A_IPG2_DEFAULT, 0, NULL)) < 0) {
+ deverr(dev, "Write IPG,IPG1,IPG2 failed: %d", ret);
+ goto out2;
+ }
+
+ /* Set RX_CTL to default values with 2k buffer, and enable cactus */
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
+ (AX_RX_CTL_START | AX_RX_CTL_AB),
+ 0, 0, NULL)) < 0) {
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
+ goto out2;
+ }
+
+ /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
+ if (dev->driver_info->flags & FLAG_FRAMING_AX) {
+ /* hard_mtu is still the default - the device does not support
+ jumbo eth frames */
+ dev->rx_urb_size = 2048;
+ }
-out:
+ kfree (buf);
+
+ printk (version);
+
+ return ret;
+out2:
+ destroy_workqueue (ax772a_data->ax_work);
+ kfree (ax772a_data);
+ kfree (buf);
+out1:
return ret;
}
-static const struct ethtool_ops ax88772_ethtool_ops = {
- .get_drvinfo = asix_get_drvinfo,
- .get_link = asix_get_link,
- .get_msglevel = usbnet_get_msglevel,
- .set_msglevel = usbnet_set_msglevel,
- .get_wol = asix_get_wol,
- .set_wol = asix_set_wol,
- .get_eeprom_len = asix_get_eeprom_len,
- .get_eeprom = asix_get_eeprom,
- .get_settings = usbnet_get_settings,
- .set_settings = usbnet_set_settings,
- .nway_reset = usbnet_nway_reset,
-};
-
-static int ax88772_link_reset(struct usbnet *dev)
+static void ax88772a_unbind(struct usbnet *dev, struct usb_interface *intf)
{
- u16 mode;
- struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
+ struct ax88772a_data *ax772a_data = (struct ax88772a_data *)dev->priv;
+
+ if (ax772a_data) {
+
+ flush_workqueue (ax772a_data->ax_work);
+ destroy_workqueue (ax772a_data->ax_work);
+
+ /* stop MAC operation */
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
+ AX_RX_CTL_STOP, 0, 0, NULL);
+
+ /* Power down PHY */
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPPD, 0, 0, NULL);
- mii_check_media(&dev->mii, 1, 1);
- mii_ethtool_gset(&dev->mii, &ecmd);
- mode = AX88772_MEDIUM_DEFAULT;
+ kfree (ax772a_data);
+ }
+}
- if (ethtool_cmd_speed(&ecmd) != SPEED_100)
- mode &= ~AX_MEDIUM_PS;
+static int ax88772b_set_csums(struct usbnet *dev)
+{
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
+ u16 checksum;
- if (ecmd.duplex != DUPLEX_FULL)
- mode &= ~AX_MEDIUM_FD;
+ if (ax772b_data->checksum & AX_RX_CHECKSUM)
+ checksum = AX_RXCOE_DEF_CSUM;
+ else
+ checksum = 0;
- netdev_dbg(dev->net, "ax88772_link_reset() speed: %u duplex: %d setting mode to 0x%04x\n",
- ethtool_cmd_speed(&ecmd), ecmd.duplex, mode);
+ ax8817x_write_cmd (dev, AX_CMD_WRITE_RXCOE_CTL,
+ checksum, 0, 0, NULL);
- asix_write_medium_mode(dev, mode);
+ if (ax772b_data->checksum & AX_TX_CHECKSUM)
+ checksum = AX_TXCOE_DEF_CSUM;
+ else
+ checksum = 0;
+
+ ax8817x_write_cmd (dev, AX_CMD_WRITE_TXCOE_CTL,
+ checksum, 0, 0, NULL);
return 0;
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
+static u32 ax88772b_get_tx_csum(struct net_device *netdev)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
-static const struct net_device_ops ax88772_netdev_ops = {
- .ndo_open = usbnet_open,
- .ndo_stop = usbnet_stop,
- .ndo_start_xmit = usbnet_start_xmit,
- .ndo_tx_timeout = usbnet_tx_timeout,
- .ndo_change_mtu = usbnet_change_mtu,
- .ndo_set_mac_address = asix_set_mac_address,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_do_ioctl = asix_ioctl,
- .ndo_set_multicast_list = asix_set_multicast,
-};
+ return (ax772b_data->checksum & AX_TX_CHECKSUM);
+}
-static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
+static u32 ax88772b_get_rx_csum(struct net_device *netdev)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
+
+ return (ax772b_data->checksum & AX_RX_CHECKSUM);
+}
+
+static int ax88772b_set_rx_csum(struct net_device *netdev, u32 val)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
+
+ if (val)
+ ax772b_data->checksum |= AX_RX_CHECKSUM;
+ else
+ ax772b_data->checksum &= ~AX_RX_CHECKSUM;
+
+ return ax88772b_set_csums(dev);
+}
+
+static int ax88772b_set_tx_csum(struct net_device *netdev, u32 val)
{
- int ret, embd_phy;
- u16 rx_ctl;
- struct asix_data *data = (struct asix_data *)&dev->data;
- u8 buf[ETH_ALEN];
- u32 phyid;
+ struct usbnet *dev = netdev_priv(netdev);
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
+
+ if (val)
+ ax772b_data->checksum |= AX_TX_CHECKSUM;
+ else
+ ax772b_data->checksum &= ~AX_TX_CHECKSUM;
+
+ ethtool_op_set_tx_csum(netdev, val);
- data->eeprom_len = AX88772_EEPROM_LEN;
+ return ax88772b_set_csums(dev);
+}
+#endif
+static struct ethtool_ops ax88772b_ethtool_ops = {
+ .get_drvinfo = ax8817x_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_msglevel = axusbnet_get_msglevel,
+ .set_msglevel = axusbnet_set_msglevel,
+ .get_wol = ax8817x_get_wol,
+ .set_wol = ax8817x_set_wol,
+ .get_eeprom_len = ax8817x_get_eeprom_len,
+ .get_eeprom = ax8817x_get_eeprom,
+ .get_settings = ax8817x_get_settings,
+ .set_settings = ax8817x_set_settings,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
+ .set_tx_csum = ax88772b_set_tx_csum,
+ .get_tx_csum = ax88772b_get_tx_csum,
+ .get_rx_csum = ax88772b_get_rx_csum,
+ .set_rx_csum = ax88772b_set_rx_csum,
+#endif
+};
- usbnet_get_endpoints(dev,intf);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
+static const struct net_device_ops ax88772b_netdev_ops = {
+ .ndo_open = axusbnet_open,
+ .ndo_stop = axusbnet_stop,
+ .ndo_start_xmit = axusbnet_start_xmit,
+ .ndo_tx_timeout = axusbnet_tx_timeout,
+ .ndo_change_mtu = axusbnet_change_mtu,
+ .ndo_do_ioctl = ax8817x_ioctl,
+ .ndo_get_stats = axusbnet_get_stats,
+ .ndo_set_mac_address = ax8817x_set_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,2,0)
+ .ndo_set_multicast_list = ax88772b_set_multicast,
+#else
+ .ndo_set_rx_mode = ax88772b_set_multicast,
+#endif
+};
+#endif
- if ((ret = asix_write_gpio(dev,
- AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5)) < 0)
- goto out;
+static int ax88772b_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ int ret;
+ void *buf;
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
+ struct ax88772b_data *ax772b_data;
+ u16 *tmp16;
+ u8 i;
+ u8 TempPhySelect;
+ bool InternalPhy;
+ u8 default_asix_mac[ETH_ALEN] = { 0x00, 0x0e, 0xc6, 0x87, 0x72, 0x01 };
+
+ axusbnet_get_endpoints(dev,intf);
+
+ buf = kmalloc (6, GFP_KERNEL);
+ if (!buf) {
+ deverr(dev, "Cannot allocate memory for buffer");
+ return -ENOMEM;
+ }
+ tmp16 = (u16 *)buf;
- /* 0x10 is the phy id of the embedded 10/100 ethernet phy */
- embd_phy = ((asix_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0);
- if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
- embd_phy, 0, 0, NULL)) < 0) {
- dbg("Select PHY #1 failed: %d", ret);
- goto out;
+ ax772b_data = kmalloc (sizeof(*ax772b_data), GFP_KERNEL);
+ if (!ax772b_data) {
+ deverr(dev, "Cannot allocate memory for AX88772B data");
+ kfree (buf);
+ return -ENOMEM;
+ }
+ memset (ax772b_data, 0, sizeof(*ax772b_data));
+ dev->priv = ax772b_data;
+
+ ax772b_data->ax_work = create_singlethread_workqueue ("ax88772b");
+ if (!ax772b_data->ax_work) {
+ kfree (buf);
+ kfree (ax772b_data);
+ return -ENOMEM;
}
- if ((ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL)) < 0)
- goto out;
+ ax772b_data->dev = dev;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ INIT_WORK (&ax772b_data->check_link, ax88772b_link_reset, dev);
+#else
+ INIT_WORK (&ax772b_data->check_link, ax88772b_link_reset);
+#endif
+
+ if ((ret = ax8817x_read_cmd (dev, AX_CMD_SW_PHY_STATUS, 0, 0, 1,
+ &TempPhySelect)) < 0) {
+ deverr(dev, "read SW interface selection status register"
+ "failed: %d\n", ret);
+ goto err_out;
+ }
- msleep(150);
- if ((ret = asix_sw_reset(dev, AX_SWRESET_CLEAR)) < 0)
- goto out;
+ TempPhySelect &= 0x0C;
- msleep(150);
- if (embd_phy) {
- if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL)) < 0)
- goto out;
+ if (TempPhySelect == AX_PHYSEL_SSRMII) {
+ InternalPhy = false;
+ ax772b_data->OperationMode = OPERATION_MAC_MODE;
+ ax772b_data->PhySelect = 0x00;
+ }
+ else if (TempPhySelect == AX_PHYSEL_SSRRMII) {
+ InternalPhy = true;
+ ax772b_data->OperationMode = OPERATION_PHY_MODE;
+ ax772b_data->PhySelect = 0x00;
+ }
+ else if (TempPhySelect == AX_PHYSEL_SSMII) {
+ InternalPhy = true;
+ ax772b_data->OperationMode = OPERATION_MAC_MODE;
+ ax772b_data->PhySelect = 0x01;
}
else {
- if ((ret = asix_sw_reset(dev, AX_SWRESET_PRTE)) < 0)
- goto out;
+ deverr(dev, "Unknown MII type\n");
+ goto err_out;
}
- msleep(150);
- rx_ctl = asix_read_rx_ctl(dev);
- dbg("RX_CTL is 0x%04x after software reset", rx_ctl);
- if ((ret = asix_write_rx_ctl(dev, 0x0000)) < 0)
- goto out;
+ /* reload eeprom data */
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
+ AXGPIOS_RSE, 0, 0, NULL)) < 0) {
+ deverr(dev, "Failed to enable GPIO finction: %d", ret);
+ goto err_out;
+ }
+ msleep(5);
- rx_ctl = asix_read_rx_ctl(dev);
- dbg("RX_CTL is 0x%04x setting to 0x0000", rx_ctl);
+ /* Get the EEPROM data*/
+ if ((ret = ax8817x_read_cmd (dev, AX_CMD_READ_EEPROM,
+ 0x18, 0, 2, (void *)tmp16)) < 0) {
+ deverr(dev, "read SROM address 18h failed: %d", ret);
+ goto err_out;
+ }
+ le16_to_cpus(tmp16);
+ ax772b_data->psc = *tmp16 & 0xFF00;
+ /* End of get EEPROM data */
+
+ /* Get the MAC address from EEPROM */
+ memset(buf, 0, ETH_ALEN);
+ for (i = 0; i < (ETH_ALEN >> 1); i++) {
+ if ((ret = ax8817x_read_cmd (dev, AX_CMD_READ_EEPROM,
+ 0x04 + i, 0, 2, (buf + i * 2))) < 0) {
+ deverr(dev, "read SROM address 04h failed: %d", ret);
+ goto err_out;
+ }
+ }
- /* Get the MAC address */
- if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
- 0, 0, ETH_ALEN, buf)) < 0) {
- dbg("Failed to read MAC address: %d", ret);
- goto out;
+ /* Check for default ASIX MAC (e.g. 00:0e:c6:87:72:01) in case of no EEPROM being present */
+ if (!memcmp(buf, default_asix_mac, ETH_ALEN)) {
+ if (g_usr_mac && (g_usr_mac < 3)) {
+ /* Get user set MAC address */
+ if (g_usr_mac == 2) {
+ /* 0x100000 offset for 2nd Ethernet MAC */
+ g_mac_addr[3] += 0x10;
+ if (g_mac_addr[3] < 0x10)
+ devwarn(dev, "MAC address byte 3 (0x%02x) wrap around", g_mac_addr[3]);
+ }
+ memcpy(buf, g_mac_addr, ETH_ALEN);
+ g_usr_mac++;
+ } else devwarn(dev, "using default ASIX MAC");
}
memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+ /* Set the MAC address */
+ if ((ret = ax8817x_write_cmd (dev, AX88772_CMD_WRITE_NODE_ID,
+ 0, 0, ETH_ALEN, buf)) < 0) {
+ deverr(dev, "set MAC address failed: %d", ret);
+ goto err_out;
+ }
+
/* Initialize MII structure */
dev->mii.dev = dev->net;
- dev->mii.mdio_read = asix_mdio_read;
- dev->mii.mdio_write = asix_mdio_write;
- dev->mii.phy_id_mask = 0x1f;
- dev->mii.reg_num_mask = 0x1f;
- dev->mii.phy_id = asix_get_phy_addr(dev);
+ dev->mii.mdio_read = ax8817x_mdio_read_le;
+ dev->mii.mdio_write = ax88772b_mdio_write_le;
+ dev->mii.phy_id_mask = 0xff;
+ dev->mii.reg_num_mask = 0xff;
- phyid = asix_get_phyid(dev);
- dbg("PHYID=0x%08x", phyid);
+ /* Get the PHY id */
+ if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID,
+ 0, 0, 2, buf)) < 0) {
+ deverr(dev, "Error reading PHY ID: %02x", ret);
+ goto err_out;
+ } else if (ret < 2) {
+ /* this should always return 2 bytes */
+ deverr(dev, "Read PHYID returned less than 2 bytes: ret=%02x",
+ ret);
+ ret = -EIO;
+ goto err_out;
+ }
- if ((ret = asix_sw_reset(dev, AX_SWRESET_PRL)) < 0)
- goto out;
+ if (InternalPhy)
+ dev->mii.phy_id = *((u8 *)buf + 1);
+ else
+ dev->mii.phy_id = *((u8 *)buf);
- msleep(150);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
+ ax772b_data->PhySelect, 0, 0, NULL)) < 0) {
+ deverr(dev, "Select PHY #1 failed: %d", ret);
+ goto err_out;
+ }
- if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL)) < 0)
- goto out;
+#if 0
+ /* select the embedded 10/100 Ethernet PHY */
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
+ AX_PHYSEL_SSEN | AX_PHYSEL_PSEL | AX_PHYSEL_SSMII
+ , 0, 0, NULL)) < 0) {
+ deverr(dev, "Select PHY #1 failed: %d", ret);
+ goto err_out;
+ }
- msleep(150);
+ if(dev->mii.phy_id != 0x10) {
+ deverr(dev, "Got wrong PHY ID: %02x", dev->mii.phy_id);
+ ret = -EIO;
+ goto err_out;
+ }
+#endif
+ if ((ret = ax88772a_phy_powerup (dev)) < 0)
+ goto err_out;
+
+ /* stop MAC operation */
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
+ AX_RX_CTL_STOP, 0, 0, NULL)) < 0) {
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
+ goto err_out;
+ }
- dev->net->netdev_ops = &ax88772_netdev_ops;
- dev->net->ethtool_ops = &ax88772_ethtool_ops;
+ /* make sure the driver can enable sw mii operation */
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII,
+ 0, 0, 0, NULL)) < 0) {
+ deverr(dev, "Enabling software MII failed: %d", ret);
+ goto err_out;
+ }
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
+ dev->net->do_ioctl = ax8817x_ioctl;
+ dev->net->set_multicast_list = ax88772b_set_multicast;
+ dev->net->set_mac_address = ax8817x_set_mac_addr;
+#else
+ dev->net->netdev_ops = &ax88772b_netdev_ops;
+#endif
+
+ dev->net->ethtool_ops = &ax88772b_ethtool_ops;
+
+ /* Register suspend and resume functions */
+ data->suspend = ax88772b_suspend;
+ data->resume = ax88772b_resume;
+
+ if (ax772b_data->OperationMode == OPERATION_PHY_MODE)
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id
+ , MII_BMCR, 0x3900);
+
+ if (dev->mii.phy_id != 0x10)
+ ax8817x_mdio_write_le(dev->net, 0x10, MII_BMCR, 0x3900);
+
+
+ if (dev->mii.phy_id == 0x10 && ax772b_data->OperationMode
+ != OPERATION_PHY_MODE) {
+
+ *tmp16 = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, 0x12);
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, 0x12,
+ ((*tmp16 & 0xFF9F) | 0x0040));
+ }
+
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+ ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
- asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
- asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
- ADVERTISE_ALL | ADVERTISE_CSMA);
mii_nway_restart(&dev->mii);
- if ((ret = asix_write_medium_mode(dev, AX88772_MEDIUM_DEFAULT)) < 0)
- goto out;
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
+ 0, 0, 0, NULL)) < 0) {
+ deverr(dev, "Failed to write medium mode: %d", ret);
+ goto err_out;
+ }
- if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
- AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
- AX88772_IPG2_DEFAULT, 0, NULL)) < 0) {
- dbg("Write IPG,IPG1,IPG2 failed: %d", ret);
- goto out;
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
+ AX88772A_IPG0_DEFAULT | AX88772A_IPG1_DEFAULT << 8,
+ AX88772A_IPG2_DEFAULT, 0, NULL)) < 0) {
+ deverr(dev, "Failed to write interframe gap: %d", ret);
+ goto err_out;
}
- /* Set RX_CTL to default values with 2k buffer, and enable cactus */
- if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0)
- goto out;
+ dev->net->features |= NETIF_F_IP_CSUM;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)
+ dev->net->features |= NETIF_F_IPV6_CSUM;
+#endif
- rx_ctl = asix_read_rx_ctl(dev);
- dbg("RX_CTL is 0x%04x after all initializations", rx_ctl);
+ ax772b_data->checksum = AX_RX_CHECKSUM | AX_TX_CHECKSUM;
+ if ((ret = ax88772b_set_csums(dev)) < 0) {
+ deverr(dev, "Write RX_COE/TX_COE failed: %d", ret);
+ goto err_out;
+ }
- rx_ctl = asix_read_medium_status(dev);
- dbg("Medium Status is 0x%04x after all initializations", rx_ctl);
+ dev->rx_size = bsize & 0x07;
+ if (dev->udev->speed == USB_SPEED_HIGH) {
- /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
- if (dev->driver_info->flags & FLAG_FRAMING_AX) {
- /* hard_mtu is still the default - the device does not support
- jumbo eth frames */
+ if ((ret = ax8817x_write_cmd (dev, 0x2A,
+ AX88772B_BULKIN_SIZE[dev->rx_size].byte_cnt,
+ AX88772B_BULKIN_SIZE[dev->rx_size].threshold,
+ 0, NULL)) < 0) {
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
+ goto err_out;
+ }
+
+ dev->rx_urb_size = AX88772B_BULKIN_SIZE[dev->rx_size].size;
+ } else {
+ if ((ret = ax8817x_write_cmd (dev, 0x2A,
+ 0x8000, 0x8001, 0, NULL)) < 0) {
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
+ goto err_out;
+ }
dev->rx_urb_size = 2048;
}
- return 0;
-out:
+ /* Configure RX header type */
+ if ((ret = ax8817x_write_cmd (dev, AX_CMD_WRITE_RX_CTL,
+ (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_HEADER_DEFAULT),
+ 0, 0, NULL)) < 0) {
+ deverr(dev, "Reset RX_CTL failed: %d", ret);
+ goto err_out;
+ }
+
+ /* Overwrite power saving configuration from eeprom */
+ if ((ret = ax8817x_write_cmd (dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPRL | (ax772b_data->psc & 0x7FFF), 0, 0, NULL)) < 0) {
+ deverr(dev, "Failed to configure PHY power saving: %d", ret);
+ goto err_out;
+ }
+
+ if (ax772b_data->OperationMode == OPERATION_PHY_MODE)
+ netif_carrier_on(dev->net);
+
+ kfree (buf);
+ printk (version);
+
+ return ret;
+err_out:
+ destroy_workqueue (ax772b_data->ax_work);
+ kfree (buf);
+ kfree (ax772b_data);
return ret;
}
-static struct ethtool_ops ax88178_ethtool_ops = {
- .get_drvinfo = asix_get_drvinfo,
- .get_link = asix_get_link,
- .get_msglevel = usbnet_get_msglevel,
- .set_msglevel = usbnet_set_msglevel,
- .get_wol = asix_get_wol,
- .set_wol = asix_set_wol,
- .get_eeprom_len = asix_get_eeprom_len,
- .get_eeprom = asix_get_eeprom,
- .get_settings = usbnet_get_settings,
- .set_settings = usbnet_set_settings,
- .nway_reset = usbnet_nway_reset,
-};
+static void ax88772b_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
+
+ if (ax772b_data) {
+
+ flush_workqueue (ax772b_data->ax_work);
+ destroy_workqueue (ax772b_data->ax_work);
+
+ /* stop MAC operation */
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
+ AX_RX_CTL_STOP, 0, 0, NULL);
+
+ /* Power down PHY */
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPPD, 0, 0, NULL);
+
+ kfree (ax772b_data);
+ }
+}
-static int marvell_phy_init(struct usbnet *dev)
+static int
+ax88178_media_check (struct usbnet *dev, struct ax88178_data *ax178dataptr)
{
- struct asix_data *data = (struct asix_data *)&dev->data;
- u16 reg;
+ int fullduplex;
+ u16 tempshort = 0;
+ u16 media;
+ u16 advertise, lpa, result, stat1000;
+
+ advertise = ax8817x_mdio_read_le (dev->net,
+ dev->mii.phy_id, MII_ADVERTISE);
+ lpa = ax8817x_mdio_read_le (dev->net, dev->mii.phy_id, MII_LPA);
+ result = advertise & lpa;
+
+ stat1000 = ax8817x_mdio_read_le (dev->net,
+ dev->mii.phy_id, MII_STAT1000);
+
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
+ (ax178dataptr->LedMode == 1)) {
+ tempshort = ax8817x_mdio_read_le (dev->net,
+ dev->mii.phy_id, MARVELL_MANUAL_LED) & 0xfc0f;
+ }
- netdev_dbg(dev->net, "marvell_phy_init()\n");
+ fullduplex=1;
+ if (stat1000 & LPA_1000FULL) {
+ media = MEDIUM_GIGA_MODE | MEDIUM_FULL_DUPLEX_MODE |
+ MEDIUM_ENABLE_125MHZ | MEDIUM_ENABLE_RECEIVE;
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
+ (ax178dataptr->LedMode == 1))
+ tempshort|= 0x3e0;
+ } else if (result & LPA_100FULL) {
+ media = MEDIUM_FULL_DUPLEX_MODE | MEDIUM_ENABLE_RECEIVE |
+ MEDIUM_MII_100M_MODE;
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
+ (ax178dataptr->LedMode == 1))
+ tempshort|= 0x3b0;
+ } else if (result & LPA_100HALF) {
+ fullduplex = 0;
+ media = MEDIUM_ENABLE_RECEIVE | MEDIUM_MII_100M_MODE;
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
+ (ax178dataptr->LedMode == 1))
+ tempshort |= 0x3b0;
+ } else if (result & LPA_10FULL) {
+ media = MEDIUM_FULL_DUPLEX_MODE | MEDIUM_ENABLE_RECEIVE;
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
+ (ax178dataptr->LedMode == 1))
+ tempshort |= 0x2f0;
+ } else {
+ media = MEDIUM_ENABLE_RECEIVE;
+ fullduplex=0;
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
+ (ax178dataptr->LedMode == 1))
+ tempshort |= 0x02f0;
+ }
- reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_MARVELL_STATUS);
- netdev_dbg(dev->net, "MII_MARVELL_STATUS = 0x%04x\n", reg);
+ if ((ax178dataptr->PhyMode == PHY_MODE_MARVELL) &&
+ (ax178dataptr->LedMode == 1)) {
+ ax8817x_mdio_write_le (dev->net,
+ dev->mii.phy_id, MARVELL_MANUAL_LED, tempshort);
+ }
- asix_mdio_write(dev->net, dev->mii.phy_id, MII_MARVELL_CTRL,
- MARVELL_CTRL_RXDELAY | MARVELL_CTRL_TXDELAY);
+ media |= 0x0004;
+ if(ax178dataptr->UseRgmii)
+ media |= 0x0008;
+ if(fullduplex) {
+ media |= 0x0020; //ebable tx flow control as default;
+ media |= 0x0010; //ebable rx flow control as default;
+ }
- if (data->ledmode) {
- reg = asix_mdio_read(dev->net, dev->mii.phy_id,
- MII_MARVELL_LED_CTRL);
- netdev_dbg(dev->net, "MII_MARVELL_LED_CTRL (1) = 0x%04x\n", reg);
+ return media;
+}
- reg &= 0xf8ff;
- reg |= (1 + 0x0100);
- asix_mdio_write(dev->net, dev->mii.phy_id,
- MII_MARVELL_LED_CTRL, reg);
+static void Vitess_8601_Init (struct usbnet *dev, int State)
+{
+ u16 reg;
- reg = asix_mdio_read(dev->net, dev->mii.phy_id,
- MII_MARVELL_LED_CTRL);
- netdev_dbg(dev->net, "MII_MARVELL_LED_CTRL (2) = 0x%04x\n", reg);
- reg &= 0xfc0f;
+ switch (State) {
+ case 0: // tx, rx clock skew
+ ax8817x_swmii_mdio_write_le (dev->net, dev->mii.phy_id, 31, 1);
+ ax8817x_swmii_mdio_write_le (dev->net, dev->mii.phy_id, 28, 0);
+ ax8817x_swmii_mdio_write_le (dev->net, dev->mii.phy_id, 31, 0);
+ break;
+
+ case 1:
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 31, 0x52B5);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 18, 0x009E);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 17, 0xDD39);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0x87AA);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0xA7B4);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 18,
+ ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 18));
+
+ reg = (ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 17) & ~0x003f) | 0x003c;
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 17, reg);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0x87B4);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0xa794);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 18,
+ ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 18));
+
+ reg = (ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 17) & ~0x003f) | 0x003e;
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 17, reg);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0x8794);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 18, 0x00f7);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 17, 0xbe36);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0x879e);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0xa7a0);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 18,
+ ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 18));
+
+ reg = (ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 17) & ~0x003f) | 0x0034;
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 17, reg);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0x87a0);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 18, 0x003c);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 17, 0xf3cf);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0x87a2);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 18, 0x003c);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 17, 0xf3cf);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0x87a4);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 18, 0x003c);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 17, 0xd287);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0x87a6);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0xa7a8);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 18,
+ ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 18));
+
+ reg = (ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 17) & ~0x0fff) | 0x0125;
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 17, reg);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0x87a8);
+
+ // Enable Smart Pre-emphasis
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0xa7fa);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 18,
+ ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 18));
+
+ reg = (ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 17) & ~0x0008) | 0x0008;
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 17, reg);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0x87fa);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 31, 0);
+
+ break;
}
+}
- return 0;
+static void
+marvell_88E1510_magic_init(struct usbnet *dev)
+{
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 22, 0xff);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 17, 0x214b);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0x2144);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 17, 0x0c28);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0x2146);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 17, 0xb233);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0x214d);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 17, 0xcc0c);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0x2159);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 22, 0x00fb);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 7, 0xc00d);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 22, 0);
}
-static int marvell_led_status(struct usbnet *dev, u16 speed)
+static int
+ax88178_phy_init (struct usbnet *dev, struct ax88178_data *ax178dataptr)
{
- u16 reg = asix_mdio_read(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL);
+ int i;
+ u16 PhyAnar, PhyAuxCtrl, PhyCtrl, TempShort, PhyID1;
+ u16 PhyReg = 0;
- netdev_dbg(dev->net, "marvell_led_status() read 0x%04x\n", reg);
+ //Disable MII operation of AX88178 Hardware
+ ax8817x_write_cmd (dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
- /* Clear out the center LED bits - 0x03F0 */
- reg &= 0xfc0f;
- switch (speed) {
- case SPEED_1000:
- reg |= 0x03e0;
- break;
- case SPEED_100:
- reg |= 0x03b0;
- break;
- default:
- reg |= 0x02f0;
+ //Read SROM - MiiPhy Address (ID)
+ ax8817x_read_cmd (dev, AX_CMD_READ_PHY_ID, 0, 0, 2, &dev->mii.phy_id);
+ le32_to_cpus (&dev->mii.phy_id);
+
+ /* Initialize MII structure */
+ dev->mii.phy_id >>= 8;
+ dev->mii.phy_id &= PHY_ID_MASK;
+ dev->mii.dev = dev->net;
+ dev->mii.mdio_read = ax8817x_mdio_read_le;
+ dev->mii.mdio_write = ax8817x_mdio_write_le;
+ dev->mii.phy_id_mask = 0x3f;
+ dev->mii.reg_num_mask = 0x1f;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11)
+ dev->mii.supports_gmii = 1;
+#endif
+
+ if (ax178dataptr->PhyMode == PHY_MODE_MAC_TO_MAC_GMII)
+ {
+ ax178dataptr->UseRgmii = 0;
+ ax178dataptr->MediaLink = MEDIUM_GIGA_MODE |
+ MEDIUM_FULL_DUPLEX_MODE |
+ MEDIUM_ENABLE_125MHZ |
+ MEDIUM_ENABLE_RECEIVE |
+ MEDIUM_ENABLE_RX_FLOWCTRL |
+ MEDIUM_ENABLE_TX_FLOWCTRL;
+
+ goto SkipPhySetting;
}
- netdev_dbg(dev->net, "marvell_led_status() writing 0x%04x\n", reg);
- asix_mdio_write(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL, reg);
+ // test read phy register 2
+ if (!ax178dataptr->UseGpio0) {
+ i = 1000;
+ while (i--) {
+ PhyID1 = ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, GMII_PHY_OUI);
+ if ((PhyID1 == 0x000f) || (PhyID1 == 0x0141) ||
+ (PhyID1 == 0x0282) || (PhyID1 == 0x004d) ||
+ (PhyID1 == 0x0243) || (PhyID1 == 0x001C) ||
+ (PhyID1 == 0x0007))
+ break;
+ msleep(5);
+ }
+ if (i < 0)
+ return -EIO;
+ }
- return 0;
-}
+ ax178dataptr->UseRgmii = 0;
+ if (ax178dataptr->PhyMode == PHY_MODE_MARVELL) {
+ PhyReg = ax8817x_swmii_mdio_read_le(dev->net,
+ dev->mii.phy_id, 27);
+ if (!(PhyReg & 4) && !(ax178dataptr->LedMode & 0x10)) {
+ ax178dataptr->UseRgmii = 1;
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 20, 0x82);
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
+ } else if (ax178dataptr->LedMode & 0x10) {
+
+ ax178dataptr->UseRgmii = 1;
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
+ marvell_88E1510_magic_init(dev);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 22, 2);
+
+ PhyReg = ax8817x_swmii_mdio_read_le(dev->net,
+ dev->mii.phy_id, 21);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 21, PhyReg | 0x30);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 22, 0);
+
+ }
+ } else if ((ax178dataptr->PhyMode == PHY_MODE_AGERE_V0) ||
+ (ax178dataptr->PhyMode == PHY_MODE_AGERE_V0_GMII)) {
+ if (ax178dataptr->PhyMode == PHY_MODE_AGERE_V0) {
+ ax178dataptr->UseRgmii = 1;
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
+ }
+ } else if (ax178dataptr->PhyMode == PHY_MODE_CICADA_V1) {
+ // not Cameo
+ if (!ax178dataptr->UseGpio0 || ax178dataptr->LedMode) {
+ ax178dataptr->UseRgmii = 1;
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
+ }
-static int ax88178_link_reset(struct usbnet *dev)
-{
- u16 mode;
- struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
- struct asix_data *data = (struct asix_data *)&dev->data;
- u32 speed;
+ for (i = 0; i < (sizeof(CICADA_FAMILY_HWINIT) /
+ sizeof(CICADA_FAMILY_HWINIT[0])); i++) {
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id,
+ CICADA_FAMILY_HWINIT[i].offset,
+ CICADA_FAMILY_HWINIT[i].value);
+ }
- netdev_dbg(dev->net, "ax88178_link_reset()\n");
+ } else if (ax178dataptr->PhyMode == PHY_MODE_CICADA_V2) {
+ // not Cameo
+ if (!ax178dataptr->UseGpio0 || ax178dataptr->LedMode)
+ {
+ ax178dataptr->UseRgmii = 1;
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
+ }
- mii_check_media(&dev->mii, 1, 1);
- mii_ethtool_gset(&dev->mii, &ecmd);
- mode = AX88178_MEDIUM_DEFAULT;
- speed = ethtool_cmd_speed(&ecmd);
+ for (i = 0; i < (sizeof(CICADA_V2_HWINIT) /
+ sizeof(CICADA_V2_HWINIT[0])); i++) {
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, CICADA_V2_HWINIT[i].offset,
+ CICADA_V2_HWINIT[i].value);
+ }
+ } else if (ax178dataptr->PhyMode == PHY_MODE_CICADA_V2_ASIX) {
+ // not Cameo
+ if (!ax178dataptr->UseGpio0 || ax178dataptr->LedMode)
+ {
+ ax178dataptr->UseRgmii = 1;
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
+ }
- if (speed == SPEED_1000)
- mode |= AX_MEDIUM_GM;
- else if (speed == SPEED_100)
- mode |= AX_MEDIUM_PS;
- else
- mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM);
+ for (i = 0; i < (sizeof(CICADA_V2_HWINIT) /
+ sizeof(CICADA_V2_HWINIT[0])); i++) {
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, CICADA_V2_HWINIT[i].offset,
+ CICADA_V2_HWINIT[i].value);
+ }
+ } else if (ax178dataptr->PhyMode == PHY_MODE_RTL8211CL) {
+ ax178dataptr->UseRgmii = 1;
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
+ } else if (ax178dataptr->PhyMode == PHY_MODE_RTL8211BN) {
+ ax178dataptr->UseRgmii = 1;
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
+ } else if (ax178dataptr->PhyMode == PHY_MODE_RTL8251CL) {
+ ax178dataptr->UseRgmii = 1;
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
+ } else if (ax178dataptr->PhyMode == PHY_MODE_VSC8601) {
+ ax178dataptr->UseRgmii = 1;
+ ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
+// Vitess_8601_Init (dev, 0);
+ }
- mode |= AX_MEDIUM_ENCK;
+ if (ax178dataptr->PhyMode != PHY_MODE_ATTANSIC_V0) {
+ // software reset
+ ax8817x_swmii_mdio_write_le (
+ dev->net, dev->mii.phy_id, GMII_PHY_CONTROL,
+ ax8817x_swmii_mdio_read_le (
+ dev->net, dev->mii.phy_id, GMII_PHY_CONTROL)
+ | GMII_CONTROL_RESET);
+ msleep (1);
+ }
- if (ecmd.duplex == DUPLEX_FULL)
- mode |= AX_MEDIUM_FD;
- else
- mode &= ~AX_MEDIUM_FD;
+ if ((ax178dataptr->PhyMode == PHY_MODE_AGERE_V0) ||
+ (ax178dataptr->PhyMode == PHY_MODE_AGERE_V0_GMII)) {
+ if (ax178dataptr->PhyMode == PHY_MODE_AGERE_V0)
+ {
+ i = 1000;
+ while (i--)
+ {
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 21, 0x1001);
+
+ PhyReg = ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 21);
+ if ((PhyReg & 0xf00f) == 0x1001)
+ break;
+ }
+ if (i < 0)
+ return -EIO;
+ }
+
+ if (ax178dataptr->LedMode == 4) {
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 28, 0x7417);
+ } else if (ax178dataptr->LedMode == 9) {
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 28, 0x7a10);
+ } else if (ax178dataptr->LedMode == 10) {
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 28, 0x7a13);
+ }
+
+ for (i = 0; i < (sizeof(AGERE_FAMILY_HWINIT) /
+ sizeof(AGERE_FAMILY_HWINIT[0])); i++) {
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, AGERE_FAMILY_HWINIT[i].offset,
+ AGERE_FAMILY_HWINIT[i].value);
+ }
+ } else if (ax178dataptr->PhyMode == PHY_MODE_RTL8211CL) {
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 0x1f, 0x0005);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 0x0c, 0);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 0x01,
+ (ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 0x01) | 0x0080));
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 0x1f, 0);
+
+ if (ax178dataptr->LedMode == 12) {
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 0x1f, 0x0002);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 0x1a, 0x00cb);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 0x1f, 0);
+ }
+ } else if (ax178dataptr->PhyMode == PHY_MODE_VSC8601) {
+ Vitess_8601_Init (dev, 1);
+ }
+
+ // read phy register 0
+ PhyCtrl = ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, GMII_PHY_CONTROL);
+ TempShort = PhyCtrl;
+ PhyCtrl &= ~(GMII_CONTROL_POWER_DOWN | GMII_CONTROL_ISOLATE);
+ if (PhyCtrl != TempShort) {
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, GMII_PHY_CONTROL, PhyCtrl);
+ }
+
+ // led
+ if (ax178dataptr->PhyMode == PHY_MODE_MARVELL) {
+ if (ax178dataptr->LedMode == 1) {
+
+ PhyReg = (ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 24) & 0xf8ff) | (1 + 0x100);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 24, PhyReg);
+ PhyReg = ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 25) & 0xfc0f;
+
+ } else if (ax178dataptr->LedMode == 2) {
+
+ PhyReg = (ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 24) & 0xf886) |
+ (1 + 0x10 + 0x300);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 24, PhyReg);
+
+ } else if (ax178dataptr->LedMode == 5) {
+
+ PhyReg = (ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 24) & 0xf8be) |
+ (1 + 0x40 + 0x300);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 24, PhyReg);
+
+ } else if (ax178dataptr->LedMode == 7) {
+
+ PhyReg = (ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 24) & 0xf8ff) |
+ (1 + 0x100);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 24, PhyReg);
+
+ } else if (ax178dataptr->LedMode == 8) {
+
+ PhyReg = (ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 24) & 0xf8be) |
+ (1 + 0x40 + 0x100);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 24, PhyReg);
+
+ } else if (ax178dataptr->LedMode == 11) {
+
+ PhyReg = ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 24) & 0x4106;
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 24, PhyReg);
+
+ } else if (ax178dataptr->LedMode == 0x10) {
+ //MARVEL 88e1510 use default led setting
+ }
+
+ } else if ((ax178dataptr->PhyMode == PHY_MODE_CICADA_V1) ||
+ (ax178dataptr->PhyMode == PHY_MODE_CICADA_V2) ||
+ (ax178dataptr->PhyMode == PHY_MODE_CICADA_V2_ASIX)) {
+
+ if (ax178dataptr->LedMode == 3) {
+
+ PhyReg = (ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 27) & 0xFCFF) | 0x0100;
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 27, PhyReg);
+ }
+
+ }
+
+ if (ax178dataptr->PhyMode == PHY_MODE_MARVELL)
+ {
+ if (ax178dataptr->LedMode == 1)
+ PhyReg |= 0x3f0;
+ }
+
+ PhyAnar = 1 | (GMII_ANAR_PAUSE | GMII_ANAR_100TXFD | GMII_ANAR_100TX |
+ GMII_ANAR_10TFD | GMII_ANAR_10T | GMII_ANAR_ASYM_PAUSE);
+
+ PhyAuxCtrl = GMII_1000_AUX_CTRL_FD_CAPABLE;
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, GMII_PHY_ANAR, PhyAnar);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, GMII_PHY_1000BT_CONTROL, PhyAuxCtrl);
+
+ if (ax178dataptr->PhyMode == PHY_MODE_VSC8601)
+ {
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 31, 0x52B5);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0xA7F8);
+
+ TempShort = ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 17) & (~0x0018);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 17, TempShort);
+
+ TempShort = ax8817x_swmii_mdio_read_le (dev->net,
+ dev->mii.phy_id, 18);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 18, TempShort);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 16, 0x87F8);
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 31, 0);
+ }
+
+ if (ax178dataptr->PhyMode == PHY_MODE_ATTANSIC_V0) {
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, GMII_PHY_CONTROL, 0x9000);
+
+ } else {
+ PhyCtrl &= ~GMII_CONTROL_LOOPBACK;
+ PhyCtrl |= (GMII_CONTROL_ENABLE_AUTO | GMII_CONTROL_START_AUTO);
+
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, GMII_PHY_CONTROL, PhyCtrl);
+ }
+
+ if (ax178dataptr->PhyMode == PHY_MODE_MARVELL) {
+ if (ax178dataptr->LedMode == 1)
+ ax8817x_swmii_mdio_write_le (dev->net,
+ dev->mii.phy_id, 25, PhyReg);
+ }
- netdev_dbg(dev->net, "ax88178_link_reset() speed: %u duplex: %d setting mode to 0x%04x\n",
- speed, ecmd.duplex, mode);
+SkipPhySetting:
- asix_write_medium_mode(dev, mode);
+ ax8817x_write_cmd (dev, AX_CMD_WRITE_MEDIUM_MODE,
+ ax178dataptr->MediaLink, 0, 0, NULL);
- if (data->phymode == PHY_MODE_MARVELL && data->ledmode)
- marvell_led_status(dev, speed);
+ ax8817x_write_cmd (dev, AX_CMD_WRITE_IPG0,
+ AX88772_IPG0_DEFAULT | (AX88772_IPG1_DEFAULT << 8),
+ AX88772_IPG2_DEFAULT, 0, NULL);
+
+ msleep (1);
+
+ ax8817x_write_cmd (dev, AX_CMD_SET_HW_MII, 0, 0, 0, NULL);
return 0;
}
-static void ax88178_set_mfb(struct usbnet *dev)
+static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
{
- u16 mfb = AX_RX_CTL_MFB_16384;
- u16 rxctl;
- u16 medium;
- int old_rx_urb_size = dev->rx_urb_size;
+ int ret;
+ void *buf;
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
+ struct ax88178_data *ax178dataptr = NULL;
- if (dev->hard_mtu < 2048) {
- dev->rx_urb_size = 2048;
- mfb = AX_RX_CTL_MFB_2048;
- } else if (dev->hard_mtu < 4096) {
- dev->rx_urb_size = 4096;
- mfb = AX_RX_CTL_MFB_4096;
- } else if (dev->hard_mtu < 8192) {
- dev->rx_urb_size = 8192;
- mfb = AX_RX_CTL_MFB_8192;
- } else if (dev->hard_mtu < 16384) {
+ axusbnet_get_endpoints(dev,intf);
+
+ buf = kmalloc(6, GFP_KERNEL);
+ if(!buf) {
+ deverr(dev, "Cannot allocate memory for buffer");
+ return -ENOMEM;
+ }
+
+ /* allocate 178 data */
+ ax178dataptr = kmalloc (sizeof (*ax178dataptr), GFP_KERNEL);
+ if (!ax178dataptr) {
+ deverr(dev, "Cannot allocate memory for AX88178 data");
+ ret = -ENOMEM;
+ goto error_out;
+ }
+ memset (ax178dataptr, 0, sizeof (struct ax88178_data));
+ dev->priv = ax178dataptr;
+ /* end of allocate 178 data */
+
+ /* Get the EEPROM data*/
+ if ((ret = ax8817x_read_cmd (dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2,
+ (void *)(&ax178dataptr->EepromData))) < 0) {
+ deverr(dev, "read SROM address 17h failed: %d", ret);
+ goto error_out;
+ }
+ le16_to_cpus (&ax178dataptr->EepromData);
+ /* End of get EEPROM data */
+
+ if (ax178dataptr->EepromData == 0xffff) {
+ ax178dataptr->PhyMode = PHY_MODE_MARVELL;
+ ax178dataptr->LedMode = 0;
+ ax178dataptr->UseGpio0 = 1; //True
+ } else {
+ ax178dataptr->PhyMode = (u8)(ax178dataptr->EepromData &
+ EEPROMMASK);
+ ax178dataptr->LedMode = (u8)(ax178dataptr->EepromData >> 8);
+ if (ax178dataptr->LedMode == 6) // for buffalo new (use gpio2)
+ ax178dataptr->LedMode = 1;
+ else if (ax178dataptr->LedMode == 1)
+ ax178dataptr->BuffaloOld = 1;
+
+
+ if(ax178dataptr->EepromData & 0x80) {
+ ax178dataptr->UseGpio0=0; //MARVEL se and other
+ } else {
+ ax178dataptr->UseGpio0=1; //cameo
+ }
+ }
+
+ if (ax178dataptr->UseGpio0) {
+
+ if (ax178dataptr->PhyMode == PHY_MODE_MARVELL) {
+
+ if ((ret = ax8817x_write_cmd (dev, AX_CMD_WRITE_GPIOS,
+ AXGPIOS_GPO0EN | AXGPIOS_RSE,
+ 0, 0, NULL)) < 0) {
+ deverr(dev, "write GPIO failed: %d", ret);
+ goto error_out;
+ }
+
+ msleep (25);
+
+ if ((ret = ax8817x_write_cmd (dev, AX_CMD_WRITE_GPIOS,
+ (AXGPIOS_GPO2 | AXGPIOS_GPO2EN |
+ AXGPIOS_GPO0EN), 0, 0, NULL)) < 0) {
+ deverr(dev, "write GPIO failed: %d", ret);
+ goto error_out;
+ }
+
+ msleep (15);
+
+ if ((ret = ax8817x_write_cmd (dev, AX_CMD_WRITE_GPIOS,
+ AXGPIOS_GPO2EN | AXGPIOS_GPO0EN,
+ 0, 0, NULL)) < 0) {
+ deverr(dev, "write GPIO failed: %d", ret);
+ goto error_out;
+ }
+
+ msleep (245);
+
+ if ((ret = ax8817x_write_cmd (dev, AX_CMD_WRITE_GPIOS,
+ (AXGPIOS_GPO2 | AXGPIOS_GPO2EN |
+ AXGPIOS_GPO0EN), 0, 0, NULL)) < 0) {
+ deverr(dev, "write GPIO failed: %d", ret);
+ goto error_out;
+ }
+
+ } else { // vitesse
+
+ if ((ret = ax8817x_write_cmd (dev, AX_CMD_WRITE_GPIOS,
+ (AXGPIOS_RSE | AXGPIOS_GPO0EN |
+ AXGPIOS_GPO0), 0, 0, NULL)) < 0) {
+ deverr(dev, "write GPIO failed: %d", ret);
+ goto error_out;
+ }
+
+ msleep (25);
+
+ if ((ret = ax8817x_write_cmd (dev, AX_CMD_WRITE_GPIOS,
+ (AXGPIOS_GPO0EN | AXGPIOS_GPO0 |
+ AXGPIOS_GPO2EN | AXGPIOS_GPO2),
+ 0, 0, NULL)) < 0) {
+ deverr(dev, "write GPIO failed: %d", ret);
+ goto error_out;
+ }
+
+ msleep (25);
+
+ if ((ret = ax8817x_write_cmd (dev, AX_CMD_WRITE_GPIOS,
+ (AXGPIOS_GPO0EN | AXGPIOS_GPO0 |
+ AXGPIOS_GPO2EN), 0, 0, NULL)) < 0) {
+ deverr(dev, "write GPIO failed: %d", ret);
+ goto error_out;
+ }
+
+ msleep (245);
+
+ if ((ret = ax8817x_write_cmd (dev, AX_CMD_WRITE_GPIOS,
+ (AXGPIOS_GPO0EN | AXGPIOS_GPO0 |
+ AXGPIOS_GPO2EN | AXGPIOS_GPO2),
+ 0, 0, NULL)) < 0) {
+ deverr(dev, "write GPIO failed: %d", ret);
+ goto error_out;
+ }
+ }
+ } else { // use gpio1
+
+ if ((ret = ax8817x_write_cmd (dev, AX_CMD_WRITE_GPIOS,
+ (AXGPIOS_GPO1 |AXGPIOS_GPO1EN | AXGPIOS_RSE),
+ 0, 0, NULL)) < 0) {
+ deverr(dev, "write GPIO failed: %d", ret);
+ goto error_out;
+ }
+
+ if (ax178dataptr->BuffaloOld) {
+
+ msleep (350);
+
+ if ((ret = ax8817x_write_cmd (dev, AX_CMD_WRITE_GPIOS,
+ AXGPIOS_GPO1EN, 0, 0, NULL)) < 0) {
+ deverr(dev, "write GPIO failed: %d", ret);
+ goto error_out;
+ }
+
+ msleep (350);
+
+ if ((ret = ax8817x_write_cmd (dev, AX_CMD_WRITE_GPIOS,
+ AXGPIOS_GPO1EN | AXGPIOS_GPO1,
+ 0, 0, NULL)) < 0) {
+ deverr(dev, "write GPIO failed: %d", ret);
+ goto error_out;
+ }
+ }
+ else
+ {
+ msleep (25);
+
+ if ((ret = ax8817x_write_cmd (dev, AX_CMD_WRITE_GPIOS,
+ (AXGPIOS_GPO1EN | AXGPIOS_GPO1 |
+ AXGPIOS_GPO2EN | AXGPIOS_GPO2),
+ 0, 0, NULL)) < 0) {
+ deverr(dev, "write GPIO failed: %d", ret);
+ goto error_out;
+ }
+
+ msleep (25);
+
+ if ((ret = ax8817x_write_cmd (dev, AX_CMD_WRITE_GPIOS,
+ (AXGPIOS_GPO1EN | AXGPIOS_GPO1 |
+ AXGPIOS_GPO2EN), 0, 0, NULL)) < 0) {
+ deverr(dev, "write GPIO failed: %d", ret);
+ goto error_out;
+ }
+
+ msleep (245);
+
+ if ((ret = ax8817x_write_cmd (dev, AX_CMD_WRITE_GPIOS,
+ (AXGPIOS_GPO1EN | AXGPIOS_GPO1 |
+ AXGPIOS_GPO2EN | AXGPIOS_GPO2),
+ 0, 0, NULL)) < 0) {
+ deverr(dev, "write GPIO failed: %d", ret);
+ goto error_out;
+ }
+ }
+ }
+
+ if ((ret = ax8817x_write_cmd(dev,
+ AX_CMD_SW_PHY_SELECT, 0, 0, 0, NULL)) < 0) {
+ deverr(dev, "Select PHY failed: %d", ret);
+ goto error_out;
+ }
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPPD | AX_SWRESET_PRL, 0, 0, NULL)) < 0) {
+ deverr(dev, "Issue sw reset failed: %d", ret);
+ goto error_out;
+ }
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
+ 0, 0, 0, NULL)) < 0) {
+ deverr(dev, "Issue rx ctrl failed: %d", ret);
+ goto error_out;
+ }
+
+ /* Get the MAC address */
+ memset(buf, 0, ETH_ALEN);
+ if ((ret = ax8817x_read_cmd (dev, AX88772_CMD_READ_NODE_ID,
+ 0, 0, ETH_ALEN, buf)) < 0) {
+ deverr(dev, "read AX_CMD_READ_NODE_ID failed: %d", ret);
+ goto error_out;
+ }
+ memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+ /* End of get MAC address */
+
+ if ((ret = ax88178_phy_init (dev, ax178dataptr)) < 0)
+ goto error_out;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
+ dev->net->do_ioctl = ax8817x_ioctl;
+ dev->net->set_multicast_list = ax88178_set_multicast;
+ dev->net->set_mac_address = ax88178_set_mac_addr;
+#else
+ dev->net->netdev_ops = &ax88178_netdev_ops;
+#endif
+ dev->net->ethtool_ops = &ax8817x_ethtool_ops;
+
+ /* Register suspend and resume functions */
+ data->suspend = ax88772_suspend;
+ data->resume = ax88772_resume;
+
+ if (dev->driver_info->flags & FLAG_FRAMING_AX) {
dev->rx_urb_size = 16384;
- mfb = AX_RX_CTL_MFB_16384;
}
- rxctl = asix_read_rx_ctl(dev);
- asix_write_rx_ctl(dev, (rxctl & ~AX_RX_CTL_MFB_16384) | mfb);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
+ (AX_RX_CTL_MFB | AX_RX_CTL_START | AX_RX_CTL_AB),
+ 0, 0, NULL)) < 0) {
+ deverr(dev, "write RX ctrl reg failed: %d", ret);
+ goto error_out;
+ }
- medium = asix_read_medium_status(dev);
- if (dev->net->mtu > 1500)
- medium |= AX_MEDIUM_JFE;
- else
- medium &= ~AX_MEDIUM_JFE;
- asix_write_medium_mode(dev, medium);
+ kfree (buf);
+ printk (version);
+ return ret;
- if (dev->rx_urb_size > old_rx_urb_size)
- usbnet_unlink_rx_urbs(dev);
+error_out:
+ if (ax178dataptr)
+ kfree (ax178dataptr);
+ kfree (buf);
+ return ret;
}
-static int ax88178_change_mtu(struct net_device *net, int new_mtu)
+static void ax88178_unbind(struct usbnet *dev, struct usb_interface *intf)
{
- struct usbnet *dev = netdev_priv(net);
- int ll_mtu = new_mtu + net->hard_header_len + 4;
+ struct ax88178_data *ax178dataptr = (struct ax88178_data *)dev->priv;
- netdev_dbg(dev->net, "ax88178_change_mtu() new_mtu=%d\n", new_mtu);
+ if (ax178dataptr) {
- if (new_mtu <= 0 || ll_mtu > 16384)
- return -EINVAL;
+ /* stop MAC operation */
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
+ AX_RX_CTL_STOP, 0, 0, NULL);
+
+ kfree (ax178dataptr);
+ }
+}
+
+static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+ u8 *head;
+ u32 header;
+ char *packet;
+ struct sk_buff *ax_skb;
+ u16 size;
+
+ head = (u8 *) skb->data;
+ memcpy(&header, head, sizeof(header));
+ le32_to_cpus(&header);
+ packet = head + sizeof(header);
- if ((ll_mtu % dev->maxpacket) == 0)
- return -EDOM;
+ skb_pull(skb, 4);
- net->mtu = new_mtu;
- dev->hard_mtu = net->mtu + net->hard_header_len;
- ax88178_set_mfb(dev);
+ while (skb->len > 0) {
+ if ((short)(header & 0x0000ffff) !=
+ ~((short)((header & 0xffff0000) >> 16))) {
+ deverr(dev, "header length data is error 0x%08x, %d\n",
+ header, skb->len);
+ }
+ /* get the packet length */
+ size = (u16) (header & 0x0000ffff);
- return 0;
+ if ((skb->len) - ((size + 1) & 0xfffe) == 0) {
+
+ /* Make sure ip header is aligned on 32-bit boundary */
+ if (!((unsigned long)skb->data & 0x02)) {
+ memmove (skb->data - 2, skb->data, size);
+ skb->data -= 2;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+ skb->tail = skb->data + size;
+#else
+ skb_set_tail_pointer (skb, size);
+#endif
+ }
+ skb->truesize = size + sizeof(struct sk_buff);
+ return 2;
+ }
+
+ if (size > ETH_FRAME_LEN) {
+ deverr(dev, "invalid rx length %d", size);
+ return 0;
+ }
+ ax_skb = skb_clone(skb, GFP_ATOMIC);
+ if (ax_skb) {
+
+ /* Make sure ip header is aligned on 32-bit boundary */
+ if (!((unsigned long)packet & 0x02)) {
+ memmove (packet - 2, packet, size);
+ packet -= 2;
+ }
+ ax_skb->data = packet;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+ ax_skb->tail = packet + size;
+#else
+ skb_set_tail_pointer (ax_skb, size);
+#endif
+ ax_skb->truesize = size + sizeof(struct sk_buff);
+ axusbnet_skb_return(dev, ax_skb);
+
+ } else {
+ return 0;
+ }
+
+ skb_pull(skb, (size + 1) & 0xfffe);
+
+ if (skb->len == 0)
+ break;
+
+ head = (u8 *) skb->data;
+ memcpy(&header, head, sizeof(header));
+ le32_to_cpus(&header);
+ packet = head + sizeof(header);
+ skb_pull(skb, 4);
+ }
+
+ if (skb->len < 0) {
+ deverr(dev, "invalid rx length %d", skb->len);
+ return 0;
+ }
+ return 1;
}
-static const struct net_device_ops ax88178_netdev_ops = {
- .ndo_open = usbnet_open,
- .ndo_stop = usbnet_stop,
- .ndo_start_xmit = usbnet_start_xmit,
- .ndo_tx_timeout = usbnet_tx_timeout,
- .ndo_set_mac_address = asix_set_mac_address,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_multicast_list = asix_set_multicast,
- .ndo_do_ioctl = asix_ioctl,
- .ndo_change_mtu = ax88178_change_mtu,
-};
+static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
+{
+ int padlen = ((skb->len + 4) % 512) ? 0 : 4;
+ u32 packet_len;
+ u32 padbytes = 0xffff0000;
-static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
+#if (!AX_FORCE_BUFF_ALIGN)
+ int headroom = skb_headroom(skb);
+ int tailroom = skb_tailroom(skb);
+
+ if ((!skb_cloned(skb))
+ && ((headroom + tailroom) >= (4 + padlen))) {
+ if ((headroom < 4) || (tailroom < padlen)) {
+ skb->data = memmove(skb->head + 4, skb->data, skb->len);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+ skb->tail = skb->data + skb->len;
+#else
+ skb_set_tail_pointer (skb, skb->len);
+#endif
+ }
+ } else
+#endif
+ {
+ struct sk_buff *skb2;
+ skb2 = skb_copy_expand(skb, 4, padlen, flags);
+ dev_kfree_skb_any(skb);
+ skb = skb2;
+ if (!skb)
+ return NULL;
+ }
+
+ skb_push(skb, 4);
+ packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
+ cpu_to_le32s(&packet_len);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+ memcpy(skb->data, &packet_len, sizeof(packet_len));
+#else
+ skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
+#endif
+
+ if ((skb->len % 512) == 0) {
+ cpu_to_le32s(&padbytes);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+ memcpy(skb->tail, &padbytes, sizeof(padbytes));
+#else
+ memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
+#endif
+ skb_put(skb, sizeof(padbytes));
+ }
+ return skb;
+}
+
+static void
+ax88772b_rx_checksum (struct sk_buff *skb, struct ax88772b_rx_header *rx_hdr)
{
- struct asix_data *data = (struct asix_data *)&dev->data;
- int ret;
- u8 buf[ETH_ALEN];
- __le16 eeprom;
- u8 status;
- int gpio0 = 0;
- u32 phyid;
+ skb->ip_summed = CHECKSUM_NONE;
+
+ /* checksum error bit is set */
+ if (rx_hdr->l3_csum_err || rx_hdr->l4_csum_err) {
+ return;
+ }
+
+ /* It must be a TCP or UDP packet with a valid checksum */
+ if ((rx_hdr->l4_type == AX_RXHDR_L4_TYPE_TCP) ||
+ (rx_hdr->l4_type == AX_RXHDR_L4_TYPE_UDP)) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ }
+}
+
+static int ax88772b_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+ struct ax88772b_rx_header rx_hdr;
+ struct sk_buff *ax_skb;
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
- usbnet_get_endpoints(dev,intf);
+ while (skb->len > 0) {
- asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status);
- dbg("GPIO Status: 0x%04x", status);
+ le16_to_cpus((u16 *)skb->data);
+ le16_to_cpus(((u16 *)skb->data) + 1);
- asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0, 0, 0, NULL);
- asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2, &eeprom);
- asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0, 0, 0, NULL);
+ memcpy (&rx_hdr, skb->data, sizeof (struct ax88772b_rx_header));
- dbg("EEPROM index 0x17 is 0x%04x", eeprom);
+ if ((short)rx_hdr.len != (~((short)rx_hdr.len_bar) & 0x7FF)) {
+ return 0;
+ }
- if (eeprom == cpu_to_le16(0xffff)) {
- data->phymode = PHY_MODE_MARVELL;
- data->ledmode = 0;
- gpio0 = 1;
- } else {
- data->phymode = le16_to_cpu(eeprom) & 7;
- data->ledmode = le16_to_cpu(eeprom) >> 8;
- gpio0 = (le16_to_cpu(eeprom) & 0x80) ? 0 : 1;
+ if (rx_hdr.len > (ETH_FRAME_LEN + 4)) {
+ deverr(dev, "invalid rx length %d", rx_hdr.len);
+ return 0;
+ }
+
+ if (skb->len - ((rx_hdr.len +
+ sizeof (struct ax88772b_rx_header) + 3) &
+ 0xfffc) == 0) {
+ skb_pull(skb, sizeof (struct ax88772b_rx_header));
+ skb->len = rx_hdr.len;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+ skb->tail = skb->data + rx_hdr.len;
+#else
+ skb_set_tail_pointer(skb, rx_hdr.len);
+#endif
+ skb->truesize = rx_hdr.len + sizeof(struct sk_buff);
+
+ if (ax772b_data->checksum & AX_RX_CHECKSUM)
+ ax88772b_rx_checksum (skb, &rx_hdr);
+
+ return 2;
+ }
+
+ ax_skb = skb_clone(skb, GFP_ATOMIC);
+ if (ax_skb) {
+ ax_skb->len = rx_hdr.len;
+ ax_skb->data = skb->data +
+ sizeof (struct ax88772b_rx_header);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+ ax_skb->tail = ax_skb->data + rx_hdr.len;
+#else
+ skb_set_tail_pointer(ax_skb, rx_hdr.len);
+#endif
+ ax_skb->truesize = rx_hdr.len + sizeof(struct sk_buff);
+
+ if (ax772b_data->checksum & AX_RX_CHECKSUM) {
+ ax88772b_rx_checksum (ax_skb, &rx_hdr);
+ }
+
+ axusbnet_skb_return(dev, ax_skb);
+
+ } else {
+ return 0;
+ }
+
+ skb_pull(skb, ((rx_hdr.len +
+ sizeof (struct ax88772b_rx_header) + 3)
+ & 0xfffc));
}
- dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode);
- asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40);
- if ((le16_to_cpu(eeprom) >> 8) != 1) {
- asix_write_gpio(dev, 0x003c, 30);
- asix_write_gpio(dev, 0x001c, 300);
- asix_write_gpio(dev, 0x003c, 30);
- } else {
- dbg("gpio phymode == 1 path");
- asix_write_gpio(dev, AX_GPIO_GPO1EN, 30);
- asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30);
+ if (skb->len < 0) {
+ deverr(dev, "invalid rx length %d", skb->len);
+ return 0;
}
+ return 1;
+}
- asix_sw_reset(dev, 0);
- msleep(150);
+static struct sk_buff *
+ax88772b_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
+{
+ int padlen = ((skb->len + 4) % 512) ? 0 : 4;
+ u32 packet_len;
+ u32 padbytes = 0xffff0000;
- asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD);
- msleep(150);
+#if (!AX_FORCE_BUFF_ALIGN)
+ int headroom = skb_headroom(skb);
+ int tailroom = skb_tailroom(skb);
- asix_write_rx_ctl(dev, 0);
+ if ((!skb_cloned(skb))
+ && ((headroom + tailroom) >= (4 + padlen))) {
+ if ((headroom < 4) || (tailroom < padlen)) {
+ skb->data = memmove(skb->head + 4, skb->data, skb->len);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+ skb->tail = skb->data + skb->len;
+#else
+ skb_set_tail_pointer(skb, skb->len);
+#endif
+ }
+ } else
+#endif
+ {
+ struct sk_buff *skb2;
+ skb2 = skb_copy_expand(skb, 4, padlen, flags);
+ dev_kfree_skb_any(skb);
+ skb = skb2;
+ if (!skb)
+ return NULL;
+ }
- /* Get the MAC address */
- if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
- 0, 0, ETH_ALEN, buf)) < 0) {
- dbg("Failed to read MAC address: %d", ret);
- goto out;
+ skb_push(skb, 4);
+ packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
+
+ cpu_to_le32s (&packet_len);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+ memcpy(skb->data, &packet_len, sizeof(packet_len));
+#else
+ skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
+#endif
+
+ if ((skb->len % 512) == 0) {
+ cpu_to_le32s (&padbytes);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+ memcpy(skb->tail, &padbytes, sizeof(padbytes));
+#else
+ memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
+#endif
+ skb_put(skb, sizeof(padbytes));
}
- memcpy(dev->net->dev_addr, buf, ETH_ALEN);
- /* Initialize MII structure */
- dev->mii.dev = dev->net;
- dev->mii.mdio_read = asix_mdio_read;
- dev->mii.mdio_write = asix_mdio_write;
- dev->mii.phy_id_mask = 0x1f;
- dev->mii.reg_num_mask = 0xff;
- dev->mii.supports_gmii = 1;
- dev->mii.phy_id = asix_get_phy_addr(dev);
+ return skb;
+}
- dev->net->netdev_ops = &ax88178_netdev_ops;
- dev->net->ethtool_ops = &ax88178_ethtool_ops;
+static const u8 ChkCntSel [6][3] =
+{
+ {12, 23, 31},
+ {12, 31, 23},
+ {23, 31, 12},
+ {23, 12, 31},
+ {31, 12, 23},
+ {31, 23, 12}
+};
- phyid = asix_get_phyid(dev);
- dbg("PHYID=0x%08x", phyid);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+static void ax88772_link_reset (void *data)
+{
+ struct usbnet *dev = (struct usbnet *)data;
+ struct ax88772_data *ax772_data = (struct ax88772_data *)dev->priv;
+#else
+static void ax88772_link_reset (struct work_struct *work)
+{
+ struct ax88772_data *ax772_data = container_of (work,
+ struct ax88772_data, check_link);
+ struct usbnet *dev = ax772_data->dev;
+#endif
+
+ if (ax772_data->Event == AX_SET_RX_CFG) {
+ u16 bmcr;
+ u16 mode;
+
+ ax772_data->Event = AX_NOP;
+
+ mode = AX88772_MEDIUM_DEFAULT;
+
+ bmcr = ax8817x_mdio_read_le(dev->net,
+ dev->mii.phy_id, MII_BMCR);
+ if (!(bmcr & BMCR_FULLDPLX))
+ mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
+ if (!(bmcr & BMCR_SPEED100))
+ mode &= ~AX88772_MEDIUM_100MB;
+
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
+ mode, 0, 0, NULL);
+ return;
+ }
+
+ switch (ax772_data->Event) {
+ case WAIT_AUTONEG_COMPLETE:
+ if (jiffies > (ax772_data->autoneg_start + 5 * HZ)) {
+ ax772_data->Event = PHY_POWER_DOWN;
+ ax772_data->TickToExpire = 23;
+ }
+ break;
+ case PHY_POWER_DOWN:
+ if (ax772_data->TickToExpire == 23) {
+ /* Set Phy Power Down */
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPPD,
+ 0, 0, NULL);
+ --ax772_data->TickToExpire;
+ } else if (--ax772_data->TickToExpire == 0) {
+ /* Set Phy Power Up */
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPRL, 0, 0, NULL);
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPPD | AX_SWRESET_IPRL, 0, 0, NULL);
+ msleep(10);
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPRL, 0, 0, NULL);
+ msleep(60);
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_CLEAR, 0, 0, NULL);
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPRL, 0, 0, NULL);
+
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id,
+ MII_ADVERTISE,
+ ADVERTISE_ALL | ADVERTISE_CSMA |
+ ADVERTISE_PAUSE_CAP);
+ mii_nway_restart(&dev->mii);
+
+ ax772_data->Event = PHY_POWER_UP;
+ ax772_data->TickToExpire = 47;
+ }
+ break;
+ case PHY_POWER_UP:
+ if (--ax772_data->TickToExpire == 0) {
+ ax772_data->Event = PHY_POWER_DOWN;
+ ax772_data->TickToExpire = 23;
+ }
+ break;
+ default:
+ break;
+ }
+ return;
+}
- if (data->phymode == PHY_MODE_MARVELL) {
- marvell_phy_init(dev);
- msleep(60);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+static void ax88772a_link_reset (void *data)
+{
+ struct usbnet *dev = (struct usbnet *)data;
+ struct ax88772a_data *ax772a_data = (struct ax88772a_data *)dev->priv;
+#else
+static void ax88772a_link_reset (struct work_struct *work)
+{
+ struct ax88772a_data *ax772a_data = container_of (work,
+ struct ax88772a_data, check_link);
+ struct usbnet *dev = ax772a_data->dev;
+#endif
+ int PowSave = (ax772a_data->EepromData >> 14);
+ u16 phy_reg;
+
+ if (ax772a_data->Event == AX_SET_RX_CFG) {
+ u16 bmcr;
+ u16 mode;
+
+ ax772a_data->Event = AX_NOP;
+
+ mode = AX88772_MEDIUM_DEFAULT;
+
+ bmcr = ax8817x_mdio_read_le(dev->net,
+ dev->mii.phy_id, MII_BMCR);
+ if (!(bmcr & BMCR_FULLDPLX))
+ mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
+ if (!(bmcr & BMCR_SPEED100))
+ mode &= ~AX88772_MEDIUM_100MB;
+
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
+ mode, 0, 0, NULL);
+ return;
}
- asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR,
- BMCR_RESET | BMCR_ANENABLE);
- asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+ switch (ax772a_data->Event) {
+ case WAIT_AUTONEG_COMPLETE:
+ if (jiffies > (ax772a_data->autoneg_start + 5 * HZ)) {
+ ax772a_data->Event = CHK_CABLE_EXIST;
+ ax772a_data->TickToExpire = 14;
+ }
+ break;
+ case CHK_CABLE_EXIST:
+ phy_reg = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, 0x12);
+ if ((phy_reg != 0x8012) && (phy_reg != 0x8013)) {
+ ax8817x_mdio_write_le(dev->net,
+ dev->mii.phy_id, 0x16, 0x4040);
+ mii_nway_restart(&dev->mii);
+ ax772a_data->Event = CHK_CABLE_STATUS;
+ ax772a_data->TickToExpire = 31;
+ } else if (--ax772a_data->TickToExpire == 0) {
+ mii_nway_restart(&dev->mii);
+ ax772a_data->Event = CHK_CABLE_EXIST_AGAIN;
+ if (PowSave == 0x03){
+ ax772a_data->TickToExpire = 47;
+ } else if (PowSave == 0x01) {
+ ax772a_data->DlyIndex = (u8)(jiffies % 6);
+ ax772a_data->DlySel = 0;
+ ax772a_data->TickToExpire =
+ ChkCntSel[ax772a_data->DlyIndex][ax772a_data->DlySel];
+ }
+ }
+ break;
+ case CHK_CABLE_EXIST_AGAIN:
+ /* if cable disconnected */
+ phy_reg = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, 0x12);
+ if ((phy_reg != 0x8012) && (phy_reg != 0x8013)) {
+ mii_nway_restart(&dev->mii);
+ ax772a_data->Event = CHK_CABLE_STATUS;
+ ax772a_data->TickToExpire = 31;
+ } else if (--ax772a_data->TickToExpire == 0) {
+ /* Power down PHY */
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPPD,
+ 0, 0, NULL);
+ ax772a_data->Event = PHY_POWER_DOWN;
+ if (PowSave == 0x03){
+ ax772a_data->TickToExpire = 23;
+ } else if (PowSave == 0x01) {
+ ax772a_data->TickToExpire = 31;
+ }
+ }
+ break;
+ case PHY_POWER_DOWN:
+ if (--ax772a_data->TickToExpire == 0) {
+ ax772a_data->Event = PHY_POWER_UP;
+ }
+ break;
+ case CHK_CABLE_STATUS:
+ if (--ax772a_data->TickToExpire == 0) {
+ ax8817x_mdio_write_le(dev->net,
+ dev->mii.phy_id, 0x16, 0x4040);
+ mii_nway_restart(&dev->mii);
+ ax772a_data->Event = CHK_CABLE_EXIST_AGAIN;
+ if (PowSave == 0x03){
+ ax772a_data->TickToExpire = 47;
+ } else if (PowSave == 0x01) {
+ ax772a_data->DlyIndex = (u8)(jiffies % 6);
+ ax772a_data->DlySel = 0;
+ ax772a_data->TickToExpire =
+ ChkCntSel[ax772a_data->DlyIndex][ax772a_data->DlySel];
+ }
+ }
+ break;
+ case PHY_POWER_UP:
+
+ ax88772a_phy_powerup (dev);
+
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
- asix_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000,
- ADVERTISE_1000FULL);
- mii_nway_restart(&dev->mii);
+ mii_nway_restart(&dev->mii);
+
+ ax772a_data->Event = CHK_CABLE_EXIST_AGAIN;
+
+ if (PowSave == 0x03){
+ ax772a_data->TickToExpire = 47;
+
+ } else if (PowSave == 0x01) {
+
+ if (++ax772a_data->DlySel >= 3) {
+ ax772a_data->DlyIndex = (u8)(jiffies % 6);
+ ax772a_data->DlySel = 0;
+ }
+ ax772a_data->TickToExpire =
+ ChkCntSel[ax772a_data->DlyIndex][ax772a_data->DlySel];
+ }
+ break;
+ default:
+ break;
+ }
- if ((ret = asix_write_medium_mode(dev, AX88178_MEDIUM_DEFAULT)) < 0)
- goto out;
+ return;
+}
- if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0)
- goto out;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+static void ax88772b_link_reset (void *data)
+{
+ struct usbnet *dev = (struct usbnet *)data;
+ struct ax88772b_data *ax772b_data = (struct ax88772b_data *)dev->priv;
+#else
+static void ax88772b_link_reset (struct work_struct *work)
+{
+ struct ax88772b_data *ax772b_data = container_of (work,
+ struct ax88772b_data, check_link);
+ struct usbnet *dev = ax772b_data->dev;
+#endif
+
+ switch (ax772b_data->Event) {
+
+ case AX_SET_RX_CFG:
+ {
+ u16 bmcr = ax8817x_mdio_read_le(dev->net,
+ dev->mii.phy_id, MII_BMCR);
+ u16 mode = AX88772_MEDIUM_DEFAULT;
+
+ if (!(bmcr & BMCR_FULLDPLX))
+ mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
+ if (!(bmcr & BMCR_SPEED100))
+ mode &= ~AX88772_MEDIUM_100MB;
+
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
+ mode, 0, 0, NULL);
+ break;
+ }
+ case PHY_POWER_UP:
+ {
+ u16 tmp16;
- /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
- if (dev->driver_info->flags & FLAG_FRAMING_AX) {
- /* hard_mtu is still the default - the device does not support
- jumbo eth frames */
- dev->rx_urb_size = 2048;
+ ax88772a_phy_powerup (dev);
+ tmp16 = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, 0x12);
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, 0x12,
+ ((tmp16 & 0xFF9F) | 0x0040));
+
+ ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+ ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
+ break;
+ }
+ case AX_CHK_AUTODETACH:
+ {
+ u16 tmp16;
+ int ret;
+ void *buf;
+ buf = kmalloc(6, GFP_KERNEL);
+ devwarn(dev, "EVENT: AX_CHK_AUTODETACH\n");
+ /* Get the EEPROM data*/
+ if ((ret = ax8817x_read_cmd (dev, AX_CMD_READ_EEPROM,
+ 0x18, 0, 2, (void *)(&tmp16))) < 0) {
+ deverr(dev, "read SROM address 18h failed: %d", ret);
+ }
+ else {
+ ax772b_data->psc = le16_to_cpu(tmp16) & 0xFF00;
+ devwarn(dev, "EEPROM (0x18) = : %04X", ax772b_data->psc);
+ if ((ret = ax8817x_write_cmd (dev, AX_CMD_SW_RESET,
+ AX_SWRESET_IPRL | (ax772b_data->psc & 0x7FFF), 0, 0, buf)) < 0) {
+ deverr(dev, "Failed to configure PHY power saving: %d", ret);
+ }
+ }
+ break;
+ }
+ default:
+ break;
}
+
+ ax772b_data->Event = AX_NOP;
+
+ return;
+}
+
+static int ax88178_set_media(struct usbnet *dev)
+{
+ int ret;
+ struct ax88178_data *ax178dataptr = (struct ax88178_data *)dev->priv;
+ int media;
+
+ media = ax88178_media_check (dev, ax178dataptr);
+ if (media < 0)
+ return media;
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
+ media, 0, 0, NULL)) < 0) {
+ deverr(dev, "write mode medium reg failed: %d", ret);
+ return ret;
+ }
+
return 0;
+}
-out:
- return ret;
+static int ax88178_link_reset(struct usbnet *dev)
+{
+ return ax88178_set_media (dev);
+}
+
+static int ax_suspend (struct usb_interface *intf,
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
+ pm_message_t message)
+#else
+ u32 message)
+#endif
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
+
+ return data->suspend (intf, message);
+}
+
+static int ax_resume (struct usb_interface *intf)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+ struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
+
+ return data->resume (intf);
}
+static const struct driver_info ax88178_info = {
+ .description = "ASIX AX88178 USB 2.0 Ethernet",
+ .bind = ax88178_bind,
+ .unbind = ax88178_unbind,
+ .status = ax88178_status,
+ .link_reset = ax88178_link_reset,
+ .reset = ax88178_link_reset,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88772_rx_fixup,
+ .tx_fixup = ax88772_tx_fixup,
+};
+
+static const struct driver_info belkin178_info = {
+ .description = "Belkin Gigabit USB 2.0 Network Adapter",
+ .bind = ax88178_bind,
+ .unbind = ax88178_unbind,
+ .status = ax8817x_status,
+ .link_reset = ax88178_link_reset,
+ .reset = ax88178_link_reset,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88772_rx_fixup,
+ .tx_fixup = ax88772_tx_fixup,
+};
+
static const struct driver_info ax8817x_info = {
.description = "ASIX AX8817x USB 2.0 Ethernet",
- .bind = ax88172_bind,
- .status = asix_status,
+ .bind = ax8817x_bind,
+ .status = ax8817x_status,
.link_reset = ax88172_link_reset,
.reset = ax88172_link_reset,
- .flags = FLAG_ETHER | FLAG_LINK_INTR,
- .data = 0x00130103,
+ .flags = FLAG_ETHER,
};
static const struct driver_info dlink_dub_e100_info = {
.description = "DLink DUB-E100 USB Ethernet",
- .bind = ax88172_bind,
- .status = asix_status,
+ .bind = ax8817x_bind,
+ .status = ax8817x_status,
.link_reset = ax88172_link_reset,
.reset = ax88172_link_reset,
- .flags = FLAG_ETHER | FLAG_LINK_INTR,
- .data = 0x009f9d9f,
+ .flags = FLAG_ETHER,
};
static const struct driver_info netgear_fa120_info = {
.description = "Netgear FA-120 USB Ethernet",
- .bind = ax88172_bind,
- .status = asix_status,
+ .bind = ax8817x_bind,
+ .status = ax8817x_status,
.link_reset = ax88172_link_reset,
.reset = ax88172_link_reset,
- .flags = FLAG_ETHER | FLAG_LINK_INTR,
- .data = 0x00130103,
+ .flags = FLAG_ETHER,
};
static const struct driver_info hawking_uf200_info = {
.description = "Hawking UF200 USB Ethernet",
- .bind = ax88172_bind,
- .status = asix_status,
+ .bind = ax8817x_bind,
+ .status = ax8817x_status,
.link_reset = ax88172_link_reset,
.reset = ax88172_link_reset,
- .flags = FLAG_ETHER | FLAG_LINK_INTR,
- .data = 0x001f1d1f,
+ .flags = FLAG_ETHER,
};
static const struct driver_info ax88772_info = {
.description = "ASIX AX88772 USB 2.0 Ethernet",
.bind = ax88772_bind,
- .status = asix_status,
- .link_reset = ax88772_link_reset,
- .reset = ax88772_link_reset,
- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR,
- .rx_fixup = asix_rx_fixup,
- .tx_fixup = asix_tx_fixup,
+ .unbind = ax88772_unbind,
+ .status = ax88772_status,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88772_rx_fixup,
+ .tx_fixup = ax88772_tx_fixup,
+ .stop = ax88772b_stop,
+ .reset = ax88772b_reset,
};
-static const struct driver_info ax88178_info = {
- .description = "ASIX AX88178 USB 2.0 Ethernet",
- .bind = ax88178_bind,
- .status = asix_status,
- .link_reset = ax88178_link_reset,
- .reset = ax88178_link_reset,
- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR,
- .rx_fixup = asix_rx_fixup,
- .tx_fixup = asix_tx_fixup,
+static const struct driver_info dlink_dub_e100b_info = {
+ .description = "D-Link DUB-E100 USB 2.0 Fast Ethernet Adapter",
+ .bind = ax88772_bind,
+ .unbind = ax88772_unbind,
+ .status = ax88772_status,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88772_rx_fixup,
+ .tx_fixup = ax88772_tx_fixup,
+ .stop = ax88772b_stop,
+ .reset = ax88772b_reset,
+};
+
+static const struct driver_info ax88772a_info = {
+ .description = "ASIX AX88772A USB 2.0 Ethernet",
+ .bind = ax88772a_bind,
+ .unbind = ax88772a_unbind,
+ .status = ax88772a_status,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88772_rx_fixup,
+ .tx_fixup = ax88772_tx_fixup,
+ .stop = ax88772b_stop,
+ .reset = ax88772b_reset,
+};
+
+static const struct driver_info ax88772b_info = {
+ .description = "ASIX AX88772B USB 2.0 Ethernet",
+ .bind = ax88772b_bind,
+ .unbind = ax88772b_unbind,
+ .status = ax88772b_status,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_HW_IP_ALIGNMENT,
+ .rx_fixup = ax88772b_rx_fixup,
+ .tx_fixup = ax88772b_tx_fixup,
+ .stop = ax88772b_stop,
+ .reset = ax88772b_reset,
};
static const struct usb_device_id products [] = {
{
+ // 88178
+ USB_DEVICE (0x0b95, 0x1780),
+ .driver_info = (unsigned long) &ax88178_info,
+}, {
+ // 88178 for billianton linksys
+ USB_DEVICE (0x077b, 0x2226),
+ .driver_info = (unsigned long) &ax88178_info,
+}, {
+ // ABOCOM for linksys
+ USB_DEVICE (0x1737, 0x0039),
+ .driver_info = (unsigned long) &ax88178_info,
+}, {
+ // ABOCOM for pci
+ USB_DEVICE (0x14ea, 0xab11),
+ .driver_info = (unsigned long) &ax88178_info,
+}, {
+ // Belkin
+ USB_DEVICE (0x050d, 0x5055),
+ .driver_info = (unsigned long) &belkin178_info,
+}, {
// Linksys USB200M
USB_DEVICE (0x077b, 0x2226),
.driver_info = (unsigned long) &ax8817x_info,
@@ -1457,6 +3665,14 @@ static const struct usb_device_id products [] = {
USB_DEVICE (0x2001, 0x1a00),
.driver_info = (unsigned long) &dlink_dub_e100_info,
}, {
+ // DLink DUB-E100B
+ USB_DEVICE (0x2001, 0x3c05),
+ .driver_info = (unsigned long) &dlink_dub_e100b_info,
+}, {
+ // DLink DUB-E100B
+ USB_DEVICE (0x07d1, 0x3c05),
+ .driver_info = (unsigned long) &dlink_dub_e100b_info,
+}, {
// Intellinet, ST Lab USB Ethernet
USB_DEVICE (0x0b95, 0x1720),
.driver_info = (unsigned long) &ax8817x_info,
@@ -1465,9 +3681,9 @@ static const struct usb_device_id products [] = {
USB_DEVICE (0x07b8, 0x420a),
.driver_info = (unsigned long) &hawking_uf200_info,
}, {
- // Billionton Systems, USB2AR
- USB_DEVICE (0x08dd, 0x90ff),
- .driver_info = (unsigned long) &ax8817x_info,
+ // Billionton Systems, USB2AR
+ USB_DEVICE (0x08dd, 0x90ff),
+ .driver_info = (unsigned long) &ax8817x_info,
}, {
// ATEN UC210T
USB_DEVICE (0x0557, 0x2009),
@@ -1477,10 +3693,6 @@ static const struct usb_device_id products [] = {
USB_DEVICE (0x0411, 0x003d),
.driver_info = (unsigned long) &ax8817x_info,
}, {
- // Buffalo LUA-U2-GT 10/100/1000
- USB_DEVICE (0x0411, 0x006e),
- .driver_info = (unsigned long) &ax88178_info,
-}, {
// Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter"
USB_DEVICE (0x6189, 0x182d),
.driver_info = (unsigned long) &ax8817x_info,
@@ -1497,86 +3709,53 @@ static const struct usb_device_id products [] = {
USB_DEVICE (0x1631, 0x6200),
.driver_info = (unsigned long) &ax8817x_info,
}, {
- // JVC MP-PRX1 Port Replicator
- USB_DEVICE (0x04f1, 0x3008),
- .driver_info = (unsigned long) &ax8817x_info,
-}, {
- // ASIX AX88772B 10/100
- USB_DEVICE (0x0b95, 0x772b),
- .driver_info = (unsigned long) &ax88772_info,
-}, {
// ASIX AX88772 10/100
- USB_DEVICE (0x0b95, 0x7720),
- .driver_info = (unsigned long) &ax88772_info,
-}, {
- // ASIX AX88178 10/100/1000
- USB_DEVICE (0x0b95, 0x1780),
- .driver_info = (unsigned long) &ax88178_info,
-}, {
- // Logitec LAN-GTJ/U2A
- USB_DEVICE (0x0789, 0x0160),
- .driver_info = (unsigned long) &ax88178_info,
-}, {
- // Linksys USB200M Rev 2
- USB_DEVICE (0x13b1, 0x0018),
- .driver_info = (unsigned long) &ax88772_info,
+ USB_DEVICE (0x0b95, 0x7720),
+ .driver_info = (unsigned long) &ax88772_info,
}, {
- // 0Q0 cable ethernet
- USB_DEVICE (0x1557, 0x7720),
- .driver_info = (unsigned long) &ax88772_info,
-}, {
- // DLink DUB-E100 H/W Ver B1
- USB_DEVICE (0x07d1, 0x3c05),
- .driver_info = (unsigned long) &ax88772_info,
-}, {
- // DLink DUB-E100 H/W Ver B1 Alternate
- USB_DEVICE (0x2001, 0x3c05),
- .driver_info = (unsigned long) &ax88772_info,
-}, {
- // Linksys USB1000
- USB_DEVICE (0x1737, 0x0039),
- .driver_info = (unsigned long) &ax88178_info,
+ // ASIX AX88772 10/100
+ USB_DEVICE (0x125E, 0x180D),
+ .driver_info = (unsigned long) &ax88772_info,
}, {
- // IO-DATA ETG-US2
- USB_DEVICE (0x04bb, 0x0930),
- .driver_info = (unsigned long) &ax88178_info,
+ // ASIX AX88772A 10/100
+ USB_DEVICE (0x0b95, 0x772A),
+ .driver_info = (unsigned long) &ax88772a_info,
}, {
- // Belkin F5D5055
- USB_DEVICE(0x050d, 0x5055),
- .driver_info = (unsigned long) &ax88178_info,
+ // ASIX AX88772A 10/100
+ USB_DEVICE (0x0db0, 0xA877),
+ .driver_info = (unsigned long) &ax88772a_info,
}, {
- // Apple USB Ethernet Adapter
- USB_DEVICE(0x05ac, 0x1402),
- .driver_info = (unsigned long) &ax88772_info,
+ // ASIX AX88772A 10/100
+ USB_DEVICE (0x0421, 0x772A),
+ .driver_info = (unsigned long) &ax88772a_info,
}, {
- // Cables-to-Go USB Ethernet Adapter
- USB_DEVICE(0x0b95, 0x772a),
- .driver_info = (unsigned long) &ax88772_info,
+ // Linksys 200M
+ USB_DEVICE (0x13B1, 0x0018),
+ .driver_info = (unsigned long) &ax88772a_info,
}, {
- // ABOCOM for pci
- USB_DEVICE(0x14ea, 0xab11),
- .driver_info = (unsigned long) &ax88178_info,
+ USB_DEVICE (0x05ac, 0x1402),
+ .driver_info = (unsigned long) &ax88772a_info,
}, {
- // ASIX 88772a
- USB_DEVICE(0x0db0, 0xa877),
- .driver_info = (unsigned long) &ax88772_info,
+ // ASIX AX88772B 10/100
+ USB_DEVICE (0x0b95, 0x772B),
+ .driver_info = (unsigned long) &ax88772b_info,
}, {
- // Asus USB Ethernet Adapter
- USB_DEVICE (0x0b95, 0x7e2b),
- .driver_info = (unsigned long) &ax88772_info,
+ // ASIX AX88772B 10/100
+ USB_DEVICE (0x0b95, 0x7E2B),
+ .driver_info = (unsigned long) &ax88772b_info,
},
{ }, // END
};
MODULE_DEVICE_TABLE(usb, products);
static struct usb_driver asix_driver = {
+// .owner = THIS_MODULE,
.name = "asix",
.id_table = products,
- .probe = usbnet_probe,
- .suspend = usbnet_suspend,
- .resume = usbnet_resume,
- .disconnect = usbnet_disconnect,
- .supports_autosuspend = 1,
+ .probe = axusbnet_probe,
+ .suspend = ax_suspend,
+ .resume = ax_resume,
+ .disconnect = axusbnet_disconnect,
};
static int __init asix_init(void)
diff --git a/drivers/net/usb/asix.h b/drivers/net/usb/asix.h
new file mode 100644
index 000000000000..ea51eb7001e2
--- /dev/null
+++ b/drivers/net/usb/asix.h
@@ -0,0 +1,558 @@
+#ifndef __LINUX_USBNET_ASIX_H
+#define __LINUX_USBNET_ASIX_H
+
+/*
+ * Turn on this flag if the implementation of your USB host controller
+ * cannot handle non-double word aligned buffer.
+ * When turn on this flag, driver will fixup egress packet aligned on double
+ * word boundary before deliver to USB host controller. And will Disable the
+ * function "skb_reserve (skb, NET_IP_ALIGN)" to retain the buffer aligned on
+ * double word alignment for ingress packets.
+ */
+#define AX_FORCE_BUFF_ALIGN 0
+
+#define AX_MONITOR_MODE 0x01
+#define AX_MONITOR_LINK 0x02
+#define AX_MONITOR_MAGIC 0x04
+#define AX_MONITOR_HSFS 0x10
+
+/* AX88172 Medium Status Register values */
+#define AX_MEDIUM_FULL_DUPLEX 0x02
+#define AX_MEDIUM_TX_ABORT_ALLOW 0x04
+#define AX_MEDIUM_FLOW_CONTROL_EN 0x10
+#define AX_MCAST_FILTER_SIZE 8
+#define AX_MAX_MCAST 64
+
+#define AX_EEPROM_LEN 0x40
+
+#define AX_SWRESET_CLEAR 0x00
+#define AX_SWRESET_RR 0x01
+#define AX_SWRESET_RT 0x02
+#define AX_SWRESET_PRTE 0x04
+#define AX_SWRESET_PRL 0x08
+#define AX_SWRESET_BZ 0x10
+#define AX_SWRESET_IPRL 0x20
+#define AX_SWRESET_IPPD 0x40
+#define AX_SWRESET_IPOSC 0x0080
+#define AX_SWRESET_IPPSL_0 0x0100
+#define AX_SWRESET_IPPSL_1 0x0200
+#define AX_SWRESET_IPCOPS 0x0400
+#define AX_SWRESET_IPCOPSC 0x0800
+#define AX_SWRESET_AUTODETACH 0x1000
+#define AX_SWRESET_WOLLP 0x8000
+
+#define AX88772_IPG0_DEFAULT 0x15
+#define AX88772_IPG1_DEFAULT 0x0c
+#define AX88772_IPG2_DEFAULT 0x0E
+
+#define AX88772A_IPG0_DEFAULT 0x15
+#define AX88772A_IPG1_DEFAULT 0x16
+#define AX88772A_IPG2_DEFAULT 0x1A
+
+#define AX88772_MEDIUM_FULL_DUPLEX 0x0002
+#define AX88772_MEDIUM_RESERVED 0x0004
+#define AX88772_MEDIUM_RX_FC_ENABLE 0x0010
+#define AX88772_MEDIUM_TX_FC_ENABLE 0x0020
+#define AX88772_MEDIUM_PAUSE_FORMAT 0x0080
+#define AX88772_MEDIUM_RX_ENABLE 0x0100
+#define AX88772_MEDIUM_100MB 0x0200
+#define AX88772_MEDIUM_DEFAULT \
+ (AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \
+ AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \
+ AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE )
+
+#define AX_CMD_SET_SW_MII 0x06
+#define AX_CMD_READ_MII_REG 0x07
+#define AX_CMD_WRITE_MII_REG 0x08
+#define AX_CMD_SET_HW_MII 0x0a
+#define AX_CMD_READ_EEPROM 0x0b
+#define AX_CMD_WRITE_EEPROM 0x0c
+#define AX_CMD_WRITE_EEPROM_EN 0x0d
+#define AX_CMD_WRITE_EEPROM_DIS 0x0e
+#define AX_CMD_WRITE_RX_CTL 0x10
+#define AX_CMD_READ_IPG012 0x11
+#define AX_CMD_WRITE_IPG0 0x12
+#define AX_CMD_WRITE_IPG1 0x13
+#define AX_CMD_WRITE_IPG2 0x14
+#define AX_CMD_WRITE_MULTI_FILTER 0x16
+#define AX_CMD_READ_NODE_ID 0x17
+#define AX_CMD_READ_PHY_ID 0x19
+#define AX_CMD_READ_MEDIUM_MODE 0x1a
+#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
+#define AX_CMD_READ_MONITOR_MODE 0x1c
+#define AX_CMD_WRITE_MONITOR_MODE 0x1d
+#define AX_CMD_WRITE_GPIOS 0x1f
+#define AX_CMD_SW_RESET 0x20
+#define AX_CMD_SW_PHY_STATUS 0x21
+#define AX_CMD_SW_PHY_SELECT 0x22
+ #define AX_PHYSEL_PSEL (1 << 0)
+ #define AX_PHYSEL_ASEL (1 << 1)
+ #define AX_PHYSEL_SSMII (0 << 2)
+ #define AX_PHYSEL_SSRMII (1 << 2)
+ #define AX_PHYSEL_SSRRMII (3 << 2)
+ #define AX_PHYSEL_SSEN (1 << 4)
+#define AX88772_CMD_READ_NODE_ID 0x13
+#define AX88772_CMD_WRITE_NODE_ID 0x14
+#define AX_CMD_READ_RXCOE_CTL 0x2b
+#define AX_CMD_WRITE_RXCOE_CTL 0x2c
+#define AX_CMD_READ_TXCOE_CTL 0x2d
+#define AX_CMD_WRITE_TXCOE_CTL 0x2e
+
+#define REG_LENGTH 2
+#define PHY_ID_MASK 0x1f
+
+#define AX_RXCOE_IPCE 0x0001
+#define AX_RXCOE_IPVE 0x0002
+#define AX_RXCOE_V6VE 0x0004
+#define AX_RXCOE_TCPE 0x0008
+#define AX_RXCOE_UDPE 0x0010
+#define AX_RXCOE_ICMP 0x0020
+#define AX_RXCOE_IGMP 0x0040
+#define AX_RXCOE_ICV6 0x0080
+#define AX_RXCOE_TCPV6 0x0100
+#define AX_RXCOE_UDPV6 0x0200
+#define AX_RXCOE_ICMV6 0x0400
+#define AX_RXCOE_IGMV6 0x0800
+#define AX_RXCOE_ICV6V6 0x1000
+#define AX_RXCOE_FOPC 0x8000
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)
+#define AX_RXCOE_DEF_CSUM (AX_RXCOE_IPCE | AX_RXCOE_IPVE | \
+ AX_RXCOE_V6VE | AX_RXCOE_TCPE | \
+ AX_RXCOE_UDPE | AX_RXCOE_ICV6 | \
+ AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6)
+#else
+#define AX_RXCOE_DEF_CSUM (AX_RXCOE_IPCE | AX_RXCOE_IPVE | \
+ AX_RXCOE_TCPE | AX_RXCOE_UDPE)
+#endif
+
+#define AX_RXCOE_64TE 0x0100
+#define AX_RXCOE_PPPOE 0x0200
+#define AX_RXCOE_RPCE 0x8000
+
+#define AX_TXCOE_IP 0x0001
+#define AX_TXCOE_TCP 0x0002
+#define AX_TXCOE_UDP 0x0004
+#define AX_TXCOE_ICMP 0x0008
+#define AX_TXCOE_IGMP 0x0010
+#define AX_TXCOE_ICV6 0x0020
+
+#define AX_TXCOE_TCPV6 0x0100
+#define AX_TXCOE_UDPV6 0x0200
+#define AX_TXCOE_ICMV6 0x0400
+#define AX_TXCOE_IGMV6 0x0800
+#define AX_TXCOE_ICV6V6 0x1000
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)
+#define AX_TXCOE_DEF_CSUM (AX_TXCOE_TCP | AX_TXCOE_UDP | \
+ AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6)
+#else
+#define AX_TXCOE_DEF_CSUM (AX_TXCOE_TCP | AX_TXCOE_UDP)
+#endif
+
+#define AX_TXCOE_64TE 0x0001
+#define AX_TXCOE_PPPE 0x0002
+
+#define AX88772B_MAX_BULKIN_2K 0
+#define AX88772B_MAX_BULKIN_4K 1
+#define AX88772B_MAX_BULKIN_6K 2
+#define AX88772B_MAX_BULKIN_8K 3
+#define AX88772B_MAX_BULKIN_16K 4
+#define AX88772B_MAX_BULKIN_20K 5
+#define AX88772B_MAX_BULKIN_24K 6
+#define AX88772B_MAX_BULKIN_32K 7
+struct {unsigned short size, byte_cnt,threshold;} AX88772B_BULKIN_SIZE[] =
+{
+ /* 2k */
+ {2048, 0x8000, 0x8001},
+ /* 4k */
+ {4096, 0x8100, 0x8147},
+ /* 6k */
+ {6144, 0x8200, 0x81EB},
+ /* 8k */
+ {8192, 0x8300, 0x83D7},
+ /* 16 */
+ {16384, 0x8400, 0x851E},
+ /* 20k */
+ {20480, 0x8500, 0x8666},
+ /* 24k */
+ {24576, 0x8600, 0x87AE},
+ /* 32k */
+ {32768, 0x8700, 0x8A3D},
+};
+
+
+#define AX_RX_CTL_RH1M 0x0100 /* Enable RX-Header mode 0 */
+#define AX_RX_CTL_RH2M 0x0200 /* Enable IP header in receive buffer aligned on 32-bit aligment */
+#define AX_RX_CTL_RH3M 0x0400 /* checksum value in rx header 3 */
+#define AX_RX_HEADER_DEFAULT (AX_RX_CTL_RH1M | AX_RX_CTL_RH2M)
+
+#define AX_RX_CTL_MFB 0x0300 /* Maximum Frame size 16384bytes */
+#define AX_RX_CTL_START 0x0080 /* Ethernet MAC start */
+#define AX_RX_CTL_AP 0x0020 /* Accept physcial address from Multicast array */
+#define AX_RX_CTL_AM 0x0010
+#define AX_RX_CTL_AB 0x0008 /* Accetp Brocadcast frames*/
+#define AX_RX_CTL_SEP 0x0004 /* Save error packets */
+#define AX_RX_CTL_AMALL 0x0002 /* Accetp all multicast frames */
+#define AX_RX_CTL_PRO 0x0001 /* Promiscuous Mode */
+#define AX_RX_CTL_STOP 0x0000 /* Stop MAC */
+
+#define AX_MONITOR_MODE 0x01
+#define AX_MONITOR_LINK 0x02
+#define AX_MONITOR_MAGIC 0x04
+#define AX_MONITOR_HSFS 0x10
+
+#define AX_MCAST_FILTER_SIZE 8
+#define AX_MAX_MCAST 64
+#define AX_INTERRUPT_BUFSIZE 8
+
+#define AX_EEPROM_LEN 0x40
+#define AX_EEPROM_MAGIC 0xdeadbeef
+#define EEPROMMASK 0x7f
+
+/* GPIO REGISTER */
+#define AXGPIOS_GPO0EN 0X01 // 1 << 0
+#define AXGPIOS_GPO0 0X02 // 1 << 1
+#define AXGPIOS_GPO1EN 0X04 // 1 << 2
+#define AXGPIOS_GPO1 0X08 // 1 << 3
+#define AXGPIOS_GPO2EN 0X10 // 1 << 4
+#define AXGPIOS_GPO2 0X20 // 1 << 5
+#define AXGPIOS_RSE 0X80 // 1 << 7
+
+/* TX-header format */
+#define AX_TX_HDR_CPHI 0x4000
+#define AX_TX_HDR_DICF 0x8000
+
+// GMII register definitions
+#define GMII_PHY_CONTROL 0x00 // control reg
+#define GMII_PHY_STATUS 0x01 // status reg
+#define GMII_PHY_OUI 0x02 // most of the OUI bits
+#define GMII_PHY_MODEL 0x03 // model/rev bits, and rest of OUI
+#define GMII_PHY_ANAR 0x04 // AN advertisement reg
+#define GMII_PHY_ANLPAR 0x05 // AN Link Partner
+#define GMII_PHY_ANER 0x06 // AN expansion reg
+#define GMII_PHY_1000BT_CONTROL 0x09 // control reg for 1000BT
+#define GMII_PHY_1000BT_STATUS 0x0A // status reg for 1000BT
+
+// Bit definitions: GMII Control
+#define GMII_CONTROL_RESET 0x8000 // reset bit in control reg
+#define GMII_CONTROL_LOOPBACK 0x4000 // loopback bit in control reg
+#define GMII_CONTROL_10MB 0x0000 // 10 Mbit
+#define GMII_CONTROL_100MB 0x2000 // 100Mbit
+#define GMII_CONTROL_1000MB 0x0040 // 1000Mbit
+#define GMII_CONTROL_SPEED_BITS 0x2040 // speed bit mask
+#define GMII_CONTROL_ENABLE_AUTO 0x1000 // autonegotiate enable
+#define GMII_CONTROL_POWER_DOWN 0x0800
+#define GMII_CONTROL_ISOLATE 0x0400 // islolate bit
+#define GMII_CONTROL_START_AUTO 0x0200 // restart autonegotiate
+#define GMII_CONTROL_FULL_DUPLEX 0x0100
+
+// Bit definitions: GMII Status
+#define GMII_STATUS_100MB_MASK 0xE000 // any of these indicate 100 Mbit
+#define GMII_STATUS_10MB_MASK 0x1800 // either of these indicate 10 Mbit
+#define GMII_STATUS_AUTO_DONE 0x0020 // auto negotiation complete
+#define GMII_STATUS_AUTO 0x0008 // auto negotiation is available
+#define GMII_STATUS_LINK_UP 0x0004 // link status bit
+#define GMII_STATUS_EXTENDED 0x0001 // extended regs exist
+#define GMII_STATUS_100T4 0x8000 // capable of 100BT4
+#define GMII_STATUS_100TXFD 0x4000 // capable of 100BTX full duplex
+#define GMII_STATUS_100TX 0x2000 // capable of 100BTX
+#define GMII_STATUS_10TFD 0x1000 // capable of 10BT full duplex
+#define GMII_STATUS_10T 0x0800 // capable of 10BT
+
+// Bit definitions: Auto-Negotiation Advertisement
+#define GMII_ANAR_ASYM_PAUSE 0x0800 // support asymetric pause
+#define GMII_ANAR_PAUSE 0x0400 // support pause packets
+#define GMII_ANAR_100T4 0x0200 // support 100BT4
+#define GMII_ANAR_100TXFD 0x0100 // support 100BTX full duplex
+#define GMII_ANAR_100TX 0x0080 // support 100BTX half duplex
+#define GMII_ANAR_10TFD 0x0040 // support 10BT full duplex
+#define GMII_ANAR_10T 0x0020 // support 10BT half duplex
+#define GMII_SELECTOR_FIELD 0x001F // selector field.
+
+// Bit definitions: Auto-Negotiation Link Partner Ability
+#define GMII_ANLPAR_100T4 0x0200 // support 100BT4
+#define GMII_ANLPAR_100TXFD 0x0100 // support 100BTX full duplex
+#define GMII_ANLPAR_100TX 0x0080 // support 100BTX half duplex
+#define GMII_ANLPAR_10TFD 0x0040 // support 10BT full duplex
+#define GMII_ANLPAR_10T 0x0020 // support 10BT half duplex
+#define GMII_ANLPAR_PAUSE 0x0400 // support pause packets
+#define GMII_ANLPAR_ASYM_PAUSE 0x0800 // support asymetric pause
+#define GMII_ANLPAR_ACK 0x4000 // means LCB was successfully rx'd
+#define GMII_SELECTOR_8023 0x0001;
+
+// Bit definitions: 1000BaseT AUX Control
+#define GMII_1000_AUX_CTRL_MASTER_SLAVE 0x1000
+#define GMII_1000_AUX_CTRL_FD_CAPABLE 0x0200 // full duplex capable
+#define GMII_1000_AUX_CTRL_HD_CAPABLE 0x0100 // half duplex capable
+
+// Bit definitions: 1000BaseT AUX Status
+#define GMII_1000_AUX_STATUS_FD_CAPABLE 0x0800 // full duplex capable
+#define GMII_1000_AUX_STATUS_HD_CAPABLE 0x0400 // half duplex capable
+
+// Cicada MII Registers
+#define GMII_AUX_CTRL_STATUS 0x1C
+#define GMII_AUX_ANEG_CPLT 0x8000
+#define GMII_AUX_FDX 0x0020
+#define GMII_AUX_SPEED_1000 0x0010
+#define GMII_AUX_SPEED_100 0x0008
+
+#ifndef ADVERTISE_PAUSE_CAP
+#define ADVERTISE_PAUSE_CAP 0x0400
+#endif
+
+#ifndef MII_STAT1000
+#define MII_STAT1000 0x000A
+#endif
+
+#ifndef LPA_1000FULL
+#define LPA_1000FULL 0x0800
+#endif
+
+// medium mode register
+#define MEDIUM_GIGA_MODE 0x0001
+#define MEDIUM_FULL_DUPLEX_MODE 0x0002
+#define MEDIUM_TX_ABORT_MODE 0x0004
+#define MEDIUM_ENABLE_125MHZ 0x0008
+#define MEDIUM_ENABLE_RX_FLOWCTRL 0x0010
+#define MEDIUM_ENABLE_TX_FLOWCTRL 0x0020
+#define MEDIUM_ENABLE_JUMBO_FRAME 0x0040
+#define MEDIUM_CHECK_PAUSE_FRAME_MODE 0x0080
+#define MEDIUM_ENABLE_RECEIVE 0x0100
+#define MEDIUM_MII_100M_MODE 0x0200
+#define MEDIUM_ENABLE_JAM_PATTERN 0x0400
+#define MEDIUM_ENABLE_STOP_BACKPRESSURE 0x0800
+#define MEDIUM_ENABLE_SUPPER_MAC_SUPPORT 0x1000
+
+/* PHY mode */
+#define PHY_MODE_MARVELL 0
+#define PHY_MODE_CICADA_FAMILY 1
+#define PHY_MODE_CICADA_V1 1
+#define PHY_MODE_AGERE_FAMILY 2
+#define PHY_MODE_AGERE_V0 2
+#define PHY_MODE_CICADA_V2 5
+#define PHY_MODE_AGERE_V0_GMII 6
+#define PHY_MODE_CICADA_V2_ASIX 9
+#define PHY_MODE_VSC8601 10
+#define PHY_MODE_RTL8211CL 12
+#define PHY_MODE_RTL8211BN 13
+#define PHY_MODE_RTL8251CL 14
+#define PHY_MODE_ATTANSIC_V0 0x40
+#define PHY_MODE_ATTANSIC_FAMILY 0x40
+#define PHY_MODE_MAC_TO_MAC_GMII 0x7C
+
+/* */
+#define LED_MODE_MARVELL 0
+#define LED_MODE_CAMEO 1
+
+#define MARVELL_LED_CTRL 0x18
+#define MARVELL_MANUAL_LED 0x19
+
+#define PHY_IDENTIFIER 0x0002
+#define PHY_AGERE_IDENTIFIER 0x0282
+#define PHY_CICADA_IDENTIFIER 0x000f
+#define PHY_MARVELL_IDENTIFIER 0x0141
+
+#define PHY_MARVELL_STATUS 0x001b
+#define MARVELL_STATUS_HWCFG 0x0004 /* SGMII without clock */
+
+#define PHY_MARVELL_CTRL 0x0014
+#define MARVELL_CTRL_RXDELAY 0x0080
+#define MARVELL_CTRL_TXDELAY 0x0002
+
+#define PHY_CICADA_EXTPAGE 0x001f
+#define CICADA_EXTPAGE_EN 0x0001
+#define CICADA_EXTPAGE_DIS 0x0000
+
+
+struct {unsigned short value, offset; } CICADA_FAMILY_HWINIT[] =
+{
+ {0x0001, 0x001f}, {0x1c25, 0x0017}, {0x2a30, 0x001f}, {0x234c, 0x0010},
+ {0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0xa7fa, 0x0000},
+ {0x0012, 0x0002}, {0x3002, 0x0001}, {0x87fa, 0x0000}, {0x52b5, 0x001f},
+ {0xafac, 0x0000}, {0x000d, 0x0002}, {0x001c, 0x0001}, {0x8fac, 0x0000},
+ {0x2a30, 0x001f}, {0x0012, 0x0008}, {0x2a30, 0x001f}, {0x0400, 0x0014},
+ {0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0xa760, 0x0000},
+ {0x0000, 0x0002}, {0xfaff, 0x0001}, {0x8760, 0x0000}, {0x52b5, 0x001f},
+ {0xa760, 0x0000}, {0x0000, 0x0002}, {0xfaff, 0x0001}, {0x8760, 0x0000},
+ {0x52b5, 0x001f}, {0xafae, 0x0000}, {0x0004, 0x0002}, {0x0671, 0x0001},
+ {0x8fae, 0x0000}, {0x2a30, 0x001f}, {0x0012, 0x0008}, {0x0000, 0x001f},
+};
+
+struct {unsigned short value, offset; } CICADA_V2_HWINIT[] =
+{
+ {0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0x000f, 0x0002},
+ {0x472a, 0x0001}, {0x8fa4, 0x0000}, {0x2a30, 0x001f}, {0x0212, 0x0008},
+ {0x0000, 0x001f},
+};
+
+struct {unsigned short value, offset; } CICADA_V2_ASIX_HWINIT[] =
+{
+ {0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0x0012, 0x0002},
+ {0x3002, 0x0001}, {0x87fa, 0x0000}, {0x52b5, 0x001f}, {0x000f, 0x0002},
+ {0x472a, 0x0001}, {0x8fa4, 0x0000}, {0x2a30, 0x001f}, {0x0212, 0x0008},
+ {0x0000, 0x001f},
+};
+
+struct {unsigned short value, offset; } AGERE_FAMILY_HWINIT[] =
+{
+ {0x0800, 0x0000}, {0x0007, 0x0012}, {0x8805, 0x0010}, {0xb03e, 0x0011},
+ {0x8808, 0x0010}, {0xe110, 0x0011}, {0x8806, 0x0010}, {0xb03e, 0x0011},
+ {0x8807, 0x0010}, {0xff00, 0x0011}, {0x880e, 0x0010}, {0xb4d3, 0x0011},
+ {0x880f, 0x0010}, {0xb4d3, 0x0011}, {0x8810, 0x0010}, {0xb4d3, 0x0011},
+ {0x8817, 0x0010}, {0x1c00, 0x0011}, {0x300d, 0x0010}, {0x0001, 0x0011},
+ {0x0002, 0x0012},
+};
+
+struct ax88178_data {
+ u16 EepromData;
+ u16 MediaLink;
+ int UseGpio0;
+ int UseRgmii;
+ u8 PhyMode;
+ u8 LedMode;
+ u8 BuffaloOld;
+};
+
+enum watchdog_state {
+ AX_NOP = 0,
+ CHK_LINK, /* Routine A */
+ CHK_CABLE_EXIST, /* Called by A */
+ CHK_CABLE_EXIST_AGAIN, /* Routine B */
+ PHY_POWER_UP, /* Called by B */
+ PHY_POWER_UP_BH,
+ PHY_POWER_DOWN,
+ CHK_CABLE_STATUS, /* Routine C */
+ WAIT_AUTONEG_COMPLETE,
+ AX_SET_RX_CFG,
+ AX_CHK_AUTODETACH,
+};
+
+struct ax88772b_data {
+ struct usbnet *dev;
+ struct workqueue_struct *ax_work;
+ struct work_struct check_link;
+ unsigned long time_to_chk;
+ u16 psc;
+ u8 pw_enabled;
+ u8 Event;
+ u8 checksum;
+ u8 PhySelect:1;
+ u8 OperationMode:1;
+
+};
+
+// define for MAC or PHY mode
+#define OPERATION_MAC_MODE 0
+#define OPERATION_PHY_MODE 1
+
+struct ax88772a_data {
+ struct usbnet *dev;
+ struct workqueue_struct *ax_work;
+ struct work_struct check_link;
+ unsigned long autoneg_start;
+#define AX88772B_WATCHDOG (6 * HZ)
+ u8 Event;
+ u8 TickToExpire;
+ u8 DlyIndex;
+ u8 DlySel;
+ u16 EepromData;
+};
+
+struct ax88772_data {
+ struct usbnet *dev;
+ struct workqueue_struct *ax_work;
+ struct work_struct check_link;
+ unsigned long autoneg_start;
+ u8 Event;
+ u8 TickToExpire;
+};
+
+#define AX_RX_CHECKSUM 1
+#define AX_TX_CHECKSUM 2
+
+/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
+struct ax8817x_data {
+ u8 multi_filter[AX_MCAST_FILTER_SIZE];
+ int (*resume) (struct usb_interface *intf);
+ int (*suspend) (struct usb_interface *intf,
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
+ pm_message_t message);
+#else
+ u32 message);
+#endif
+};
+
+struct ax88172_int_data {
+ u16 res1;
+#define AX_INT_PPLS_LINK (1 << 0)
+#define AX_INT_SPLS_LINK (1 << 1)
+#define AX_INT_CABOFF_UNPLUG (1 << 7)
+ u8 link;
+ u16 res2;
+ u8 status;
+ u16 res3;
+} __attribute__ ((packed));
+
+#define AX_RXHDR_L4_ERR (1 << 8)
+#define AX_RXHDR_L3_ERR (1 << 9)
+
+#define AX_RXHDR_L4_TYPE_UDP 1
+#define AX_RXHDR_L4_TYPE_ICMP 2
+#define AX_RXHDR_L4_TYPE_IGMP 3
+#define AX_RXHDR_L4_TYPE_TCP 4
+#define AX_RXHDR_L4_TYPE_TCMPV6 5
+#define AX_RXHDR_L4_TYPE_MASK 7
+
+#define AX_RXHDR_L3_TYPE_IP 1
+#define AX_RXHDR_L3_TYPE_IPV6 2
+
+struct ax88772b_rx_header {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u16 len:11,
+ res1:1,
+ crc:1,
+ mii:1,
+ runt:1,
+ mc_bc:1;
+
+ u16 len_bar:11,
+ res2:5;
+
+ u8 vlan_ind:3,
+ vlan_tag_striped:1,
+ pri:3,
+ res3:1;
+
+ u8 l4_csum_err:1,
+ l3_csum_err:1,
+ l4_type:3,
+ l3_type:2,
+ ce:1;
+#elif defined (__BIG_ENDIAN_BITFIELD)
+ u16 mc_bc:1,
+ runt:1,
+ mii:1,
+ crc:1,
+ res1:1,
+ len:11;
+
+ u16 res2:5,
+ len_bar:11;
+
+ u8 res3:1,
+ pri:3,
+ vlan_tag_striped:1,
+ vlan_ind:3;
+
+ u8 ce:1,
+ l3_type:2,
+ l4_type:3,
+ l3_csum_err:1,
+ l4_csum_err:1;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+
+} __attribute__ ((packed));
+
+#endif /* __LINUX_USBNET_ASIX_H */
+
diff --git a/drivers/net/usb/axusbnet.c b/drivers/net/usb/axusbnet.c
new file mode 100644
index 000000000000..00393d38a379
--- /dev/null
+++ b/drivers/net/usb/axusbnet.c
@@ -0,0 +1,1374 @@
+/*
+ * USB Network driver infrastructure
+ * Copyright (C) 2000-2005 by David Brownell
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * This is a generic "USB networking" framework that works with several
+ * kinds of full and high speed networking devices: host-to-host cables,
+ * smart usb peripherals, and actual Ethernet adapters.
+ *
+ * These devices usually differ in terms of control protocols (if they
+ * even have one!) and sometimes they define new framing to wrap or batch
+ * Ethernet packets. Otherwise, they talk to USB pretty much the same,
+ * so interface (un)binding, endpoint I/O queues, fault handling, and other
+ * issues can usefully be addressed by this framework.
+ */
+
+#define DEBUG // error path messages, extra info
+// #define VERBOSE // more; success messages
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ctype.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+/*#include <linux/usb/usbnet.h>*/
+
+#include "asix.h"
+#include "axusbnet.h"
+
+#define DRIVER_VERSION "22-Aug-2005"
+
+static void axusbnet_unlink_rx_urbs(struct usbnet *);
+
+extern void
+ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+ u16 size, void *data);
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Nineteen USB 1.1 max size bulk transactions per frame (ms), max.
+ * Several dozen bytes of IPv4 data can fit in two such transactions.
+ * One maximum size Ethernet packet takes twenty four of them.
+ * For high speed, each frame comfortably fits almost 36 max size
+ * Ethernet packets (so queues should be bigger).
+ *
+ * REVISIT qlens should be members of 'struct usbnet'; the goal is to
+ * let the USB host controller be busy for 5msec or more before an irq
+ * is required, under load. Jumbograms change the equation.
+ */
+#define RX_MAX_QUEUE_MEMORY (60 * 1518)
+#define RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \
+ (RX_MAX_QUEUE_MEMORY/(dev)->rx_urb_size) : 4)
+#define TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \
+ (RX_MAX_QUEUE_MEMORY/(dev)->hard_mtu) : 4)
+
+// reawaken network queue this soon after stopping; else watchdog barks
+//#define TX_TIMEOUT_JIFFIES (5*HZ)
+#define TX_TIMEOUT_JIFFIES (30*HZ)
+
+// throttle rx/tx briefly after some faults, so khubd might disconnect()
+// us (it polls at HZ/4 usually) before we report too many false errors.
+#define THROTTLE_JIFFIES (HZ/8)
+
+// between wakeups
+#define UNLINK_TIMEOUT_MS 3
+
+/*-------------------------------------------------------------------------*/
+
+static const char driver_name [] = "axusbnet";
+
+/* use ethtool to change the level for any given device */
+static int msg_level = -1;
+module_param (msg_level, int, 0);
+MODULE_PARM_DESC (msg_level, "Override default message level");
+
+/*-------------------------------------------------------------------------*/
+
+/* handles CDC Ethernet and many other network "bulk data" interfaces */
+static
+int axusbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
+{
+ int tmp;
+ struct usb_host_interface *alt = NULL;
+ struct usb_host_endpoint *in = NULL, *out = NULL;
+ struct usb_host_endpoint *status = NULL;
+
+ for (tmp = 0; tmp < intf->num_altsetting; tmp++) {
+ unsigned ep;
+
+ in = out = status = NULL;
+ alt = intf->altsetting + tmp;
+
+ /* take the first altsetting with in-bulk + out-bulk;
+ * remember any status endpoint, just in case;
+ * ignore other endpoints and altsetttings.
+ */
+ for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) {
+ struct usb_host_endpoint *e;
+ int intr = 0;
+
+ e = alt->endpoint + ep;
+ switch (e->desc.bmAttributes) {
+ case USB_ENDPOINT_XFER_INT:
+ if (!(e->desc.bEndpointAddress & USB_DIR_IN))
+ continue;
+ intr = 1;
+ /* FALLTHROUGH */
+ case USB_ENDPOINT_XFER_BULK:
+ break;
+ default:
+ continue;
+ }
+ if (e->desc.bEndpointAddress & USB_DIR_IN) {
+ if (!intr && !in)
+ in = e;
+ else if (intr && !status)
+ status = e;
+ } else {
+ if (!out)
+ out = e;
+ }
+ }
+ if (in && out)
+ break;
+ }
+ if (!alt || !in || !out)
+ return -EINVAL;
+
+ if (alt->desc.bAlternateSetting != 0
+ || !(dev->driver_info->flags & FLAG_NO_SETINT)) {
+ tmp = usb_set_interface (dev->udev, alt->desc.bInterfaceNumber,
+ alt->desc.bAlternateSetting);
+ if (tmp < 0)
+ return tmp;
+ }
+
+ dev->in = usb_rcvbulkpipe (dev->udev,
+ in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+ dev->out = usb_sndbulkpipe (dev->udev,
+ out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+ dev->status = status;
+ return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+static void intr_complete (struct urb *urb, struct pt_regs *regs);
+#else
+static void intr_complete (struct urb *urb);
+#endif
+
+static int init_status (struct usbnet *dev, struct usb_interface *intf)
+{
+ char *buf = NULL;
+ unsigned pipe = 0;
+ unsigned maxp;
+ unsigned period;
+
+ if (!dev->driver_info->status)
+ return 0;
+
+ pipe = usb_rcvintpipe (dev->udev,
+ dev->status->desc.bEndpointAddress
+ & USB_ENDPOINT_NUMBER_MASK);
+ maxp = usb_maxpacket (dev->udev, pipe, 0);
+
+ /* avoid 1 msec chatter: min 8 msec poll rate */
+ period = max ((int) dev->status->desc.bInterval,
+ (dev->udev->speed == USB_SPEED_HIGH) ? 7 : 3);
+
+ buf = kmalloc (maxp, GFP_KERNEL);
+ if (buf) {
+ dev->interrupt = usb_alloc_urb (0, GFP_KERNEL);
+ if (!dev->interrupt) {
+ kfree (buf);
+ return -ENOMEM;
+ } else {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
+ dev->interrupt->transfer_flags |= URB_ASYNC_UNLINK;
+#endif
+ usb_fill_int_urb(dev->interrupt, dev->udev, pipe,
+ buf, maxp, intr_complete, dev, period);
+ devdbg(dev,
+ "status ep%din, %d bytes period %d",
+ usb_pipeendpoint(pipe), maxp, period);
+ }
+ }
+ return 0;
+}
+
+/* Passes this packet up the stack, updating its accounting.
+ * Some link protocols batch packets, so their rx_fixup paths
+ * can return clones as well as just modify the original skb.
+ */
+static
+void axusbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
+{
+ int status;
+
+ skb->dev = dev->net;
+ skb->protocol = eth_type_trans (skb, dev->net);
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
+
+ if (netif_msg_rx_status (dev))
+ devdbg (dev, "< rx, len %zu, type 0x%x",
+ skb->len + sizeof (struct ethhdr), skb->protocol);
+ memset (skb->cb, 0, sizeof (struct skb_data));
+ status = netif_rx (skb);
+ if (status != NET_RX_SUCCESS && netif_msg_rx_err (dev))
+ devdbg (dev, "netif_rx status %d", status);
+}
+
+/*-------------------------------------------------------------------------
+ *
+ * Network Device Driver (peer link to "Host Device", from USB host)
+ *
+ *-------------------------------------------------------------------------*/
+
+static
+int axusbnet_change_mtu (struct net_device *net, int new_mtu)
+{
+ struct usbnet *dev = netdev_priv(net);
+ int ll_mtu = new_mtu + net->hard_header_len;
+ int old_hard_mtu = dev->hard_mtu;
+ int old_rx_urb_size = dev->rx_urb_size;
+
+ if (new_mtu <= 0)
+ return -EINVAL;
+ // no second zero-length packet read wanted after mtu-sized packets
+ if ((ll_mtu % dev->maxpacket) == 0)
+ return -EDOM;
+ net->mtu = new_mtu;
+
+ dev->hard_mtu = net->mtu + net->hard_header_len;
+ if (dev->rx_urb_size == old_hard_mtu) {
+ dev->rx_urb_size = dev->hard_mtu;
+ if (dev->rx_urb_size > old_rx_urb_size)
+ axusbnet_unlink_rx_urbs(dev);
+ }
+
+ return 0;
+}
+
+static struct net_device_stats *axusbnet_get_stats (struct net_device *net)
+{
+ struct usbnet *dev = netdev_priv (net);
+ return &dev->stats;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* some LK 2.4 HCDs oopsed if we freed or resubmitted urbs from
+ * completion callbacks. 2.5 should have fixed those bugs...
+ */
+
+static void
+defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_head *list)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&list->lock, flags);
+ __skb_unlink(skb, list);
+ spin_unlock(&list->lock);
+ spin_lock(&dev->done.lock);
+ __skb_queue_tail(&dev->done, skb);
+ if (dev->done.qlen == 1)
+ tasklet_schedule(&dev->bh);
+ spin_unlock_irqrestore(&dev->done.lock, flags);
+}
+
+/* some work can't be done in tasklets, so we use keventd
+ *
+ * NOTE: annoying asymmetry: if it's active, schedule_work() fails,
+ * but tasklet_schedule() doesn't. hope the failure is rare.
+ */
+static
+void axusbnet_defer_kevent (struct usbnet *dev, int work)
+{
+ set_bit (work, &dev->flags);
+ if (!schedule_work (&dev->kevent))
+ deverr (dev, "kevent %d may have been dropped", work);
+ else
+ devdbg (dev, "kevent %d scheduled", work);
+}
+
+/*-------------------------------------------------------------------------*/
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+static void rx_complete (struct urb *urb, struct pt_regs *regs);
+#else
+static void rx_complete (struct urb *urb);
+#endif
+
+static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
+{
+ struct sk_buff *skb;
+ struct skb_data *entry;
+ int retval = 0;
+ unsigned long lockflags;
+ size_t size = dev->rx_urb_size;
+ struct driver_info *info = dev->driver_info;
+ u8 align;
+
+#if (AX_FORCE_BUFF_ALIGN)
+ align = 0;
+#else
+ if (!(info->flags & FLAG_HW_IP_ALIGNMENT))
+ align = NET_IP_ALIGN;
+ else
+ align = 0;
+#endif
+
+ if ((skb = alloc_skb (size + align, flags)) == NULL) {
+
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "no rx skb");
+
+ if((dev->rx_urb_size > 2048) && dev->rx_size) {
+ dev->rx_size--;
+ dev->rx_urb_size = AX88772B_BULKIN_SIZE[dev->rx_size].size;
+
+ ax8817x_write_cmd_async (dev, 0x2A,
+ AX88772B_BULKIN_SIZE[dev->rx_size].byte_cnt,
+ AX88772B_BULKIN_SIZE[dev->rx_size].threshold,
+ 0, NULL);
+ }
+
+ if (!(dev->flags & EVENT_RX_MEMORY))
+ axusbnet_defer_kevent (dev, EVENT_RX_MEMORY);
+ usb_free_urb (urb);
+ return;
+ }
+
+ if (align)
+ skb_reserve (skb, NET_IP_ALIGN);
+
+ entry = (struct skb_data *) skb->cb;
+ entry->urb = urb;
+ entry->dev = dev;
+ entry->state = rx_start;
+ entry->length = 0;
+
+ usb_fill_bulk_urb (urb, dev->udev, dev->in,
+ skb->data, size, rx_complete, skb);
+
+ spin_lock_irqsave (&dev->rxq.lock, lockflags);
+
+ if (netif_running (dev->net)
+ && netif_device_present (dev->net)
+ && !test_bit (EVENT_RX_HALT, &dev->flags)) {
+ switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) {
+ case -EPIPE:
+ axusbnet_defer_kevent (dev, EVENT_RX_HALT);
+ break;
+ case -ENOMEM:
+ axusbnet_defer_kevent (dev, EVENT_RX_MEMORY);
+ break;
+ case -ENODEV:
+ if (netif_msg_ifdown (dev))
+ devdbg (dev, "device gone");
+ netif_device_detach (dev->net);
+ break;
+ default:
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "rx submit, %d", retval);
+ tasklet_schedule (&dev->bh);
+ break;
+ case 0:
+ __skb_queue_tail (&dev->rxq, skb);
+ }
+ } else {
+ if (netif_msg_ifdown (dev))
+ devdbg (dev, "rx: stopped");
+ retval = -ENOLINK;
+ }
+ spin_unlock_irqrestore (&dev->rxq.lock, lockflags);
+ if (retval) {
+ dev_kfree_skb_any (skb);
+ usb_free_urb (urb);
+ }
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
+{
+ if (dev->driver_info->rx_fixup
+ && !dev->driver_info->rx_fixup (dev, skb))
+ goto error;
+ // else network stack removes extra byte if we forced a short packet
+
+ if (skb->len)
+ axusbnet_skb_return (dev, skb);
+ else {
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "drop");
+error:
+ dev->stats.rx_errors++;
+ skb_queue_tail (&dev->done, skb);
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+static void rx_complete (struct urb *urb, struct pt_regs *regs)
+#else
+static void rx_complete (struct urb *urb)
+#endif
+{
+ struct sk_buff *skb = (struct sk_buff *) urb->context;
+ struct skb_data *entry = (struct skb_data *) skb->cb;
+ struct usbnet *dev = entry->dev;
+ int urb_status = urb->status;
+
+ skb_put (skb, urb->actual_length);
+ entry->state = rx_done;
+ entry->urb = NULL;
+
+ switch (urb_status) {
+ /* success */
+ case 0:
+ if (skb->len < dev->net->hard_header_len) {
+ entry->state = rx_cleanup;
+ dev->stats.rx_errors++;
+ dev->stats.rx_length_errors++;
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "rx length %d", skb->len);
+ }
+ break;
+
+ /* stalls need manual reset. this is rare ... except that
+ * when going through USB 2.0 TTs, unplug appears this way.
+ * we avoid the highspeed version of the ETIMEDOUT/EILSEQ
+ * storm, recovering as needed.
+ */
+ case -EPIPE:
+ dev->stats.rx_errors++;
+ axusbnet_defer_kevent (dev, EVENT_RX_HALT);
+ // FALLTHROUGH
+
+ /* software-driven interface shutdown */
+ case -ECONNRESET: /* async unlink */
+ case -ESHUTDOWN: /* hardware gone */
+ if (netif_msg_ifdown (dev))
+ devdbg (dev, "rx shutdown, code %d", urb_status);
+ goto block;
+
+ /* we get controller i/o faults during khubd disconnect() delays.
+ * throttle down resubmits, to avoid log floods; just temporarily,
+ * so we still recover when the fault isn't a khubd delay.
+ */
+ case -EPROTO:
+ case -ETIME:
+ case -EILSEQ:
+ dev->stats.rx_errors++;
+ if (!timer_pending (&dev->delay)) {
+ mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES);
+ if (netif_msg_link (dev))
+ devdbg (dev, "rx throttle %d", urb_status);
+ }
+block:
+ entry->state = rx_cleanup;
+ entry->urb = urb;
+ urb = NULL;
+ break;
+
+ /* data overrun ... flush fifo? */
+ case -EOVERFLOW:
+ dev->stats.rx_over_errors++;
+ // FALLTHROUGH
+
+ default:
+ entry->state = rx_cleanup;
+ dev->stats.rx_errors++;
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "rx status %d", urb_status);
+ break;
+ }
+
+ defer_bh(dev, skb, &dev->rxq);
+
+ if (urb) {
+ if (netif_running (dev->net)
+ && !test_bit (EVENT_RX_HALT, &dev->flags)) {
+ rx_submit (dev, urb, GFP_ATOMIC);
+ return;
+ }
+ usb_free_urb (urb);
+ }
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "no read resubmitted");
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+static void intr_complete (struct urb *urb, struct pt_regs *regs)
+#else
+static void intr_complete (struct urb *urb)
+#endif
+{
+ struct usbnet *dev = urb->context;
+ int status = urb->status;
+
+ switch (status) {
+ /* success */
+ case 0:
+ dev->driver_info->status(dev, urb);
+ break;
+
+ /* software-driven interface shutdown */
+ case -ENOENT: /* urb killed */
+ case -ESHUTDOWN: /* hardware gone */
+ if (netif_msg_ifdown (dev))
+ devdbg (dev, "intr shutdown, code %d", status);
+ return;
+
+ /* NOTE: not throttling like RX/TX, since this endpoint
+ * already polls infrequently
+ */
+ default:
+ devdbg (dev, "intr status %d", status);
+ break;
+ }
+
+ if (!netif_running (dev->net))
+ return;
+
+ memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
+ status = usb_submit_urb (urb, GFP_ATOMIC);
+ if (status != 0 && netif_msg_timer (dev))
+ deverr(dev, "intr resubmit --> %d", status);
+}
+
+/*-------------------------------------------------------------------------*/
+
+// unlink pending rx/tx; completion handlers do all other cleanup
+
+static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
+{
+ unsigned long flags;
+ struct sk_buff *skb, *skbnext;
+ int count = 0;
+
+ spin_lock_irqsave (&q->lock, flags);
+ skb_queue_walk_safe(q, skb, skbnext) {
+ struct skb_data *entry;
+ struct urb *urb;
+ int retval;
+
+ entry = (struct skb_data *) skb->cb;
+ urb = entry->urb;
+
+ // during some PM-driven resume scenarios,
+ // these (async) unlinks complete immediately
+ retval = usb_unlink_urb (urb);
+ if (retval != -EINPROGRESS && retval != 0)
+ devdbg (dev, "unlink urb err, %d", retval);
+ else
+ count++;
+ }
+ spin_unlock_irqrestore (&q->lock, flags);
+ return count;
+}
+
+// Flush all pending rx urbs
+// minidrivers may need to do this when the MTU changes
+
+static
+void axusbnet_unlink_rx_urbs(struct usbnet *dev)
+{
+ if (netif_running(dev->net)) {
+ (void) unlink_urbs (dev, &dev->rxq);
+ tasklet_schedule(&dev->bh);
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+// precondition: never called in_interrupt
+
+static
+int axusbnet_stop (struct net_device *net)
+{
+ struct usbnet *dev = netdev_priv(net);
+ struct driver_info *info = dev->driver_info;
+ int temp;
+ int retval;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
+ DECLARE_WAIT_QUEUE_HEAD_ONSTACK (unlink_wakeup);
+#else
+ DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup);
+#endif
+ DECLARE_WAITQUEUE (wait, current);
+
+ netif_stop_queue (net);
+
+ if (netif_msg_ifdown (dev))
+ devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
+ dev->stats.rx_packets, dev->stats.tx_packets,
+ dev->stats.rx_errors, dev->stats.tx_errors
+ );
+
+ /* allow minidriver to stop correctly (wireless devices to turn off
+ * radio etc) */
+ if (info->stop) {
+ retval = info->stop(dev);
+ if (retval < 0 && netif_msg_ifdown(dev))
+ devinfo(dev,
+ "stop fail (%d) usbnet usb-%s-%s, %s",
+ retval,
+ dev->udev->bus->bus_name, dev->udev->devpath,
+ info->description);
+ }
+
+ if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) {
+ /* ensure there are no more active urbs */
+ add_wait_queue(&unlink_wakeup, &wait);
+ dev->wait = &unlink_wakeup;
+ temp = unlink_urbs(dev, &dev->txq) +
+ unlink_urbs(dev, &dev->rxq);
+
+ /* maybe wait for deletions to finish. */
+ while (!skb_queue_empty(&dev->rxq)
+ && !skb_queue_empty(&dev->txq)
+ && !skb_queue_empty(&dev->done)) {
+ msleep(UNLINK_TIMEOUT_MS);
+ if (netif_msg_ifdown(dev))
+ devdbg(dev, "waited for %d urb completions",
+ temp);
+ }
+ dev->wait = NULL;
+ remove_wait_queue(&unlink_wakeup, &wait);
+ }
+
+ usb_kill_urb(dev->interrupt);
+
+ /* deferred work (task, timer, softirq) must also stop.
+ * can't flush_scheduled_work() until we drop rtnl (later),
+ * else workers could deadlock; so make workers a NOP.
+ */
+ dev->flags = 0;
+ del_timer_sync (&dev->delay);
+ tasklet_kill (&dev->bh);
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+// posts reads, and enables write queuing
+
+// precondition: never called in_interrupt
+
+static
+int axusbnet_open (struct net_device *net)
+{
+ struct usbnet *dev = netdev_priv(net);
+ int retval = 0;
+ struct driver_info *info = dev->driver_info;
+
+ // put into "known safe" state
+ if (info->reset && (retval = info->reset (dev)) < 0) {
+ if (netif_msg_ifup (dev))
+ devinfo (dev,
+ "open reset fail (%d) usbnet usb-%s-%s, %s",
+ retval,
+ dev->udev->bus->bus_name, dev->udev->devpath,
+ info->description);
+ goto done;
+ }
+
+ // insist peer be connected
+ if (info->check_connect && (retval = info->check_connect (dev)) < 0) {
+ if (netif_msg_ifup (dev))
+ devdbg (dev, "can't open; %d", retval);
+ goto done;
+ }
+
+ /* start any status interrupt transfer */
+ if (dev->interrupt) {
+ retval = usb_submit_urb (dev->interrupt, GFP_KERNEL);
+ if (retval < 0) {
+ if (netif_msg_ifup (dev))
+ deverr (dev, "intr submit %d", retval);
+ goto done;
+ }
+ }
+
+ netif_start_queue (net);
+ if (netif_msg_ifup (dev)) {
+ char *framing;
+
+ if (dev->driver_info->flags & FLAG_FRAMING_NC)
+ framing = "NetChip";
+ else if (dev->driver_info->flags & FLAG_FRAMING_GL)
+ framing = "GeneSys";
+ else if (dev->driver_info->flags & FLAG_FRAMING_Z)
+ framing = "Zaurus";
+ else if (dev->driver_info->flags & FLAG_FRAMING_RN)
+ framing = "RNDIS";
+ else if (dev->driver_info->flags & FLAG_FRAMING_AX)
+ framing = "ASIX";
+ else
+ framing = "simple";
+
+ devinfo (dev, "open: enable queueing "
+ "(rx %d, tx %d) mtu %d %s framing",
+ (int)RX_QLEN (dev), (int)TX_QLEN (dev), dev->net->mtu,
+ framing);
+ }
+
+ // delay posting reads until we're fully open
+ tasklet_schedule (&dev->bh);
+ return retval;
+done:
+ return retval;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* ethtool methods; minidrivers may need to add some more, but
+ * they'll probably want to use this base set.
+ */
+
+static
+int axusbnet_get_settings (struct net_device *net, struct ethtool_cmd *cmd)
+{
+ struct usbnet *dev = netdev_priv(net);
+
+ if (!dev->mii.mdio_read)
+ return -EOPNOTSUPP;
+
+ return mii_ethtool_gset(&dev->mii, cmd);
+}
+
+static
+int axusbnet_set_settings (struct net_device *net, struct ethtool_cmd *cmd)
+{
+ struct usbnet *dev = netdev_priv(net);
+ int retval;
+
+ if (!dev->mii.mdio_write)
+ return -EOPNOTSUPP;
+
+ retval = mii_ethtool_sset(&dev->mii, cmd);
+
+ /* link speed/duplex might have changed */
+ if (dev->driver_info->link_reset)
+ dev->driver_info->link_reset(dev);
+
+ return retval;
+
+}
+
+static
+u32 axusbnet_get_link (struct net_device *net)
+{
+ struct usbnet *dev = netdev_priv(net);
+
+ /* If a check_connect is defined, return its result */
+ if (dev->driver_info->check_connect)
+ return dev->driver_info->check_connect (dev) == 0;
+
+ /* if the device has mii operations, use those */
+ if (dev->mii.mdio_read)
+ return mii_link_ok(&dev->mii);
+
+ /* Otherwise, dtrt for drivers calling netif_carrier_{on,off} */
+ return ethtool_op_get_link(net);
+}
+
+static
+int axusbnet_nway_reset(struct net_device *net)
+{
+ struct usbnet *dev = netdev_priv(net);
+
+ if (!dev->mii.mdio_write)
+ return -EOPNOTSUPP;
+
+ return mii_nway_restart(&dev->mii);
+}
+
+static
+void axusbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info)
+{
+ struct usbnet *dev = netdev_priv(net);
+
+ strncpy (info->driver, dev->driver_name, sizeof info->driver);
+ strncpy (info->version, DRIVER_VERSION, sizeof info->version);
+ strncpy (info->fw_version, dev->driver_info->description,
+ sizeof info->fw_version);
+ usb_make_path (dev->udev, info->bus_info, sizeof info->bus_info);
+}
+
+static
+u32 axusbnet_get_msglevel (struct net_device *net)
+{
+ struct usbnet *dev = netdev_priv(net);
+
+ return dev->msg_enable;
+}
+
+static
+void axusbnet_set_msglevel (struct net_device *net, u32 level)
+{
+ struct usbnet *dev = netdev_priv(net);
+
+ dev->msg_enable = level;
+}
+
+/* drivers may override default ethtool_ops in their bind() routine */
+static struct ethtool_ops axusbnet_ethtool_ops = {
+ .get_settings = axusbnet_get_settings,
+ .set_settings = axusbnet_set_settings,
+ .get_link = axusbnet_get_link,
+ .nway_reset = axusbnet_nway_reset,
+ .get_drvinfo = axusbnet_get_drvinfo,
+ .get_msglevel = axusbnet_get_msglevel,
+ .set_msglevel = axusbnet_set_msglevel,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* work that cannot be done in interrupt context uses keventd.
+ *
+ * NOTE: with 2.5 we could do more of this using completion callbacks,
+ * especially now that control transfers can be queued.
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+static void kevent (void *data)
+{
+ struct usbnet *dev = (struct usbnet *)data;
+#else
+static void kevent (struct work_struct *work)
+{
+ struct usbnet *dev =
+ container_of(work, struct usbnet, kevent);
+#endif
+ int status;
+
+ /* usb_clear_halt() needs a thread context */
+ if (test_bit (EVENT_TX_HALT, &dev->flags)) {
+
+ unlink_urbs (dev, &dev->txq);
+ status = usb_clear_halt (dev->udev, dev->out);
+ if (status < 0
+ && status != -EPIPE
+ && status != -ESHUTDOWN) {
+ if (netif_msg_tx_err (dev))
+ deverr (dev, "can't clear tx halt, status %d",
+ status);
+ } else {
+ clear_bit (EVENT_TX_HALT, &dev->flags);
+ if (status != -ESHUTDOWN)
+ netif_wake_queue (dev->net);
+ }
+ }
+ if (test_bit (EVENT_RX_HALT, &dev->flags)) {
+
+ unlink_urbs (dev, &dev->rxq);
+ status = usb_clear_halt (dev->udev, dev->in);
+ if (status < 0
+ && status != -EPIPE
+ && status != -ESHUTDOWN) {
+ if (netif_msg_rx_err (dev))
+ deverr (dev, "can't clear rx halt, status %d",
+ status);
+ } else {
+ clear_bit (EVENT_RX_HALT, &dev->flags);
+ tasklet_schedule (&dev->bh);
+ }
+ }
+
+ /* tasklet could resubmit itself forever if memory is tight */
+ if (test_bit (EVENT_RX_MEMORY, &dev->flags)) {
+ struct urb *urb = NULL;
+
+ if (netif_running (dev->net))
+ urb = usb_alloc_urb (0, GFP_KERNEL);
+ else
+ clear_bit (EVENT_RX_MEMORY, &dev->flags);
+ if (urb != NULL) {
+ clear_bit (EVENT_RX_MEMORY, &dev->flags);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
+ urb->transfer_flags |= URB_ASYNC_UNLINK;
+#endif
+ rx_submit (dev, urb, GFP_KERNEL);
+ tasklet_schedule (&dev->bh);
+ }
+ }
+
+ if (test_bit (EVENT_LINK_RESET, &dev->flags)) {
+ struct driver_info *info = dev->driver_info;
+ int retval = 0;
+
+ clear_bit (EVENT_LINK_RESET, &dev->flags);
+ if(info->link_reset && (retval = info->link_reset(dev)) < 0) {
+ devinfo(dev, "link reset failed (%d) usbnet usb-%s-%s, %s",
+ retval,
+ dev->udev->bus->bus_name, dev->udev->devpath,
+ info->description);
+ }
+ }
+
+ if (dev->flags)
+ devdbg (dev, "kevent done, flags = 0x%lx",
+ dev->flags);
+}
+
+/*-------------------------------------------------------------------------*/
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+static void tx_complete (struct urb *urb, struct pt_regs *regs)
+#else
+static void tx_complete (struct urb *urb)
+#endif
+{
+ struct sk_buff *skb = (struct sk_buff *) urb->context;
+ struct skb_data *entry = (struct skb_data *) skb->cb;
+ struct usbnet *dev = entry->dev;
+
+ if (urb->status == 0) {
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += entry->length;
+ } else {
+ dev->stats.tx_errors++;
+
+ switch (urb->status) {
+ case -EPIPE:
+ axusbnet_defer_kevent (dev, EVENT_TX_HALT);
+ break;
+
+ /* software-driven interface shutdown */
+ case -ECONNRESET: // async unlink
+ case -ESHUTDOWN: // hardware gone
+ break;
+
+ // like rx, tx gets controller i/o faults during khubd delays
+ // and so it uses the same throttling mechanism.
+ case -EPROTO:
+ case -ETIME:
+ case -EILSEQ:
+ if (!timer_pending (&dev->delay)) {
+ mod_timer (&dev->delay,
+ jiffies + THROTTLE_JIFFIES);
+ if (netif_msg_link (dev))
+ devdbg (dev, "tx throttle %d",
+ urb->status);
+ }
+ netif_stop_queue (dev->net);
+ break;
+ default:
+ if (netif_msg_tx_err (dev))
+ devdbg (dev, "tx err %d", entry->urb->status);
+ break;
+ }
+ }
+
+ urb->dev = NULL;
+ entry->state = tx_done;
+ defer_bh(dev, skb, &dev->txq);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static
+void axusbnet_tx_timeout (struct net_device *net)
+{
+ struct usbnet *dev = netdev_priv(net);
+
+ unlink_urbs (dev, &dev->txq);
+ tasklet_schedule (&dev->bh);
+
+ // FIXME: device recovery -- reset?
+}
+
+/*-------------------------------------------------------------------------*/
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
+static int
+#else
+static netdev_tx_t
+#endif
+axusbnet_start_xmit (struct sk_buff *skb,
+ struct net_device *net)
+{
+ struct usbnet *dev = netdev_priv(net);
+ int length;
+ struct urb *urb = NULL;
+ struct skb_data *entry;
+ struct driver_info *info = dev->driver_info;
+ unsigned long flags;
+ int retval;
+
+ // some devices want funky USB-level framing, for
+ // win32 driver (usually) and/or hardware quirks
+ if (info->tx_fixup) {
+ skb = info->tx_fixup (dev, skb, GFP_ATOMIC);
+ if (!skb) {
+ if (netif_msg_tx_err (dev))
+ devdbg (dev, "can't tx_fixup skb");
+ goto drop;
+ }
+ }
+ length = skb->len;
+
+ if (!(urb = usb_alloc_urb (0, GFP_ATOMIC))) {
+ if (netif_msg_tx_err (dev))
+ devdbg (dev, "no urb");
+ goto drop;
+ }
+
+ entry = (struct skb_data *) skb->cb;
+ entry->urb = urb;
+ entry->dev = dev;
+ entry->state = tx_start;
+ entry->length = length;
+
+ usb_fill_bulk_urb (urb, dev->udev, dev->out,
+ skb->data, skb->len, tx_complete, skb);
+
+ /* don't assume the hardware handles USB_ZERO_PACKET
+ * NOTE: strictly conforming cdc-ether devices should expect
+ * the ZLP here, but ignore the one-byte packet.
+ */
+ if (!(info->flags & FLAG_SEND_ZLP) && (length % dev->maxpacket) == 0) {
+ urb->transfer_buffer_length++;
+ if (skb_tailroom(skb)) {
+ skb->data[skb->len] = 0;
+ __skb_put(skb, 1);
+ }
+ }
+
+ spin_lock_irqsave (&dev->txq.lock, flags);
+
+ switch ((retval = usb_submit_urb (urb, GFP_ATOMIC))) {
+ case -EPIPE:
+ netif_stop_queue (net);
+ axusbnet_defer_kevent (dev, EVENT_TX_HALT);
+ break;
+ default:
+ if (netif_msg_tx_err (dev))
+ devdbg (dev, "tx: submit urb err %d", retval);
+ break;
+ case 0:
+ net->trans_start = jiffies;
+ __skb_queue_tail (&dev->txq, skb);
+ if (dev->txq.qlen >= TX_QLEN (dev))
+ netif_stop_queue (net);
+ }
+ spin_unlock_irqrestore (&dev->txq.lock, flags);
+
+ if (retval) {
+ if (netif_msg_tx_err (dev))
+ devdbg (dev, "drop, code %d", retval);
+drop:
+ dev->stats.tx_dropped++;
+ if (skb)
+ dev_kfree_skb_any (skb);
+ usb_free_urb (urb);
+ } else if (netif_msg_tx_queued (dev)) {
+ devdbg (dev, "> tx, len %d, type 0x%x",
+ length, skb->protocol);
+ }
+ return NETDEV_TX_OK;
+}
+
+/*-------------------------------------------------------------------------*/
+
+// tasklet (work deferred from completions, in_irq) or timer
+
+static void axusbnet_bh (unsigned long param)
+{
+ struct usbnet *dev = (struct usbnet *) param;
+ struct sk_buff *skb;
+ struct skb_data *entry;
+
+ while ((skb = skb_dequeue (&dev->done))) {
+ entry = (struct skb_data *) skb->cb;
+ switch (entry->state) {
+ case rx_done:
+ entry->state = rx_cleanup;
+ rx_process (dev, skb);
+ continue;
+ case tx_done:
+ case rx_cleanup:
+ usb_free_urb (entry->urb);
+ dev_kfree_skb (skb);
+ continue;
+ default:
+ devdbg (dev, "bogus skb state %d", entry->state);
+ }
+ }
+
+ // waiting for all pending urbs to complete?
+ if (dev->wait) {
+ if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) {
+ wake_up (dev->wait);
+ }
+
+ // or are we maybe short a few urbs?
+ } else if (netif_running (dev->net)
+ && netif_device_present (dev->net)
+ && !timer_pending (&dev->delay)
+ && !test_bit (EVENT_RX_HALT, &dev->flags)) {
+ int temp = dev->rxq.qlen;
+ int qlen = RX_QLEN (dev);
+
+ if (temp < qlen) {
+ struct urb *urb;
+ int i;
+
+ // don't refill the queue all at once
+ for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) {
+ urb = usb_alloc_urb (0, GFP_ATOMIC);
+ if (urb != NULL) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
+ urb->transfer_flags |= URB_ASYNC_UNLINK;
+#endif
+ rx_submit (dev, urb, GFP_ATOMIC);
+ }
+ }
+ if (temp != dev->rxq.qlen && netif_msg_link (dev))
+ devdbg (dev, "rxqlen %d --> %d",
+ temp, dev->rxq.qlen);
+ if (dev->rxq.qlen < qlen)
+ tasklet_schedule (&dev->bh);
+ }
+ if (dev->txq.qlen < TX_QLEN (dev))
+ netif_wake_queue (dev->net);
+ }
+}
+
+
+/*-------------------------------------------------------------------------
+ *
+ * USB Device Driver support
+ *
+ *-------------------------------------------------------------------------*/
+
+// precondition: never called in_interrupt
+
+static
+void axusbnet_disconnect (struct usb_interface *intf)
+{
+ struct usbnet *dev;
+ struct usb_device *xdev;
+ struct net_device *net;
+
+ dev = usb_get_intfdata(intf);
+ usb_set_intfdata(intf, NULL);
+ if (!dev)
+ return;
+
+ xdev = interface_to_usbdev (intf);
+
+ if (netif_msg_probe (dev))
+ devinfo (dev, "unregister '%s' usb-%s-%s, %s",
+ intf->dev.driver->name,
+ xdev->bus->bus_name, xdev->devpath,
+ dev->driver_info->description);
+
+ net = dev->net;
+ unregister_netdev (net);
+
+ /* we don't hold rtnl here ... */
+ flush_scheduled_work ();
+
+ if (dev->driver_info->unbind)
+ dev->driver_info->unbind (dev, intf);
+
+ free_netdev(net);
+ usb_put_dev (xdev);
+}
+
+/*-------------------------------------------------------------------------*/
+
+// precondition: never called in_interrupt
+
+static int
+axusbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
+{
+ struct usbnet *dev;
+ struct net_device *net;
+ struct usb_host_interface *interface;
+ struct driver_info *info;
+ struct usb_device *xdev;
+ int status;
+ const char *name;
+
+ name = udev->dev.driver->name;
+ info = (struct driver_info *) prod->driver_info;
+ if (!info) {
+ printk (KERN_ERR "blacklisted by %s\n", name);
+ return -ENODEV;
+ }
+ xdev = interface_to_usbdev (udev);
+ interface = udev->cur_altsetting;
+
+ usb_get_dev (xdev);
+
+ status = -ENOMEM;
+
+ // set up our own records
+ net = alloc_etherdev(sizeof(*dev));
+ if (!net) {
+ dbg ("can't kmalloc dev");
+ goto out;
+ }
+
+ dev = netdev_priv(net);
+ dev->udev = xdev;
+ dev->intf = udev;
+ dev->driver_info = info;
+ dev->driver_name = name;
+ dev->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV
+ | NETIF_MSG_PROBE | NETIF_MSG_LINK);
+ skb_queue_head_init (&dev->rxq);
+ skb_queue_head_init (&dev->txq);
+ skb_queue_head_init (&dev->done);
+ dev->bh.func = axusbnet_bh;
+ dev->bh.data = (unsigned long) dev;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ INIT_WORK (&dev->kevent, kevent, dev);
+#else
+ INIT_WORK (&dev->kevent, kevent);
+#endif
+
+ dev->delay.function = axusbnet_bh;
+ dev->delay.data = (unsigned long) dev;
+ init_timer (&dev->delay);
+// mutex_init (&dev->phy_mutex);
+
+ dev->net = net;
+
+ /* rx and tx sides can use different message sizes;
+ * bind() should set rx_urb_size in that case.
+ */
+ dev->hard_mtu = net->mtu + net->hard_header_len;
+
+#if 0
+// dma_supported() is deeply broken on almost all architectures
+ // possible with some EHCI controllers
+ if (dma_supported (&udev->dev, DMA_BIT_MASK(64)))
+ net->features |= NETIF_F_HIGHDMA;
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
+ net->open = axusbnet_open,
+ net->stop = axusbnet_stop,
+ net->hard_start_xmit = axusbnet_start_xmit,
+ net->tx_timeout = axusbnet_tx_timeout,
+ net->get_stats = axusbnet_get_stats;
+#endif
+
+ net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
+ net->ethtool_ops = &axusbnet_ethtool_ops;
+
+ // allow device-specific bind/init procedures
+ // NOTE net->name still not usable ...
+ status = info->bind (dev, udev);
+ if (status < 0) {
+ deverr(dev, "Binding device failed: %d", status);
+ goto out1;
+ }
+
+ /* maybe the remote can't receive an Ethernet MTU */
+ if (net->mtu > (dev->hard_mtu - net->hard_header_len))
+ net->mtu = dev->hard_mtu - net->hard_header_len;
+
+ status = init_status (dev, udev);
+ if (status < 0)
+ goto out3;
+
+ if (!dev->rx_urb_size)
+ dev->rx_urb_size = dev->hard_mtu;
+ dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
+
+ SET_NETDEV_DEV(net, &udev->dev);
+ status = register_netdev (net);
+ if (status) {
+ deverr(dev, "net device registration failed: %d", status);
+ goto out3;
+ }
+
+ if (netif_msg_probe (dev))
+ devinfo (dev, "register '%s' at usb-%s-%s, %s, %pM",
+ udev->dev.driver->name,
+ xdev->bus->bus_name, xdev->devpath,
+ dev->driver_info->description,
+ net->dev_addr);
+
+ // ok, it's ready to go.
+ usb_set_intfdata (udev, dev);
+
+ // start as if the link is up
+ netif_device_attach (net);
+
+ return 0;
+
+out3:
+ if (info->unbind)
+ info->unbind (dev, udev);
+out1:
+ free_netdev(net);
+out:
+ usb_put_dev(xdev);
+ return status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * suspend the whole driver as soon as the first interface is suspended
+ * resume only when the last interface is resumed
+ */
+
+static int axusbnet_suspend (struct usb_interface *intf,
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
+pm_message_t message)
+#else
+u32 message)
+#endif
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+
+ if (!dev->suspend_count++) {
+ /*
+ * accelerate emptying of the rx and queues, to avoid
+ * having everything error out.
+ */
+ netif_device_detach (dev->net);
+ (void) unlink_urbs (dev, &dev->rxq);
+ (void) unlink_urbs (dev, &dev->txq);
+ /*
+ * reattach so runtime management can use and
+ * wake the device
+ */
+ netif_device_attach (dev->net);
+ }
+ return 0;
+}
+
+static int
+axusbnet_resume (struct usb_interface *intf)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+
+ if (!--dev->suspend_count)
+ tasklet_schedule (&dev->bh);
+
+ return 0;
+}
+
diff --git a/drivers/net/usb/axusbnet.h b/drivers/net/usb/axusbnet.h
new file mode 100644
index 000000000000..d492de3b80e1
--- /dev/null
+++ b/drivers/net/usb/axusbnet.h
@@ -0,0 +1,208 @@
+/*
+ * USB Networking Link Interface
+ *
+ * Copyright (C) 2000-2005 by David Brownell <dbrownell@users.sourceforge.net>
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __LINUX_USB_USBNET_H
+#define __LINUX_USB_USBNET_H
+
+#ifndef gfp_t
+#define gfp_t int
+#endif
+
+/* interface from usbnet core to each USB networking link we handle */
+struct usbnet {
+ /* housekeeping */
+ struct usb_device *udev;
+ struct usb_interface *intf;
+ struct driver_info *driver_info;
+ const char *driver_name;
+ void *driver_priv;
+ wait_queue_head_t *wait;
+// struct mutex phy_mutex;
+ unsigned char suspend_count;
+
+ /* i/o info: pipes etc */
+ unsigned in, out;
+ struct usb_host_endpoint *status;
+ unsigned maxpacket;
+ struct timer_list delay;
+
+ /* protocol/interface state */
+ struct net_device *net;
+ struct net_device_stats stats;
+ int msg_enable;
+ unsigned long data [5];
+ u32 xid;
+ u32 hard_mtu; /* count any extra framing */
+ size_t rx_urb_size; /* size for rx urbs */
+ struct mii_if_info mii;
+
+ /* various kinds of pending driver work */
+ struct sk_buff_head rxq;
+ struct sk_buff_head txq;
+ struct sk_buff_head done;
+ struct sk_buff_head rxq_pause;
+ struct urb *interrupt;
+ struct tasklet_struct bh;
+
+ struct work_struct kevent;
+ unsigned long flags;
+# define EVENT_TX_HALT 0
+# define EVENT_RX_HALT 1
+# define EVENT_RX_MEMORY 2
+# define EVENT_STS_SPLIT 3
+# define EVENT_LINK_RESET 4
+# define EVENT_RX_PAUSED 5
+
+ void *priv; /* point to minidriver private data */
+ unsigned char rx_size;
+};
+
+static inline struct usb_driver *driver_of(struct usb_interface *intf)
+{
+ return to_usb_driver(intf->dev.driver);
+}
+
+/* interface from the device/framing level "minidriver" to core */
+struct driver_info {
+ char *description;
+
+ int flags;
+/* framing is CDC Ethernet, not writing ZLPs (hw issues), or optionally: */
+#define FLAG_FRAMING_NC 0x0001 /* guard against device dropouts */
+#define FLAG_FRAMING_GL 0x0002 /* genelink batches packets */
+#define FLAG_FRAMING_Z 0x0004 /* zaurus adds a trailer */
+#define FLAG_FRAMING_RN 0x0008 /* RNDIS batches, plus huge header */
+
+#define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */
+#define FLAG_ETHER 0x0020 /* maybe use "eth%d" names */
+
+#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
+#define FLAG_WLAN 0x0080 /* use "wlan%d" names */
+#define FLAG_AVOID_UNLINK_URBS 0x0100 /* don't unlink urbs at usbnet_stop() */
+#define FLAG_SEND_ZLP 0x0200 /* hw requires ZLPs are sent */
+#define FLAG_HW_IP_ALIGNMENT 0x0400 /* AX88772B support hardware IP alignment */
+
+
+ /* init device ... can sleep, or cause probe() failure */
+ int (*bind)(struct usbnet *, struct usb_interface *);
+
+ /* cleanup device ... can sleep, but can't fail */
+ void (*unbind)(struct usbnet *, struct usb_interface *);
+
+ /* reset device ... can sleep */
+ int (*reset)(struct usbnet *);
+
+ /* stop device ... can sleep */
+ int (*stop)(struct usbnet *);
+
+ /* see if peer is connected ... can sleep */
+ int (*check_connect)(struct usbnet *);
+
+ /* for status polling */
+ void (*status)(struct usbnet *, struct urb *);
+
+ /* link reset handling, called from defer_kevent */
+ int (*link_reset)(struct usbnet *);
+
+ /* fixup rx packet (strip framing) */
+ int (*rx_fixup)(struct usbnet *dev, struct sk_buff *skb);
+
+ /* fixup tx packet (add framing) */
+ struct sk_buff *(*tx_fixup)(struct usbnet *dev,
+ struct sk_buff *skb, gfp_t flags);
+
+ /* early initialization code, can sleep. This is for minidrivers
+ * having 'subminidrivers' that need to do extra initialization
+ * right after minidriver have initialized hardware. */
+ int (*early_init)(struct usbnet *dev);
+
+ /* called by minidriver when receiving indication */
+ void (*indication)(struct usbnet *dev, void *ind, int indlen);
+
+ /* for new devices, use the descriptor-reading code instead */
+ int in; /* rx endpoint */
+ int out; /* tx endpoint */
+
+ unsigned long data; /* Misc driver specific data */
+};
+
+/* Drivers that reuse some of the standard USB CDC infrastructure
+ * (notably, using multiple interfaces according to the CDC
+ * union descriptor) get some helper code.
+ */
+struct cdc_state {
+ struct usb_cdc_header_desc *header;
+ struct usb_cdc_union_desc *u;
+ struct usb_cdc_ether_desc *ether;
+ struct usb_interface *control;
+ struct usb_interface *data;
+};
+
+/* CDC and RNDIS support the same host-chosen packet filters for IN transfers */
+#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \
+ |USB_CDC_PACKET_TYPE_ALL_MULTICAST \
+ |USB_CDC_PACKET_TYPE_PROMISCUOUS \
+ |USB_CDC_PACKET_TYPE_DIRECTED)
+
+
+/* we record the state for each of our queued skbs */
+enum skb_state {
+ illegal = 0,
+ tx_start, tx_done,
+ rx_start, rx_done, rx_cleanup
+};
+
+struct skb_data { /* skb->cb is one of these */
+ struct urb *urb;
+ struct usbnet *dev;
+ enum skb_state state;
+ size_t length;
+};
+
+#ifndef skb_queue_walk_safe
+#define skb_queue_walk_safe(queue, skb, tmp) \
+ for (skb = (queue)->next, tmp = skb->next; \
+ skb != (struct sk_buff *)(queue); \
+ skb = tmp, tmp = skb->next)
+#endif
+
+/* messaging support includes the interface name, so it must not be
+ * used before it has one ... notably, in minidriver bind() calls.
+ */
+#ifdef DEBUG
+#define devdbg(usbnet, fmt, arg...) \
+ printk("%s: " fmt "\n" , (usbnet)->net->name , ## arg)
+#else
+#define devdbg(usbnet, fmt, arg...) \
+ ({ if (0) printk("%s: " fmt "\n" , (usbnet)->net->name , \
+ ## arg); 0; })
+#endif
+
+#define deverr(usbnet, fmt, arg...) \
+ printk(KERN_ERR "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
+#define devwarn(usbnet, fmt, arg...) \
+ printk(KERN_WARNING "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
+
+#define devinfo(usbnet, fmt, arg...) \
+ printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net->name , ## arg); \
+
+
+#endif /* __LINUX_USB_USBNET_H */
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
index 9ab8f3fb68ef..43a3a11db46c 100644
--- a/drivers/regulator/tps6586x-regulator.c
+++ b/drivers/regulator/tps6586x-regulator.c
@@ -64,6 +64,7 @@ struct tps6586x_regulator {
int enable_reg[2];
int *voltages;
int delay; /* delay in us for regulator to stabilize */
+ enum tps6586x_type type;
/* for DVM regulators */
int go_reg;
@@ -236,6 +237,13 @@ static int tps6586x_sm2_voltages[] = {
4200, 4250, 4300, 4350, 4400, 4450, 4500, 4550,
};
+static int tps6586x_sm2fortythree_voltages[] = {
+ 1025, 1225, 1425, 1625, 1050, 1250, 1450, 1650,
+ 1075, 1275, 1475, 1675, 1100, 1300, 1500, 1700,
+ 1125, 1325, 1525, 1725, 1150, 1350, 1550, 1750,
+ 1175, 1375, 1575, 1775, 1200, 1400, 1600, 1800,
+};
+
static int tps6586x_dvm_voltages[] = {
725, 750, 775, 800, 825, 850, 875, 900,
925, 950, 975, 1000, 1025, 1050, 1075, 1100,
@@ -243,7 +251,7 @@ static int tps6586x_dvm_voltages[] = {
1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500,
};
-#define TPS6586X_REGULATOR(_id, vdata, _ops, vreg, shift, nbits, \
+#define TPS6586X_REGULATOR(_id, _type, vdata, _ops, vreg, shift, nbits, \
ereg0, ebit0, ereg1, ebit1, en_time) \
.desc = { \
.name = "REG-" #_id, \
@@ -261,43 +269,62 @@ static int tps6586x_dvm_voltages[] = {
.enable_reg[1] = TPS6586X_SUPPLY##ereg1, \
.enable_bit[1] = (ebit1), \
.voltages = tps6586x_##vdata##_voltages, \
- .delay = en_time,
+ .delay = en_time, \
+ .type = (_type),
#define TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit) \
.go_reg = TPS6586X_##goreg, \
.go_bit = (gobit),
-#define TPS6586X_LDO(_id, vdata, vreg, shift, nbits, \
+#define TPS6586X_LDO(_id, type, vdata, vreg, shift, nbits, \
ereg0, ebit0, ereg1, ebit1, en_time) \
{ \
- TPS6586X_REGULATOR(_id, vdata, ldo_ops, vreg, shift, nbits, \
- ereg0, ebit0, ereg1, ebit1, en_time) \
+ TPS6586X_REGULATOR(_id, type, vdata, ldo_ops, vreg, shift, \
+ nbits, ereg0, ebit0, ereg1, ebit1, en_time) \
}
-#define TPS6586X_DVM(_id, vdata, vreg, shift, nbits, \
+#define TPS6586X_DVM(_id, type, vdata, vreg, shift, nbits, \
ereg0, ebit0, ereg1, ebit1, goreg, gobit, en_time) \
{ \
- TPS6586X_REGULATOR(_id, vdata, dvm_ops, vreg, shift, nbits, \
- ereg0, ebit0, ereg1, ebit1, en_time) \
+ TPS6586X_REGULATOR(_id, type, vdata, dvm_ops, vreg, shift, \
+ nbits, ereg0, ebit0, ereg1, ebit1, en_time) \
TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit) \
}
+/* Note: type ANY means universal, search order matters, place ANY last */
static struct tps6586x_regulator tps6586x_regulator[] = {
- TPS6586X_LDO(LDO_0, ldo0, SUPPLYV1, 5, 3, ENC, 0, END, 0, 4000),
- TPS6586X_LDO(LDO_1, dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1, 4000),
- TPS6586X_LDO(LDO_3, ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2, 3000),
- TPS6586X_LDO(LDO_5, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6, 3000),
- TPS6586X_LDO(LDO_6, ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4, 15000),
- TPS6586X_LDO(LDO_7, ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5, 15000),
- TPS6586X_LDO(LDO_8, ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6, 15000),
- TPS6586X_LDO(LDO_9, ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7, 3000),
- TPS6586X_LDO(LDO_RTC, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7, 0),
- TPS6586X_LDO(SM_2, sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7, 0),
-
- TPS6586X_DVM(LDO_2, dvm, LDO2BV1, 0, 5, ENA, 3, ENB, 3, VCC2, 6, 3000),
- TPS6586X_DVM(SM_0, dvm, SM0V1, 0, 5, ENA, 1, ENB, 1, VCC1, 2, 4000),
- TPS6586X_DVM(SM_1, dvm, SM1V1, 0, 5, ENA, 0, ENB, 0, VCC1, 0, 4000),
- TPS6586X_DVM(LDO_4, ldo4, LDO4V1, 0, 5, ENC, 3, END, 3, VCC1, 6, 15000),
+ TPS6586X_LDO(LDO_0, TPS6586X_ANY, ldo0, SUPPLYV1, 5, 3, ENC, 0, END, 0,
+ 4000),
+ TPS6586X_LDO(LDO_1, TPS6586X_ANY, dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1,
+ 4000),
+ TPS6586X_DVM(LDO_2, TPS6586X_ANY, dvm, LDO2BV1, 0, 5, ENA, 3, ENB, 3,
+ VCC2, 6, 3000),
+ TPS6586X_LDO(LDO_3, TPS6586X_ANY, ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2,
+ 3000),
+ TPS6586X_DVM(LDO_4, TPS6586X_ANY, ldo4, LDO4V1, 0, 5, ENC, 3, END, 3,
+ VCC1, 6, 15000),
+ TPS6586X_LDO(LDO_5, TPS6586X_ANY, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6,
+ 3000),
+ TPS6586X_LDO(LDO_6, TPS6586X_ANY, ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4,
+ 15000),
+ TPS6586X_LDO(LDO_7, TPS6586X_ANY, ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5,
+ 15000),
+ TPS6586X_LDO(LDO_8, TPS6586X_ANY, ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6,
+ 15000),
+ TPS6586X_LDO(LDO_9, TPS6586X_ANY, ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7,
+ 3000),
+ TPS6586X_LDO(LDO_RTC, TPS6586X_ANY, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7,
+ 0),
+ TPS6586X_DVM(SM_0, TPS6586X_ANY, dvm, SM0V1, 0, 5, ENA, 1, ENB, 1,
+ VCC1, 2, 4000),
+ TPS6586X_DVM(SM_1, TPS6586X_ANY, dvm, SM1V1, 0, 5, ENA, 0, ENB, 0,
+ VCC1, 0, 4000),
+ TPS6586X_DVM(SM_2, TPS658623, ldo4, SUPPLYV2, 0, 5, ENC, 3, END, 3,
+ VCC1, 6, 15000),
+ TPS6586X_DVM(SM_2, TPS658643, sm2fortythree, SUPPLYV2, 0, 5, ENC, 3,
+ END, 3, VCC1, 6, 15000),
+ TPS6586X_LDO(SM_2, TPS6586X_ANY, sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7,
+ 0),
};
/*
@@ -399,14 +426,16 @@ static inline int tps6586x_regulator_set_slew_rate(struct platform_device *pdev)
return tps6586x_write(parent, reg, setting->slew_rate);
}
-static inline struct tps6586x_regulator *find_regulator_info(int id)
+static inline struct tps6586x_regulator *find_regulator_info(int id,
+ enum tps6586x_type type)
{
struct tps6586x_regulator *ri;
int i;
for (i = 0; i < ARRAY_SIZE(tps6586x_regulator); i++) {
ri = &tps6586x_regulator[i];
- if (ri->desc.id == id)
+ if ((ri->desc.id == id) && ((ri->type == type) ||
+ (ri->type == TPS6586X_ANY)))
return ri;
}
return NULL;
@@ -421,7 +450,7 @@ static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "Probing reulator %d\n", id);
- ri = find_regulator_info(id);
+ ri = find_regulator_info(id, tps6586x_gettype(pdev->dev.parent));
if (ri == NULL) {
dev_err(&pdev->dev, "invalid regulator ID specified\n");
return -EINVAL;
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index a3f966b39862..295fd2d7c713 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -1641,6 +1641,7 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
struct irq_info *i = dev_id;
struct list_head *l, *end = NULL;
int pass_counter = 0, handled = 0;
+ static unsigned int tegra_spurious = 0;
DEBUG_INTR("serial8250_interrupt(%d)...", irq);
@@ -1674,6 +1675,26 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
handled = 1;
end = NULL;
+ } else if ((up->port.type == PORT_TEGRA) && !handled) {
+ /* irq 68: nobody cared workaround */
+
+ /* The irq request flag sometimes does not get reset or is
+ * asserted immediately, but iir does not indicated this, if
+ * so we get here with iir set to 0xc1, i.e. no irq pending. */
+
+ /* Try enabling the transmit register empty interrupt,
+ * iir becomes 0xc2, irq gets de-asserted and ier is reverted
+ * by the regular code flow in the ISR. */
+ tegra_spurious++;
+ /* Try this every 4096 spurious irq. */
+ if ((tegra_spurious % 0x1000) == 0xfff) {
+ up->ier |= UART_IER_THRI;
+ serial_out(up, UART_IER, up->ier);
+ udelay(1);
+ handled = 1;
+ end = NULL;
+ } else if (end == NULL)
+ end = l;
} else if (end == NULL)
end = l;
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 7b3185ff188a..9f79c267890e 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -399,8 +399,8 @@ static int rndis_function_bind_config(struct android_usb_function *f,
rndis_control_intf.bInterfaceProtocol = 0x03;
}
- return rndis_bind_config(c, rndis->ethaddr, rndis->vendorID,
- rndis->manufacturer);
+ return rndis_bind_config_vendor(c, rndis->ethaddr, rndis->vendorID,
+ rndis->manufacturer);
}
static void rndis_function_unbind_config(struct android_usb_function *f,
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index f187b9eee9e5..25cb5fc8b263 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -774,9 +774,10 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
rndis_set_param_medium(rndis->config, NDIS_MEDIUM_802_3, 0);
rndis_set_host_mac(rndis->config, rndis->ethaddr);
- if (rndis_set_param_vendor(rndis->config, rndis->vendorID,
- rndis->manufacturer))
- goto fail;
+ if (rndis->manufacturer && rndis->vendorID &&
+ rndis_set_param_vendor(rndis->config, rndis->vendorID,
+ rndis->manufacturer))
+ goto fail;
/* NOTE: all that is done without knowing or caring about
* the network link ... which is unavailable to this code
@@ -844,20 +845,8 @@ static inline bool can_support_rndis(struct usb_configuration *c)
return true;
}
-/**
- * rndis_bind_config - add RNDIS network link to a configuration
- * @c: the configuration to support the network link
- * @ethaddr: a buffer in which the ethernet address of the host side
- * side of the link was recorded
- * Context: single threaded during gadget setup
- *
- * Returns zero on success, else negative errno.
- *
- * Caller must have called @gether_setup(). Caller is also responsible
- * for calling @gether_cleanup() before module unload.
- */
int
-rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
u32 vendorID, const char *manufacturer)
{
struct f_rndis *rndis;
diff --git a/drivers/usb/gadget/tegra_udc.c b/drivers/usb/gadget/tegra_udc.c
index c130dae3a8e9..074a9b1ce6d9 100644
--- a/drivers/usb/gadget/tegra_udc.c
+++ b/drivers/usb/gadget/tegra_udc.c
@@ -52,8 +52,8 @@
#include "tegra_udc.h"
-#define DRIVER_DESC "Nvidia Tegra High-Speed USB SOC \
- Device Controller driver"
+#define DRIVER_DESC "Nvidia Tegra High-Speed USB SOC " \
+ "Device Controller driver"
#define DRIVER_AUTHOR "Venkat Moganty/Rakesh Bodla"
#define DRIVER_VERSION "Apr 30, 2012"
@@ -95,6 +95,11 @@ static const u8 tegra_udc_test_packet[53] = {
0xfc, 0x7e, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0x7e
};
+#ifdef CONFIG_MACH_COLIBRI_T20
+/* To limit the speed of USB to full speed */
+extern int g_usb_high_speed;
+#endif /* CONFIG_MACH_COLIBRI_T20 */
+
static struct tegra_udc *the_udc;
#ifdef CONFIG_TEGRA_GADGET_BOOST_CPU_FREQ
@@ -253,6 +258,16 @@ static int dr_controller_reset(struct tegra_udc *udc)
cpu_relax();
}
+#ifdef CONFIG_MACH_COLIBRI_T20
+ /* To limit the speed of USB to full speed */
+ if (!g_usb_high_speed) {
+ tmp = udc_readl(udc, PORTSCX_REG_OFFSET);
+ tmp |= PORTSCX_PORT_FORCE_FULL_SPEED;
+ udc_writel(udc, tmp, PORTSCX_REG_OFFSET);
+ tmp = udc_readl(udc, PORTSCX_REG_OFFSET);
+ }
+#endif /* CONFIG_MACH_COLIBRI_T20 */
+
DBG("%s(%d) END\n", __func__, __LINE__);
return 0;
}
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h
index 46772413f0db..c32227ebac0b 100644
--- a/drivers/usb/gadget/u_ether.h
+++ b/drivers/usb/gadget/u_ether.h
@@ -111,13 +111,13 @@ int eem_bind_config(struct usb_configuration *c);
#ifdef USB_ETH_RNDIS
-int rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
u32 vendorID, const char *manufacturer);
#else
static inline int
-rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
u32 vendorID, const char *manufacturer)
{
return 0;
@@ -125,4 +125,23 @@ rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
#endif
+/**
+ * rndis_bind_config - add RNDIS network link to a configuration
+ * @c: the configuration to support the network link
+ * @ethaddr: a buffer in which the ethernet address of the host side
+ * side of the link was recorded
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gether_setup(). Caller is also responsible
+ * for calling @gether_cleanup() before module unload.
+ */
+static inline int rndis_bind_config(struct usb_configuration *c,
+ u8 ethaddr[ETH_ALEN])
+{
+ return rndis_bind_config_vendor(c, ethaddr, 0, NULL);
+}
+
+
#endif /* __U_ETHER_H */
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 4ddb279cfb35..095447d9e3a2 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -23,12 +23,16 @@
#include <mach/usb_phy.h>
#include <mach/iomap.h>
+#include "../../../arch/arm/mach-tegra/tegra_usb_phy.h"
+
#if 0
#define EHCI_DBG(stuff...) pr_info("ehci-tegra: " stuff)
#else
#define EHCI_DBG(stuff...) do {} while (0)
#endif
+#define TEGRA_USB_PORTSC1_PFSC (1 << 24)
+
static const char driver_name[] = "tegra-ehci";
#define TEGRA_USB_DMA_ALIGN 32
@@ -51,6 +55,22 @@ struct dma_align_buffer {
u8 data[0];
};
+#ifdef CONFIG_MACH_COLIBRI_T20
+/* To limit the speed of USB to full speed */
+int g_usb_high_speed = 0;
+
+/* To limit the speed of USB to full speed */
+static int __init enable_usb_high_speed(char *s)
+{
+ if (!(*s) || !strcmp(s, "1"))
+ g_usb_high_speed = 1;
+
+ return 0;
+}
+__setup("usb_high_speed=", enable_usb_high_speed);
+EXPORT_SYMBOL_GPL(g_usb_high_speed);
+#endif /* CONFIG_MACH_COLIBRI_T20 */
+
static void free_align_buffer(struct urb *urb)
{
struct dma_align_buffer *temp = container_of(urb->transfer_buffer,
@@ -186,6 +206,71 @@ static irqreturn_t tegra_ehci_irq(struct usb_hcd *hcd)
return irq_status;
}
+static int tegra_ehci_internal_port_reset(
+ struct ehci_hcd *ehci,
+ u32 __iomem *portsc_reg
+)
+{
+ u32 temp;
+ unsigned long flags;
+ int retval = 0;
+ int i, tries;
+ u32 saved_usbintr;
+
+ spin_lock_irqsave(&ehci->lock, flags);
+ saved_usbintr = ehci_readl(ehci, &ehci->regs->intr_enable);
+ /* disable USB interrupt */
+ ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+ spin_unlock_irqrestore(&ehci->lock, flags);
+
+ /*
+ * Here we have to do Port Reset at most twice for
+ * Port Enable bit to be set.
+ */
+ for (i = 0; i < 2; i++) {
+ temp = ehci_readl(ehci, portsc_reg);
+ temp |= PORT_RESET;
+ ehci_writel(ehci, temp, portsc_reg);
+ mdelay(10);
+ temp &= ~PORT_RESET;
+ ehci_writel(ehci, temp, portsc_reg);
+ mdelay(1);
+ tries = 100;
+ do {
+ mdelay(1);
+ /*
+ * Up to this point, Port Enable bit is
+ * expected to be set after 2 ms waiting.
+ * USB1 usually takes extra 45 ms, for safety,
+ * we take 100 ms as timeout.
+ */
+ temp = ehci_readl(ehci, portsc_reg);
+ } while (!(temp & PORT_PE) && tries--);
+ if (temp & PORT_PE)
+ break;
+ }
+ if (i == 2)
+ retval = -ETIMEDOUT;
+
+ /*
+ * Clear Connect Status Change bit if it's set.
+ * We can't clear PORT_PEC. It will also cause PORT_PE to be cleared.
+ */
+ if (temp & PORT_CSC)
+ ehci_writel(ehci, PORT_CSC, portsc_reg);
+
+ /*
+ * Write to clear any interrupt status bits that might be set
+ * during port reset.
+ */
+ temp = ehci_readl(ehci, &ehci->regs->status);
+ ehci_writel(ehci, temp, &ehci->regs->status);
+
+ /* restore original interrupt enable bits */
+ ehci_writel(ehci, saved_usbintr, &ehci->regs->intr_enable);
+
+ return retval;
+}
static int tegra_ehci_hub_control(
struct usb_hcd *hcd,
@@ -201,6 +286,29 @@ static int tegra_ehci_hub_control(
int retval = 0;
u32 __iomem *status_reg;
+#ifdef CONFIG_MACH_COLIBRI_T20
+ u32 temp;
+
+ /* To limit the speed of USB to full speed */
+ if (!g_usb_high_speed) {
+ /* Check whether port is not 2nd one internally connected to
+ ASIX Ethernet chip, set PFSC (Port Force Full Speed) only
+ for externally accessible OTG and host port */
+ if (tegra->phy->inst != 1) {
+ status_reg = &ehci->regs->port_status[(wIndex & 0xff)
+ - 1];
+ temp = ehci_readl(ehci, status_reg);
+ /* Check whether PFSC bit is already set or not */
+ if (!(temp & TEGRA_USB_PORTSC1_PFSC)) {
+ ehci_writel(ehci, (temp |
+ TEGRA_USB_PORTSC1_PFSC),
+ status_reg);
+ temp = ehci_readl(ehci, status_reg);
+ }
+ }
+ }
+#endif /* CONFIG_MACH_COLIBRI_T20 */
+
if (!tegra_usb_phy_hw_accessible(tegra->phy)) {
if (buf)
memset(buf, 0, wLength);
@@ -249,6 +357,13 @@ static int tegra_ehci_hub_control(
break;
}
+ /* For USB1 port we need to issue Port Reset twice internally */
+ if (tegra->phy->inst == 0 &&
+ (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_RESET)) {
+ status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1];
+ return tegra_ehci_internal_port_reset(ehci, status_reg);
+ }
+
/* handle ehci hub control request */
retval = ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index bcb3e8680337..e38d2b4ca134 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -25,6 +25,14 @@ if USB || USB_GADGET
#
# USB Transceiver Drivers
#
+config USB_COLIBRI_OTG
+ boolean "Colibri OTG Driver"
+ depends on USB && ARCH_TEGRA && !USB_TEGRA_OTG
+ select USB_OTG_UTILS
+ help
+ Enable this driver on boards which use a regular GPIO for VBUS
+ detection.
+
config USB_GPIO_VBUS
tristate "GPIO based peripheral-only VBUS sensing 'transceiver'"
depends on GENERIC_GPIO
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
index 0ef95e45a583..cbedff4e254f 100644
--- a/drivers/usb/otg/Makefile
+++ b/drivers/usb/otg/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_USB_OTG_UTILS) += otg_id.o
# transceiver drivers
obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o
+obj-$(CONFIG_USB_COLIBRI_OTG) += colibri-otg.o
CFLAGS_tegra-otg.o = -Werror
obj-$(CONFIG_USB_TEGRA_OTG) += tegra-otg.o
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
diff --git a/drivers/usb/otg/colibri-otg.c b/drivers/usb/otg/colibri-otg.c
new file mode 100644
index 000000000000..54d792536363
--- /dev/null
+++ b/drivers/usb/otg/colibri-otg.c
@@ -0,0 +1,268 @@
+/*
+ * drivers/usb/otg/colibri-otg.c
+ *
+ * OTG transceiver driver for Tegra UTMI phy with GPIO VBUS detection
+ *
+ * Copyright (C) 2010 NVIDIA Corp.
+ * Copyright (C) 2010 Google, Inc.
+ * Copyright (C) 2012 Toradex, Inc.
+ *
+ * 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.
+ */
+
+#include <linux/colibri_usb.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/otg.h>
+
+#include <mach/gpio.h>
+
+struct colibri_otg_data {
+ struct otg_transceiver otg;
+ spinlock_t lock;
+ int irq;
+ struct platform_device *host;
+ struct platform_device *pdev;
+ struct work_struct work;
+};
+
+static const char *tegra_state_name(enum usb_otg_state state)
+{
+ if (state == OTG_STATE_A_HOST)
+ return "HOST";
+ if (state == OTG_STATE_B_PERIPHERAL)
+ return "PERIPHERAL";
+ if (state == OTG_STATE_A_SUSPEND)
+ return "SUSPEND";
+ return "INVALID";
+}
+
+void tegra_start_host(struct colibri_otg_data *tegra)
+{
+ struct colibri_otg_platform_data *pdata = tegra->otg.dev->platform_data;
+ if (!tegra->pdev) {
+ tegra->pdev = pdata->host_register();
+ }
+}
+
+void tegra_stop_host(struct colibri_otg_data *tegra)
+{
+ struct colibri_otg_platform_data *pdata = tegra->otg.dev->platform_data;
+ if (tegra->pdev) {
+ pdata->host_unregister(tegra->pdev);
+ tegra->pdev = NULL;
+ }
+}
+
+static void tegra_otg_notify_event(struct otg_transceiver *otg,
+ enum usb_xceiv_events event)
+{
+ otg->last_event = event;
+ atomic_notifier_call_chain(&otg->notifier, event, NULL);
+}
+
+static void irq_work(struct work_struct *work)
+{
+ struct colibri_otg_data *tegra =
+ container_of(work, struct colibri_otg_data, work);
+ struct otg_transceiver *otg = &tegra->otg;
+ enum usb_otg_state from = otg->state;
+ enum usb_otg_state to = OTG_STATE_UNDEFINED;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tegra->lock, flags);
+
+ /* Check client detect (High active) */
+ mdelay(100);
+ if (gpio_get_value(irq_to_gpio(tegra->irq)))
+ to = OTG_STATE_B_PERIPHERAL;
+ else
+ to = OTG_STATE_A_HOST;
+
+ spin_unlock_irqrestore(&tegra->lock, flags);
+
+ if (to != OTG_STATE_UNDEFINED) {
+ otg->state = to;
+
+ if (from != to) {
+ dev_info(tegra->otg.dev, "%s --> %s\n",
+ tegra_state_name(from), tegra_state_name(to));
+
+ if (to == OTG_STATE_B_PERIPHERAL) {
+ if (from == OTG_STATE_A_HOST) {
+ tegra_stop_host(tegra);
+ tegra_otg_notify_event(otg, USB_EVENT_NONE);
+ }
+ if (otg->gadget) {
+ usb_gadget_vbus_connect(otg->gadget);
+ tegra_otg_notify_event(otg, USB_EVENT_VBUS);
+ }
+ } else if (to == OTG_STATE_A_HOST) {
+ if (otg->gadget && (from == OTG_STATE_B_PERIPHERAL)) {
+ usb_gadget_vbus_disconnect(otg->gadget);
+ tegra_otg_notify_event(otg, USB_EVENT_NONE);
+ }
+ tegra_start_host(tegra);
+ tegra_otg_notify_event(otg, USB_EVENT_ID);
+ }
+ }
+ }
+}
+
+static irqreturn_t colibri_otg_irq(int irq, void *data)
+{
+ struct colibri_otg_data *tegra = data;
+
+ schedule_work(&tegra->work);
+
+ return IRQ_HANDLED;
+}
+
+static int colibri_otg_set_peripheral(struct otg_transceiver *otg,
+ struct usb_gadget *gadget)
+{
+ struct colibri_otg_data *tegra;
+
+ tegra = container_of(otg, struct colibri_otg_data, otg);
+ otg->gadget = gadget;
+
+ /* Set initial state */
+ schedule_work(&tegra->work);
+
+ return 0;
+}
+
+static int colibri_otg_set_host(struct otg_transceiver *otg,
+ struct usb_bus *host)
+{
+ struct colibri_otg_data *tegra;
+
+ tegra = container_of(otg, struct colibri_otg_data, otg);
+ otg->host = host;
+
+ return 0;
+}
+
+static int colibri_otg_set_power(struct otg_transceiver *otg, unsigned mA)
+{
+ return 0;
+}
+
+static int colibri_otg_set_suspend(struct otg_transceiver *otg, int suspend)
+{
+ return 0;
+}
+
+static int colibri_otg_probe(struct platform_device *pdev)
+{
+ struct colibri_otg_data *tegra;
+ struct colibri_otg_platform_data *plat = pdev->dev.platform_data;
+ int err, gpio_cd;
+
+ if (!plat) {
+ dev_err(&pdev->dev, "no platform data?\n");
+ return -ENODEV;
+ }
+
+ tegra = kzalloc(sizeof(struct colibri_otg_data), GFP_KERNEL);
+ if (!tegra)
+ return -ENOMEM;
+
+ tegra->otg.dev = &pdev->dev;
+ tegra->otg.label = "colibri-otg";
+ tegra->otg.state = OTG_STATE_UNDEFINED;
+ tegra->otg.set_host = colibri_otg_set_host;
+ tegra->otg.set_peripheral = colibri_otg_set_peripheral;
+ tegra->otg.set_suspend = colibri_otg_set_suspend;
+ tegra->otg.set_power = colibri_otg_set_power;
+ spin_lock_init(&tegra->lock);
+
+ platform_set_drvdata(pdev, tegra);
+
+ tegra->otg.state = OTG_STATE_A_SUSPEND;
+
+ err = otg_set_transceiver(&tegra->otg);
+ if (err) {
+ dev_err(&pdev->dev, "can't register transceiver (%d)\n", err);
+ goto err_otg;
+ }
+
+ gpio_cd = plat->cable_detect_gpio;
+ err = gpio_request(gpio_cd, "USBC_DET");
+ if (err)
+ goto err_gpio;
+ gpio_direction_input(gpio_cd);
+
+ tegra->irq = gpio_to_irq(gpio_cd);
+ err = request_threaded_irq(tegra->irq, colibri_otg_irq, NULL,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ "colibri-otg USBC_DET", tegra);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to register USB client detect IRQ\n");
+ goto err_irq;
+ }
+
+ INIT_WORK (&tegra->work, irq_work);
+
+ dev_info(&pdev->dev, "otg transceiver registered\n");
+
+ return 0;
+
+err_irq:
+ gpio_free(gpio_cd);
+err_gpio:
+ otg_set_transceiver(NULL);
+err_otg:
+ platform_set_drvdata(pdev, NULL);
+ kfree(tegra);
+ return err;
+}
+
+static int __exit colibri_otg_remove(struct platform_device *pdev)
+{
+ struct colibri_otg_data *tegra = platform_get_drvdata(pdev);
+
+ free_irq(tegra->irq, tegra);
+ gpio_free(irq_to_gpio(tegra->irq));
+ otg_set_transceiver(NULL);
+ platform_set_drvdata(pdev, NULL);
+ kfree(tegra);
+
+ return 0;
+}
+
+static struct platform_driver colibri_otg_driver = {
+ .driver = {
+ .name = "colibri-otg",
+ },
+ .remove = __exit_p(colibri_otg_remove),
+ .probe = colibri_otg_probe,
+};
+
+static int __init colibri_otg_init(void)
+{
+ return platform_driver_register(&colibri_otg_driver);
+}
+subsys_initcall(colibri_otg_init);
+
+static void __exit colibri_otg_exit(void)
+{
+ platform_driver_unregister(&colibri_otg_driver);
+}
+module_exit(colibri_otg_exit);
diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig
index 39ac49e0682c..7fce1987ddc7 100644
--- a/drivers/video/logo/Kconfig
+++ b/drivers/video/logo/Kconfig
@@ -82,4 +82,8 @@ config LOGO_M32R_CLUT224
depends on M32R
default y
+config LOGO_CUSTOM_CLUT224
+ bool "Custom 224-color Linux logo"
+ default n
+
endif # LOGO
diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile
index 3b437813584c..45d4b5346d07 100644
--- a/drivers/video/logo/Makefile
+++ b/drivers/video/logo/Makefile
@@ -18,6 +18,8 @@ obj-$(CONFIG_LOGO_M32R_CLUT224) += logo_m32r_clut224.o
obj-$(CONFIG_SPU_BASE) += logo_spe_clut224.o
+obj-$(CONFIG_LOGO_CUSTOM_CLUT224) += logo_custom_clut224.o
+
# How to generate logo's
# Use logo-cfiles to retrieve list of .c files to be built
diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c
index ea7a8ccc830c..6e29415c9790 100644
--- a/drivers/video/logo/logo.c
+++ b/drivers/video/logo/logo.c
@@ -100,6 +100,10 @@ const struct linux_logo * __init_refok fb_find_logo(int depth)
/* M32R Linux logo */
logo = &logo_m32r_clut224;
#endif
+#ifdef CONFIG_LOGO_CUSTOM_CLUT224
+ /* Custom Linux logo */
+ logo = &logo_custom_clut224;
+#endif
}
return logo;
}
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index bfd916e0e16e..d4c3f8bc9a49 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -1067,9 +1067,11 @@ static void tegra_dc_continuous_irq(struct tegra_dc *dc, unsigned long status)
queue_work(system_freezable_wq, &dc->vblank_work);
if (status & FRAME_END_INT) {
+#ifndef CONFIG_ANDROID
struct timespec tm = CURRENT_TIME;
dc->frame_end_timestamp = timespec_to_ns(&tm);
wake_up(&dc->timestamp_wq);
+#endif /* !CONFIG_ANDROID */
/* Mark the frame_end as complete. */
if (!completion_done(&dc->frame_end_complete))
@@ -1079,6 +1081,7 @@ static void tegra_dc_continuous_irq(struct tegra_dc *dc, unsigned long status)
}
}
+#ifndef CONFIG_ANDROID
/* XXX: Not sure if we limit look ahead to 1 frame */
bool tegra_dc_is_within_n_vsync(struct tegra_dc *dc, s64 ts)
{
@@ -1094,6 +1097,7 @@ bool tegra_dc_does_vsync_separate(struct tegra_dc *dc, s64 new_ts, s64 old_ts)
!= div_s64((old_ts - dc->frame_end_timestamp),
dc->frametime_ns)));
}
+#endif /* !CONFIG_ANDROID */
#endif
static irqreturn_t tegra_dc_irq(int irq, void *ptr)
@@ -1781,7 +1785,9 @@ static int tegra_dc_probe(struct nvhost_device *ndev,
mutex_init(&dc->one_shot_lock);
init_completion(&dc->frame_end_complete);
init_waitqueue_head(&dc->wq);
+#ifndef CONFIG_ANDROID
init_waitqueue_head(&dc->timestamp_wq);
+#endif /* !CONFIG_ANDROID */
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
INIT_WORK(&dc->reset_work, tegra_dc_reset_worker);
#endif
diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h
index 75c3a2a29658..e91071f70ddc 100644
--- a/drivers/video/tegra/dc/dc_priv.h
+++ b/drivers/video/tegra/dc/dc_priv.h
@@ -113,14 +113,18 @@ struct tegra_dc {
void *out_data;
struct tegra_dc_mode mode;
+#ifndef CONFIG_ANDROID
s64 frametime_ns;
+#endif /* !CONFIG_ANDROID */
struct tegra_dc_win windows[DC_N_WINDOWS];
struct tegra_dc_blend blend;
int n_windows;
wait_queue_head_t wq;
+#ifndef CONFIG_ANDROID
wait_queue_head_t timestamp_wq;
+#endif /* !CONFIG_ANDROID */
struct mutex lock;
struct mutex one_shot_lock;
@@ -165,7 +169,9 @@ struct tegra_dc {
struct delayed_work underflow_work;
u32 one_shot_delay_ms;
struct delayed_work one_shot_work;
+#ifndef CONFIG_ANDROID
s64 frame_end_timestamp;
+#endif /* !CONFIG_ANDROID */
};
#define print_mode_info(dc, mode) do { \
diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c
index 88273e26c51c..c8104deb5ed6 100644
--- a/drivers/video/tegra/dc/ext/dev.c
+++ b/drivers/video/tegra/dc/ext/dev.c
@@ -56,7 +56,9 @@ struct tegra_dc_ext_flip_data {
struct tegra_dc_ext *ext;
struct work_struct work;
struct tegra_dc_ext_flip_win win[DC_N_WINDOWS];
+#ifndef CONFIG_ANDROID
struct list_head timestamp_node;
+#endif /* !CONFIG_ANDROID */
};
int tegra_dc_ext_get_num_outputs(void)
@@ -208,7 +210,9 @@ static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext,
{
int err = 0;
struct tegra_dc_ext_win *ext_win = &ext->win[win->idx];
+#ifndef CONFIG_ANDROID
s64 timestamp_ns;
+#endif /* !CONFIG_ANDROID */
if (flip_win->handle[TEGRA_DC_Y] == NULL) {
win->flags = 0;
@@ -272,6 +276,7 @@ static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext,
msecs_to_jiffies(500), NULL);
}
+#ifndef CONFIG_ANDROID
#ifndef CONFIG_TEGRA_SIMULATION_PLATFORM
timestamp_ns = timespec_to_ns(&flip_win->attr.timestamp);
@@ -286,6 +291,9 @@ static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext,
}
#endif
return err;
+#else /* !CONFIG_ANDROID */
+ return 0;
+#endif /* !CONFIG_ANDROID */
}
static void (*flip_callback)(void);
@@ -337,11 +345,14 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
for (i = 0; i < DC_N_WINDOWS; i++) {
struct tegra_dc_ext_flip_win *flip_win = &data->win[i];
- int j = 0, index = flip_win->attr.index;
+ int index = flip_win->attr.index;
struct tegra_dc_win *win;
struct tegra_dc_ext_win *ext_win;
+#ifndef CONFIG_ANDROID
+ int j = 0;
struct tegra_dc_ext_flip_data *temp = NULL;
s64 head_timestamp = 0;
+#endif /* !CONFIG_ANDROID */
if (index < 0)
continue;
@@ -353,6 +364,7 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
(flip_win->attr.flags & TEGRA_DC_EXT_FLIP_FLAG_CURSOR))
skip_flip = true;
+#ifndef CONFIG_ANDROID
mutex_lock(&ext_win->queue_lock);
list_for_each_entry(temp, &ext_win->timestamp_queue,
timestamp_node) {
@@ -377,6 +389,7 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
if (!list_empty(&ext_win->timestamp_queue))
list_del(&data->timestamp_node);
mutex_unlock(&ext_win->queue_lock);
+#endif /* !CONFIG_ANDROID */
if (win->flags & TEGRA_WIN_FLAG_ENABLED) {
int j;
@@ -409,6 +422,9 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
flip_callback();
spin_unlock(&flip_callback_lock);
}
+#ifdef CONFIG_ANDROID
+ }
+#endif /* CONFIG_ANDROID */
for (i = 0; i < DC_N_WINDOWS; i++) {
struct tegra_dc_ext_flip_win *flip_win = &data->win[i];
@@ -420,7 +436,9 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
tegra_dc_incr_syncpt_min(ext->dc, index,
flip_win->syncpt_max);
}
+#ifndef CONFIG_ANDROID
}
+#endif /* !CONFIG_ANDROID */
/* unpin and deref previous front buffers */
for (i = 0; i < nr_unpin; i++) {
@@ -531,7 +549,9 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
struct tegra_dc_ext_flip_data *data;
int work_index = -1;
int i, ret = 0;
+#ifndef CONFIG_ANDROID
bool has_timestamp = false;
+#endif /* !CONFIG_ANDROID */
#ifdef CONFIG_ANDROID
int index_check[DC_N_WINDOWS] = {0, };
@@ -572,8 +592,10 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
int index = args->win[i].index;
memcpy(&flip_win->attr, &args->win[i], sizeof(flip_win->attr));
+#ifndef CONFIG_ANDROID
if (timespec_to_ns(&flip_win->attr.timestamp))
has_timestamp = true;
+#endif /* !CONFIG_ANDROID */
if (index < 0)
continue;
@@ -648,11 +670,13 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
ret = -EINVAL;
goto unlock;
}
+#ifndef CONFIG_ANDROID
if (has_timestamp) {
mutex_lock(&ext->win[work_index].queue_lock);
list_add_tail(&data->timestamp_node, &ext->win[work_index].timestamp_queue);
mutex_unlock(&ext->win[work_index].queue_lock);
}
+#endif /* !CONFIG_ANDROID */
queue_work(ext->win[work_index].flip_wq, &data->work);
unlock_windows_for_flip(user, args);
@@ -993,8 +1017,10 @@ static int tegra_dc_ext_setup_windows(struct tegra_dc_ext *ext)
}
mutex_init(&win->lock);
+#ifndef CONFIG_ANDROID
mutex_init(&win->queue_lock);
INIT_LIST_HEAD(&win->timestamp_queue);
+#endif /* !CONFIG_ANDROID */
}
return 0;
diff --git a/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h b/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
index ef7361d1d933..7238e95e59db 100644
--- a/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
+++ b/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
@@ -59,9 +59,11 @@ struct tegra_dc_ext_win {
atomic_t nr_pending_flips;
+#ifndef CONFIG_ANDROID
struct mutex queue_lock;
struct list_head timestamp_queue;
+#endif /* !CONFIG_ANDROID */
};
struct tegra_dc_ext {
diff --git a/drivers/video/tegra/dc/mode.c b/drivers/video/tegra/dc/mode.c
index 3a95f2e7ab0e..6457f9604e90 100644
--- a/drivers/video/tegra/dc/mode.c
+++ b/drivers/video/tegra/dc/mode.c
@@ -137,6 +137,7 @@ static bool check_ref_to_sync(struct tegra_dc_mode *mode)
return true;
}
+#ifndef CONFIG_ANDROID
static s64 calc_frametime_ns(const struct tegra_dc_mode *m)
{
long h_total, v_total;
@@ -147,6 +148,7 @@ static s64 calc_frametime_ns(const struct tegra_dc_mode *m)
return (!m->pclk) ? 0 : (s64)(div_s64(((s64)h_total * v_total *
1000000000ULL), m->pclk));
}
+#endif /* !CONFIG_ANDROID */
/* return in 1000ths of a Hertz */
int tegra_dc_calc_refresh(const struct tegra_dc_mode *m)
@@ -276,7 +278,9 @@ int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode)
panel_sync_rate = dc->out->dsi->rated_refresh_rate * 1000;
print_mode(dc, mode, __func__);
+#ifndef CONFIG_ANDROID
dc->frametime_ns = calc_frametime_ns(mode);
+#endif /* !CONFIG_ANDROID */
return 0;
}
diff --git a/drivers/video/tegra/dc/nvhdcp.c b/drivers/video/tegra/dc/nvhdcp.c
index 3566e2bd33b5..8489ebf69719 100644
--- a/drivers/video/tegra/dc/nvhdcp.c
+++ b/drivers/video/tegra/dc/nvhdcp.c
@@ -760,7 +760,7 @@ static int get_repeater_info(struct tegra_nvhdcp *nvhdcp)
{
int e, retries;
u8 b_caps;
- u16 b_status;
+ u16 b_status = 0;
nvhdcp_vdbg("repeater found:fetching repeater info\n");
diff --git a/drivers/video/tegra/dc/window.c b/drivers/video/tegra/dc/window.c
index cd91fab428ed..af18564f45b9 100644
--- a/drivers/video/tegra/dc/window.c
+++ b/drivers/video/tegra/dc/window.c
@@ -24,7 +24,9 @@
#include "dc_priv.h"
static int no_vsync;
+#ifndef CONFIG_ANDROID
static atomic_t frame_end_ref = ATOMIC_INIT(0);
+#endif /* !CONFIG_ANDROID */
module_param_named(no_vsync, no_vsync, int, S_IRUGO | S_IWUSR);
@@ -41,6 +43,7 @@ static bool tegra_dc_windows_are_clean(struct tegra_dc_win *windows[],
return true;
}
+#ifndef CONFIG_ANDROID
int tegra_dc_config_frame_end_intr(struct tegra_dc *dc, bool enable)
{
tegra_dc_writel(dc, FRAME_END_INT, DC_CMD_INT_STATUS);
@@ -51,6 +54,7 @@ int tegra_dc_config_frame_end_intr(struct tegra_dc *dc, bool enable)
tegra_dc_mask_interrupt(dc, FRAME_END_INT);
return 0;
}
+#endif /* !CONFIG_ANDROID */
static int get_topmost_window(u32 *depths, unsigned long *wins)
{
@@ -418,9 +422,14 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
} else {
clear_bit(V_BLANK_FLIP, &dc->vblank_ref_count);
- tegra_dc_mask_interrupt(dc, V_BLANK_INT | ALL_UF_INT);
+ tegra_dc_mask_interrupt(dc,
+#ifndef CONFIG_ANDROID
+ V_BLANK_INT | ALL_UF_INT);
if (!atomic_read(&frame_end_ref))
tegra_dc_mask_interrupt(dc, FRAME_END_INT);
+#else /* !CONFIG_ANDROID */
+ FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
+#endif /* !CONFIG_ANDROID */
}
if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
@@ -470,7 +479,11 @@ void tegra_dc_trigger_windows(struct tegra_dc *dc)
if (!dirty) {
if (!(dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+#ifndef CONFIG_ANDROID
&& !atomic_read(&frame_end_ref))
+#else /* !CONFIG_ANDROID */
+ )
+#endif /* !CONFIG_ANDROID */
tegra_dc_mask_interrupt(dc, FRAME_END_INT);
}
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index d494001b1226..fcdcb5d5c995 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -170,6 +170,16 @@ extern int __gpio_cansleep(unsigned gpio);
extern int __gpio_to_irq(unsigned gpio);
+#define GPIOF_DIR_OUT (0 << 0)
+#define GPIOF_DIR_IN (1 << 0)
+
+#define GPIOF_INIT_LOW (0 << 1)
+#define GPIOF_INIT_HIGH (1 << 1)
+
+#define GPIOF_IN (GPIOF_DIR_IN)
+#define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW)
+#define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH)
+
/**
* struct gpio - a structure describing a GPIO with configuration
* @gpio: the GPIO number
diff --git a/include/linux/colibri_usb.h b/include/linux/colibri_usb.h
new file mode 100644
index 000000000000..6b3949979c38
--- /dev/null
+++ b/include/linux/colibri_usb.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 Toradex, Inc.
+ *
+ * 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 _COLIBRI_USB_H_
+#define _COLIBRI_USB_H_
+
+struct colibri_otg_platform_data {
+ int cable_detect_gpio;
+ struct platform_device* (*host_register)(void);
+ void (*host_unregister)(struct platform_device*);
+};
+
+#endif /* _COLIBRI_USB_H_ */
diff --git a/include/linux/linux_logo.h b/include/linux/linux_logo.h
index ca5bd91d12e1..2be299513819 100644
--- a/include/linux/linux_logo.h
+++ b/include/linux/linux_logo.h
@@ -47,6 +47,7 @@ extern const struct linux_logo logo_superh_vga16;
extern const struct linux_logo logo_superh_clut224;
extern const struct linux_logo logo_m32r_clut224;
extern const struct linux_logo logo_spe_clut224;
+extern const struct linux_logo logo_custom_clut224;
extern const struct linux_logo *fb_find_logo(int depth);
#ifdef CONFIG_FB_LOGO_EXTRA
diff --git a/include/linux/lm95245.h b/include/linux/lm95245.h
new file mode 100644
index 000000000000..1b0ddbd82759
--- /dev/null
+++ b/include/linux/lm95245.h
@@ -0,0 +1,36 @@
+/*
+ * include/linux/lm95245.h
+ *
+ * LM95245, temperature monitoring device from National Semiconductors
+ *
+ * Copyright (c) 2013, Toradex, Inc.
+ *
+ * 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 _LINUX_LM95245_H
+#define _LINUX_LM95245_H
+
+struct lm95245_platform_data {
+ bool enable_os_pin;
+ void (*probe_callback)(struct device *dev);
+};
+
+void lm95245_get_local_temp(struct device *dev, int *temp);
+void lm95245_get_remote_temp(struct device *dev, int *temp);
+void lm95245_set_remote_os_limit(struct device *dev, int temp);
+void lm95245_set_remote_critical_limit(struct device *dev, int temp);
+
+#endif /* _LINUX_LM95245_H */
diff --git a/include/linux/mfd/tps6586x.h b/include/linux/mfd/tps6586x.h
index 702cee59cc7b..b5e990e9f6ee 100644
--- a/include/linux/mfd/tps6586x.h
+++ b/include/linux/mfd/tps6586x.h
@@ -56,7 +56,6 @@ enum pwm_pfm_mode {
PWM_ONLY,
AUTO_PWM_PFM,
PWM_DEFAULT_VALUE,
-
};
enum slew_rate_settings {
@@ -71,6 +70,14 @@ enum slew_rate_settings {
SLEW_RATE_DEFAULT_VALUE,
};
+enum tps6586x_type {
+ TPS658621A = 0x15,
+ TPS658621D = 0x2c,
+ TPS658623 = 0x1b,
+ TPS658643 = 0x03,
+ TPS6586X_ANY = -1,
+};
+
struct tps6586x_settings {
/* SM0, SM1 and SM2 have PWM-only and auto PWM/PFM mode */
enum pwm_pfm_mode sm_pwm_mode;
@@ -128,5 +135,6 @@ extern int tps6586x_set_bits(struct device *dev, int reg, uint8_t bit_mask);
extern int tps6586x_clr_bits(struct device *dev, int reg, uint8_t bit_mask);
extern int tps6586x_update(struct device *dev, int reg, uint8_t val,
uint8_t mask);
+extern enum tps6586x_type tps6586x_gettype(struct device *dev);
#endif /*__LINUX_MFD_TPS6586X_H */
diff --git a/include/linux/platform_data/tegra_usb.h b/include/linux/platform_data/tegra_usb.h
index 59f928aaa07f..9ad666f987ea 100644
--- a/include/linux/platform_data/tegra_usb.h
+++ b/include/linux/platform_data/tegra_usb.h
@@ -98,6 +98,7 @@ struct tegra_usb_dev_mode_data {
*/
struct tegra_usb_host_mode_data {
int vbus_gpio;
+ int vbus_gpio_inverted;
const char *vbus_reg;
bool hot_plug;
bool remote_wakeup_supported;
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index cc09c562e479..b4793408969d 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -495,14 +495,12 @@ static struct global_cwq *get_gcwq(unsigned int cpu)
static atomic_t *get_pool_nr_running(struct worker_pool *pool)
{
int cpu = pool->gcwq->cpu;
- atomic_t (*nr_running)[NR_WORKER_POOLS];
+ int idx = worker_pool_pri(pool);
if (cpu != WORK_CPU_UNBOUND)
- nr_running = &per_cpu(pool_nr_running, cpu);
+ return &per_cpu(pool_nr_running, cpu)[idx];
else
- nr_running = &unbound_pool_nr_running;
-
- return nr_running[worker_pool_pri(pool)];
+ return &unbound_pool_nr_running[idx];
}
static struct cpu_workqueue_struct *get_cwq(unsigned int cpu,
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 7e4066e131e6..86d46ef9947c 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -20,6 +20,7 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/consumer.h>
+#include <linux/of_device.h>
#include <sound/core.h>
#include <sound/tlv.h>
#include <sound/pcm.h>
@@ -130,27 +131,24 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w,
case SND_SOC_DAPM_POST_PMU:
/* change mic bias resistor to 4Kohm */
snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL,
- SGTL5000_BIAS_R_4k, SGTL5000_BIAS_R_4k);
+ SGTL5000_BIAS_R_MASK,
+ SGTL5000_BIAS_R_4k << SGTL5000_BIAS_R_SHIFT);
break;
case SND_SOC_DAPM_PRE_PMD:
- /*
- * SGTL5000_BIAS_R_8k as mask to clean the two bits
- * of mic bias and output impedance
- */
snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL,
- SGTL5000_BIAS_R_8k, 0);
+ SGTL5000_BIAS_R_MASK, 0);
break;
}
return 0;
}
/*
- * using codec assist to small pop, hp_powerup or lineout_powerup
- * should stay setting until vag_powerup is fully ramped down,
- * vag fully ramped down require 400ms.
+ * As manual described, ADC/DAC only works when VAG powerup,
+ * So enabled VAG before ADC/DAC up.
+ * In power down case, we need wait 400ms when vag fully ramped down.
*/
-static int small_pop_event(struct snd_soc_dapm_widget *w,
+static int power_vag_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
switch (event) {
@@ -159,7 +157,7 @@ static int small_pop_event(struct snd_soc_dapm_widget *w,
SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP);
break;
- case SND_SOC_DAPM_PRE_PMD:
+ case SND_SOC_DAPM_POST_PMD:
snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER,
SGTL5000_VAG_POWERUP, 0);
msleep(400);
@@ -204,12 +202,8 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = {
mic_bias_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
- SND_SOC_DAPM_PGA_E("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0,
- small_pop_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
- SND_SOC_DAPM_PGA_E("LO", SGTL5000_CHIP_ANA_POWER, 0, 0, NULL, 0,
- small_pop_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_PGA("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("LO", SGTL5000_CHIP_ANA_POWER, 0, 0, NULL, 0),
SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0, &adc_mux),
SND_SOC_DAPM_MUX("Headphone Mux", SND_SOC_NOPM, 0, 0, &dac_mux),
@@ -224,8 +218,11 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = {
0, SGTL5000_CHIP_DIG_POWER,
1, 0),
- SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0),
+ SND_SOC_DAPM_SUPPLY("VAG_POWER", SGTL5000_CHIP_ANA_POWER, 7, 0,
+ power_vag_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0),
SND_SOC_DAPM_DAC("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0),
};
@@ -234,13 +231,16 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"Capture Mux", "LINE_IN", "LINE_IN"}, /* line_in --> adc_mux */
{"Capture Mux", "MIC_IN", "MIC_IN"}, /* mic_in --> adc_mux */
+ {"ADC", NULL, "VAG_POWER"},
{"ADC", NULL, "Capture Mux"}, /* adc_mux --> adc */
{"AIFOUT", NULL, "ADC"}, /* adc --> i2s_out */
+ {"DAC", NULL, "VAG_POWER"},
{"DAC", NULL, "AIFIN"}, /* i2s-->dac,skip audio mux */
{"Headphone Mux", "DAC", "DAC"}, /* dac --> hp_mux */
{"LO", NULL, "DAC"}, /* dac --> line_out */
+ {"LINE_IN", NULL, "VAG_POWER"},
{"Headphone Mux", "LINE_IN", "LINE_IN"},/* line_in --> hp_mux */
{"HP", NULL, "Headphone Mux"}, /* hp_mux --> hp */
@@ -367,7 +367,7 @@ static const DECLARE_TLV_DB_SCALE(capture_6db_attenuate, -600, 600, 0);
/* tlv for mic gain, 0db 20db 30db 40db */
static const unsigned int mic_gain_tlv[] = {
- TLV_DB_RANGE_HEAD(4),
+ TLV_DB_RANGE_HEAD(2),
0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0),
};
@@ -402,7 +402,7 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = {
5, 1, 0),
SOC_SINGLE_TLV("Mic Volume", SGTL5000_CHIP_MIC_CTRL,
- 0, 4, 0, mic_gain_tlv),
+ 0, 3, 0, mic_gain_tlv),
};
/* mute the codec used by alsa core */
@@ -725,7 +725,9 @@ static int sgtl5000_pcm_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- snd_soc_update_bits(codec, SGTL5000_CHIP_I2S_CTRL, i2s_ctl, i2s_ctl);
+ snd_soc_update_bits(codec, SGTL5000_CHIP_I2S_CTRL,
+ SGTL5000_I2S_DLEN_MASK | SGTL5000_I2S_SCLKFREQ_MASK,
+ i2s_ctl);
return 0;
}
@@ -756,7 +758,7 @@ static int ldo_regulator_enable(struct regulator_dev *dev)
/* set voltage to register */
snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
- (0x1 << 4) - 1, reg);
+ SGTL5000_LINREG_VDDD_MASK, reg);
snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
SGTL5000_LINEREG_D_POWERUP,
@@ -782,7 +784,7 @@ static int ldo_regulator_disable(struct regulator_dev *dev)
/* clear voltage info */
snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
- (0x1 << 4) - 1, 0);
+ SGTL5000_LINREG_VDDD_MASK, 0);
ldo->enabled = 0;
@@ -808,6 +810,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
int voltage)
{
struct ldo_regulator *ldo;
+ struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
ldo = kzalloc(sizeof(struct ldo_regulator), GFP_KERNEL);
@@ -842,6 +845,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
return ret;
}
+ sgtl5000->ldo = ldo;
return 0;
}
@@ -986,12 +990,12 @@ static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
/* restore regular registers */
for (reg = 0; reg <= SGTL5000_CHIP_SHORT_CTRL; reg += 2) {
- /* this regs depends on the others */
+ /* These regs should restore in particular order */
if (reg == SGTL5000_CHIP_ANA_POWER ||
reg == SGTL5000_CHIP_CLK_CTRL ||
reg == SGTL5000_CHIP_LINREG_CTRL ||
reg == SGTL5000_CHIP_LINE_OUT_CTRL ||
- reg == SGTL5000_CHIP_CLK_CTRL)
+ reg == SGTL5000_CHIP_REF_CTRL)
continue;
snd_soc_write(codec, reg, cache[reg]);
@@ -1002,8 +1006,17 @@ static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
snd_soc_write(codec, reg, cache[reg]);
/*
- * restore power and other regs according
- * to set_power() and set_clock()
+ * restore these regs according to the power setting sequence in
+ * sgtl5000_set_power_regs() and clock setting sequence in
+ * sgtl5000_set_clock().
+ *
+ * The order of restore is:
+ * 1. SGTL5000_CHIP_CLK_CTRL MCLK_FREQ bits (1:0) should be restore after
+ * SGTL5000_CHIP_ANA_POWER PLL bits set
+ * 2. SGTL5000_CHIP_LINREG_CTRL should be set before
+ * SGTL5000_CHIP_ANA_POWER LINREG_D restored
+ * 3. SGTL5000_CHIP_REF_CTRL controls Analog Ground Voltage,
+ * prefer to resotre it after SGTL5000_CHIP_ANA_POWER restored
*/
snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL,
cache[SGTL5000_CHIP_LINREG_CTRL]);
@@ -1115,7 +1128,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
/* set voltage to register */
snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
- (0x1 << 4) - 1, 0x8);
+ SGTL5000_LINREG_VDDD_MASK, 0x8);
/*
* if vddd linear reg has been enabled,
@@ -1146,8 +1159,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
vag = (vag - SGTL5000_ANA_GND_BASE) / SGTL5000_ANA_GND_STP;
snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL,
- vag << SGTL5000_ANA_GND_SHIFT,
- vag << SGTL5000_ANA_GND_SHIFT);
+ SGTL5000_ANA_GND_MASK, vag << SGTL5000_ANA_GND_SHIFT);
/* set line out VAG to vddio / 2, in range (0.8v, 1.675v) */
vag = vddio / 2;
@@ -1161,9 +1173,8 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
SGTL5000_LINE_OUT_GND_STP;
snd_soc_update_bits(codec, SGTL5000_CHIP_LINE_OUT_CTRL,
- vag << SGTL5000_LINE_OUT_GND_SHIFT |
- SGTL5000_LINE_OUT_CURRENT_360u <<
- SGTL5000_LINE_OUT_CURRENT_SHIFT,
+ SGTL5000_LINE_OUT_CURRENT_MASK |
+ SGTL5000_LINE_OUT_GND_MASK,
vag << SGTL5000_LINE_OUT_GND_SHIFT |
SGTL5000_LINE_OUT_CURRENT_360u <<
SGTL5000_LINE_OUT_CURRENT_SHIFT);
@@ -1331,7 +1342,7 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
SGTL5000_HP_ZCD_EN |
SGTL5000_ADC_ZCD_EN);
- snd_soc_write(codec, SGTL5000_CHIP_MIC_CTRL, 0);
+ snd_soc_write(codec, SGTL5000_CHIP_MIC_CTRL, 2);
/*
* disable DAP
@@ -1436,10 +1447,17 @@ static const struct i2c_device_id sgtl5000_id[] = {
MODULE_DEVICE_TABLE(i2c, sgtl5000_id);
+static const struct of_device_id sgtl5000_dt_ids[] = {
+ { .compatible = "fsl,sgtl5000", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sgtl5000_dt_ids);
+
static struct i2c_driver sgtl5000_i2c_driver = {
.driver = {
.name = "sgtl5000",
.owner = THIS_MODULE,
+ .of_match_table = sgtl5000_dt_ids,
},
.probe = sgtl5000_i2c_probe,
.remove = __devexit_p(sgtl5000_i2c_remove),
diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h
index eec3ab368f39..8a9f43534b79 100644
--- a/sound/soc/codecs/sgtl5000.h
+++ b/sound/soc/codecs/sgtl5000.h
@@ -280,7 +280,7 @@
/*
* SGTL5000_CHIP_MIC_CTRL
*/
-#define SGTL5000_BIAS_R_MASK 0x0200
+#define SGTL5000_BIAS_R_MASK 0x0300
#define SGTL5000_BIAS_R_SHIFT 8
#define SGTL5000_BIAS_R_WIDTH 2
#define SGTL5000_BIAS_R_off 0x0
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index de8309be3816..a47a746a2b7e 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -4,6 +4,17 @@ config SND_SOC_TEGRA
help
Say Y or M here if you want support for SoC audio on Tegra.
+config SND_SOC_TEGRA20_AC97
+ tristate "Tegra 20 AC97 driver"
+ select AC97_BUS
+ select SND_AC97_CODEC
+ select SND_SOC_AC97_BUS
+ select SND_SOC_TEGRA20_DAS
+ help
+ Say Y or M if you want to add support for codecs attached to the
+ Tegra AC97 interface. You will also need to select the individual
+ machine drivers to support below.
+
config SND_SOC_TEGRA20_DAS
tristate "Tegra 20 Digital Audio Switch driver"
depends on SND_SOC_TEGRA && ARCH_TEGRA_2x_SOC
@@ -76,6 +87,29 @@ config SND_SOC_TEGRA_WM8903
boards using the WM8093 codec. Currently, the supported boards are
Harmony, Ventana, Seaboard, Kaen, and Aebl.
+config SND_SOC_TEGRA_COLIBRI_T20
+ tristate "SoC Audio support for Colibri T20 module"
+ depends on SND_SOC_TEGRA && MACH_COLIBRI_T20
+ select SND_SOC_SPDIF
+ select SND_SOC_TEGRA20_AC97
+ select SND_SOC_TEGRA20_SPDIF
+ select SND_SOC_WM9712
+ help
+ Say Y or M here if you want to add support for SoC audio on the
+ Toradex Colibri T20 module.
+
+config SND_SOC_TEGRA_COLIBRI_T30
+ tristate "SoC Audio support for Apalis/Colibri T30 modules"
+ depends on I2C && (MACH_APALIS_T30 || MACH_COLIBRI_T30) && SND_SOC_TEGRA
+ select SND_SOC_SGTL5000
+ select SND_SOC_SPDIF
+ select SND_SOC_TEGRA30_DAM
+ select SND_SOC_TEGRA30_I2S
+ select SND_SOC_TEGRA30_SPDIF
+ help
+ Say Y or M here if you want to add support for SoC audio on the
+ Toradex Apalis/Colibri T30 modules.
+
config SND_SOC_TEGRA_TRIMSLICE
tristate "SoC Audio support for TrimSlice board"
depends on SND_SOC_TEGRA && MACH_TRIMSLICE && I2C
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index 83f30054a085..594c963cb8ea 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -8,6 +8,7 @@ snd-soc-tegra-tdm-pcm-objs := tegra_tdm_pcm.o
snd-soc-tegra20-spdif-objs := tegra20_spdif.o
snd-soc-tegra-utils-objs += tegra_asoc_utils.o
snd-soc-tegra20-das-objs := tegra20_das.o
+snd-soc-tegra20-ac97-objs := tegra20_ac97.o
snd-soc-tegra20-i2s-objs := tegra20_i2s.o
snd-soc-tegra30-ahub-objs := tegra30_ahub.o
snd-soc-tegra30-i2s-objs := tegra30_i2s.o
@@ -18,6 +19,7 @@ obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o
obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-utils.o
obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-tdm-pcm.o
obj-$(CONFIG_SND_SOC_TEGRA20_DAS) += snd-soc-tegra20-das.o
+obj-$(CONFIG_SND_SOC_TEGRA20_AC97) += snd-soc-tegra20-ac97.o
obj-$(CONFIG_SND_SOC_TEGRA20_I2S) += snd-soc-tegra20-i2s.o
obj-$(CONFIG_SND_SOC_TEGRA30_AHUB) += snd-soc-tegra30-ahub.o
obj-$(CONFIG_SND_SOC_TEGRA30_DAM) += snd-soc-tegra30-dam.o
@@ -27,6 +29,8 @@ obj-$(CONFIG_SND_SOC_TEGRA30_SPDIF) += snd-soc-tegra30-spdif.o
# Tegra machine Support
snd-soc-tegra-wm8903-objs := tegra_wm8903.o
+snd-soc-tegra-colibri_t20-objs := colibri_t20.o
+snd-soc-tegra-colibri_t30-objs := colibri_t30.o
snd-soc-tegra-trimslice-objs := trimslice.o
snd-soc-tegra-wm8753-objs := tegra_wm8753.o
snd-soc-tegra-max98088-objs := tegra_max98088.o
@@ -36,6 +40,8 @@ snd-soc-tegra-max98095-objs := tegra_max98095.o
snd-soc-tegra-vcm-objs := tegra_vcm.o
obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o
+obj-$(CONFIG_SND_SOC_TEGRA_COLIBRI_T20) += snd-soc-tegra-colibri_t20.o
+obj-$(CONFIG_SND_SOC_TEGRA_COLIBRI_T30) += snd-soc-tegra-colibri_t30.o
obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o
obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o
obj-$(CONFIG_SND_SOC_TEGRA_MAX98088) += snd-soc-tegra-max98088.o
diff --git a/sound/soc/tegra/colibri_t20.c b/sound/soc/tegra/colibri_t20.c
new file mode 100644
index 000000000000..595e5e463f27
--- /dev/null
+++ b/sound/soc/tegra/colibri_t20.c
@@ -0,0 +1,392 @@
+/*
+ * SoC audio driver for Toradex Colibri T20
+ *
+ * Copyright (C) 2012 Toradex Inc.
+ *
+ * 2010-11-19: Marcel Ziswiler <marcel.ziswiler@noser.com>
+ * initial version (note: WM9715L is fully WM9712 compatible)
+ *
+ * Copied from tosa.c:
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
+ * Richard Purdie <richard@openedhand.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 <asm/mach-types.h>
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+
+#include <mach/audio.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h> /* order crucial */
+#include <sound/soc-dapm.h>
+
+#include "../codecs/wm9712.h"
+#include "tegra_asoc_utils.h"
+#include "tegra_pcm.h"
+#include "tegra20_ac97.h"
+
+#define DRV_NAME "colibri_t20-snd-wm9715l"
+
+struct colibri_t20_wm9715l {
+ struct tegra_asoc_utils_data util_data;
+};
+
+static int colibri_t20_wm9715l_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_card *card = codec->card;
+ struct colibri_t20_wm9715l *machine = snd_soc_card_get_drvdata(card);
+ int srate, mclk;
+ int err;
+
+ srate = params_rate(params);
+
+ /* AC97 clock is really fixed */
+ mclk = 24576000;
+
+ err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
+ if (err < 0) {
+ if (!(machine->util_data.set_mclk % mclk))
+ mclk = machine->util_data.set_mclk;
+ else {
+ dev_err(card->dev, "Can't configure clocks\n");
+ return err;
+ }
+ }
+
+ tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
+
+//DAS AC97 DAC to DAP switching already done at probe
+
+ return 0;
+}
+
+static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct colibri_t20_wm9715l *machine = snd_soc_card_get_drvdata(card);
+ int srate, mclk, min_mclk;
+ int err;
+
+ srate = params_rate(params);
+ switch (srate) {
+ case 11025:
+ case 22050:
+ case 44100:
+ case 88200:
+ mclk = 11289600;
+ break;
+ case 8000:
+ case 16000:
+ case 32000:
+ case 48000:
+ case 64000:
+ case 96000:
+ mclk = 12288000;
+ break;
+ default:
+ return -EINVAL;
+ }
+ min_mclk = 128 * srate;
+
+ err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
+ if (err < 0) {
+ if (!(machine->util_data.set_mclk % min_mclk))
+ mclk = machine->util_data.set_mclk;
+ else {
+ dev_err(card->dev, "Can't configure clocks\n");
+ return err;
+ }
+ }
+
+ tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
+
+ return 0;
+}
+
+static int tegra_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct colibri_t20_wm9715l *machine = snd_soc_card_get_drvdata(rtd->card);
+
+ tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
+
+ return 0;
+}
+
+static struct snd_soc_ops colibri_t20_wm9715l_ops = {
+ .hw_params = colibri_t20_wm9715l_hw_params,
+ .hw_free = tegra_hw_free,
+};
+
+static struct snd_soc_ops tegra_spdif_ops = {
+ .hw_params = tegra_spdif_hw_params,
+ .hw_free = tegra_hw_free,
+};
+
+static const struct snd_soc_dapm_widget colibri_t20_wm9715l_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("HEADPHONE", NULL),
+ SND_SOC_DAPM_LINE("LINEIN", NULL),
+ SND_SOC_DAPM_MIC("MIC_IN", NULL),
+};
+
+/* Currently supported audio map */
+static const struct snd_soc_dapm_route colibri_t20_wm9715l_audio_map[] = {
+ /* Colibri SODIMM pin 1 (MIC_IN)
+ Colibri Evaluation Board: Audio jack X26 bottom pink
+ Iris: Audio header X9 pin 2
+ Orchid: Audio jack X11 bottom pink MIC in */
+ { "MIC_IN", NULL, "MIC1" },
+
+ /* Colibri SODIMM pin 5 & 7 (LINEIN_L/R)
+ Colibri Evaluation Board: Audio jack X26 top blue
+ Iris: Audio header X9 pin 4 & 3
+ MECS Tellurium: Audio jack X11 pin 1 & 2
+ Orchid: Audio jack X11 top blue line in */
+ { "LINEIN", NULL, "LINEINL" },
+ { "LINEIN", NULL, "LINEINR" },
+
+ /* Colibri SODIMM pin 15 & 17 (HEADPHONE_L/R)
+ Colibri Evaluation Board: Audio jack X26 middle green
+ Iris: Audio jack X8
+ MECS Tellurium: Audio jack X11 pin 4 & 5 (HEADPHONE_LF/RF)
+ Orchid: Audio jack X11 middle green line out
+ Protea: Audio jack X53 line out */
+ { "HEADPHONE", NULL, "LOUT2" },
+ { "HEADPHONE", NULL, "ROUT2" },
+};
+
+static int colibri_t20_wm9715l_init(struct snd_soc_pcm_runtime *rtd)
+{
+ int err;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+ pr_info("%s()\n", __func__);
+
+//GPIOs
+
+ /* add Colibri T20 specific widgets */
+ err = snd_soc_dapm_new_controls(dapm, colibri_t20_wm9715l_dapm_widgets,
+ ARRAY_SIZE(colibri_t20_wm9715l_dapm_widgets));
+ if (err)
+ return err;
+
+ /* set up Colibri T20 specific audio path audio_map */
+ err = snd_soc_dapm_add_routes(dapm, colibri_t20_wm9715l_audio_map, ARRAY_SIZE(colibri_t20_wm9715l_audio_map));
+ if (err)
+ return err;
+
+//jack detection
+
+ /* connected pins */
+ snd_soc_dapm_enable_pin(dapm, "HPOUTL");
+ snd_soc_dapm_enable_pin(dapm, "HPOUTR");
+ snd_soc_dapm_enable_pin(dapm, "LINEINL");
+ snd_soc_dapm_enable_pin(dapm, "LINEINR");
+ snd_soc_dapm_enable_pin(dapm, "MIC1");
+
+ /* Activate Mic Bias */
+ snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
+
+ /* not connected pins */
+ snd_soc_dapm_nc_pin(dapm, "LOUT2");
+ snd_soc_dapm_nc_pin(dapm, "MIC2");
+ snd_soc_dapm_nc_pin(dapm, "MONOOUT");
+ snd_soc_dapm_nc_pin(dapm, "OUT3");
+ snd_soc_dapm_nc_pin(dapm, "PCBEEP");
+ snd_soc_dapm_nc_pin(dapm, "PHONE");
+ snd_soc_dapm_nc_pin(dapm, "ROUT2");
+
+ err = snd_soc_dapm_sync(dapm);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static struct snd_soc_dai_link colibri_t20_wm9715l_dai[] = {
+ {
+ .name = "AC97",
+// .name = "AC97 HiFi",
+ .stream_name = "AC97 HiFi",
+ .cpu_dai_name = "tegra20-ac97-pcm",
+ .codec_dai_name = "wm9712-hifi",
+ .platform_name = "tegra-pcm-audio",
+ .codec_name = "wm9712-codec",
+ .init = colibri_t20_wm9715l_init,
+ .ops = &colibri_t20_wm9715l_ops,
+ },
+//order
+ {
+ .name = "SPDIF",
+ .stream_name = "SPDIF PCM",
+ .codec_name = "spdif-dit.0",
+ .platform_name = "tegra-pcm-audio",
+ .cpu_dai_name = "tegra20-spdif",
+ .codec_dai_name = "dit-hifi",
+ .ops = &tegra_spdif_ops,
+ },
+#if 0
+ {
+ .name = "AC97 Aux",
+ .stream_name = "AC97 Aux",
+ .cpu_dai_name = "tegra20-ac97-modem",
+ .codec_dai_name = "wm9712-aux",
+ .platform_name = "tegra-pcm-audio",
+ .codec_name = "wm9712-codec",
+ },
+#endif
+};
+
+//power management
+
+static struct snd_soc_card snd_soc_colibri_t20_wm9715l = {
+ .name = "colibri_t20-wm9715l",
+ .dai_link = colibri_t20_wm9715l_dai,
+ .num_links = ARRAY_SIZE(colibri_t20_wm9715l_dai),
+// .suspend_post = colibri_t20_wm9715l_suspend_post,
+// .resume_pre = colibri_t20_wm9715l_resume_pre,
+};
+
+//
+static struct platform_device *colibri_t20_snd_wm9715l_device;
+//
+
+static __devinit int colibri_t20_wm9715l_driver_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &snd_soc_colibri_t20_wm9715l;
+ struct colibri_t20_wm9715l *machine;
+ int ret;
+
+ pr_info("%s()\n", __func__);
+
+ if (!machine_is_colibri_t20())
+ return -ENODEV;
+
+//make sure tegra20-ac97 is properly loaded to avoid subsequent crash
+
+ machine = kzalloc(sizeof(struct colibri_t20_wm9715l), GFP_KERNEL);
+ if (!machine) {
+ dev_err(&pdev->dev, "Can't allocate colibri_t20_wm9715l struct\n");
+ return -ENOMEM;
+ }
+
+ ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev, card);
+ if (ret)
+ goto err_free_machine;
+
+//regulator handling
+
+//switch handling
+
+ card->dev = &pdev->dev;
+ platform_set_drvdata(pdev, card);
+ snd_soc_card_set_drvdata(card, machine);
+
+ /* explicitly instanciate AC97 codec */
+
+ colibri_t20_snd_wm9715l_device = platform_device_alloc("wm9712-codec", -1);
+ if (!colibri_t20_snd_wm9715l_device) {
+ dev_err(&pdev->dev, "platform_device_alloc of wm9712-codec failed (%d)\n",
+ ret);
+ goto err_fini_utils;
+ }
+
+ ret = platform_device_add(colibri_t20_snd_wm9715l_device);
+ if (ret) {
+ dev_err(&pdev->dev, "platform_device_add of wm9712-codec failed (%d)\n",
+ ret);
+ goto err_fini_utils;
+ }
+
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+ ret);
+ goto err_fini_utils;
+ }
+
+ if (!card->instantiated) {
+ ret = -ENODEV;
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+ ret);
+ goto err_unregister_card;
+ }
+
+ return 0;
+
+err_unregister_card:
+ snd_soc_unregister_card(card);
+err_fini_utils:
+ tegra_asoc_utils_fini(&machine->util_data);
+err_free_machine:
+ kfree(machine);
+ return ret;
+}
+
+static int __devexit colibri_t20_wm9715l_driver_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct colibri_t20_wm9715l *machine = snd_soc_card_get_drvdata(card);
+
+ snd_soc_unregister_card(card);
+
+//how to revert?
+// platform_device_alloc("wm9712-codec");
+
+ tegra_asoc_utils_fini(&machine->util_data);
+
+ kfree(machine);
+
+ return 0;
+}
+
+static struct platform_driver colibri_t20_wm9715l_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+// .pm = &snd_soc_pm_ops,
+ },
+ .probe = colibri_t20_wm9715l_driver_probe,
+ .remove = __devexit_p(colibri_t20_wm9715l_driver_remove),
+};
+
+static int __init colibri_t20_wm9715l_modinit(void)
+{
+ return platform_driver_register(&colibri_t20_wm9715l_driver);
+}
+
+static void __exit colibri_t20_wm9715l_modexit(void)
+{
+ platform_driver_unregister(&colibri_t20_wm9715l_driver);
+}
+
+module_init(colibri_t20_wm9715l_modinit);
+module_exit(colibri_t20_wm9715l_modexit);
+
+/* Module information */
+MODULE_AUTHOR("Marcel Ziswiler <marcel.ziswiler@toradex.com>");
+MODULE_DESCRIPTION("ALSA SoC WM9715L on Toradex Colibri T20");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/colibri_t30.c b/sound/soc/tegra/colibri_t30.c
new file mode 100644
index 000000000000..6390be5b8d6b
--- /dev/null
+++ b/sound/soc/tegra/colibri_t30.c
@@ -0,0 +1,412 @@
+/*
+ * SoC audio driver for Toradex Colibri T30
+ *
+ * Copyright (C) 2012 Toradex Inc.
+ *
+ * 2012-02-12: Marcel Ziswiler <marcel.ziswiler@toradex.com>
+ * initial version
+ *
+ * Copied from tegra_wm8903.c
+ * Copyright (C) 2010-2011 - NVIDIA, Inc.
+ *
+ * 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.
+ */
+
+#include <asm/mach-types.h>
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <mach/tegra_asoc_pdata.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "../codecs/sgtl5000.h"
+
+#include "tegra_pcm.h"
+#include "tegra_asoc_utils.h"
+
+#define DRV_NAME "tegra-snd-colibri_t30-sgtl5000"
+
+struct colibri_t30_sgtl5000 {
+ struct tegra_asoc_utils_data util_data;
+ struct tegra_asoc_platform_data *pdata;
+ enum snd_soc_bias_level bias_level;
+};
+
+static int colibri_t30_sgtl5000_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_card *card = codec->card;
+ struct colibri_t30_sgtl5000 *machine = snd_soc_card_get_drvdata(card);
+ struct tegra_asoc_platform_data *pdata = machine->pdata;
+ int srate, mclk, i2s_daifmt;
+ int err;
+ int rate;
+
+ /* sgtl5000 does not support 512*rate when in 96000 fs */
+ srate = params_rate(params);
+ switch (srate) {
+ case 96000:
+ mclk = 256 * srate;
+ break;
+ default:
+ mclk = 512 * srate;
+ break;
+ }
+
+ /* Sgtl5000 sysclk should be >= 8MHz and <= 27M */
+ if (mclk < 8000000 || mclk > 27000000)
+ return -EINVAL;
+
+ if(pdata->i2s_param[HIFI_CODEC].is_i2s_master) {
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS;
+ } else {
+ i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM;
+ }
+
+ err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
+ if (err < 0) {
+ if (!(machine->util_data.set_mclk % mclk))
+ mclk = machine->util_data.set_mclk;
+ else {
+ dev_err(card->dev, "Can't configure clocks\n");
+ return err;
+ }
+ }
+
+ tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
+
+ rate = clk_get_rate(machine->util_data.clk_cdev1);
+
+ /* Use DSP mode for mono on Tegra20 */
+ if (params_channels(params) != 2) {
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ } else {
+ switch (pdata->i2s_param[HIFI_CODEC].i2s_mode) {
+ case TEGRA_DAIFMT_I2S :
+ i2s_daifmt |= SND_SOC_DAIFMT_I2S;
+ break;
+ case TEGRA_DAIFMT_DSP_A :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
+ break;
+ case TEGRA_DAIFMT_DSP_B :
+ i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
+ break;
+ case TEGRA_DAIFMT_LEFT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
+ break;
+ case TEGRA_DAIFMT_RIGHT_J :
+ i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
+ break;
+ default :
+ dev_err(card->dev,
+ "Can't configure i2s format\n");
+ return -EINVAL;
+ }
+ }
+
+ err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
+ if (err < 0) {
+ dev_err(card->dev, "codec_dai fmt not set\n");
+ return err;
+ }
+
+ err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
+ if (err < 0) {
+ dev_err(card->dev, "cpu_dai fmt not set\n");
+ return err;
+ }
+
+ /* Set SGTL5000's SYSCLK (provided by clk_out_1) */
+ err = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, rate, SND_SOC_CLOCK_IN);
+ if (err < 0) {
+ dev_err(card->dev, "codec_dai clock not set\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct colibri_t30_sgtl5000 *machine = snd_soc_card_get_drvdata(card);
+ int srate, mclk, min_mclk;
+ int err;
+
+ srate = params_rate(params);
+ switch (srate) {
+ case 11025:
+ case 22050:
+ case 44100:
+ case 88200:
+ mclk = 11289600;
+ break;
+ case 8000:
+ case 16000:
+ case 32000:
+ case 48000:
+ case 64000:
+ case 96000:
+ mclk = 12288000;
+ break;
+ default:
+ return -EINVAL;
+ }
+ min_mclk = 128 * srate;
+
+ err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
+ if (err < 0) {
+ if (!(machine->util_data.set_mclk % min_mclk))
+ mclk = machine->util_data.set_mclk;
+ else {
+ dev_err(card->dev, "Can't configure clocks\n");
+ return err;
+ }
+ }
+
+ tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
+
+ return 0;
+}
+
+static int tegra_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct colibri_t30_sgtl5000 *machine = snd_soc_card_get_drvdata(rtd->card);
+
+ tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
+
+ return 0;
+}
+
+static struct snd_soc_ops colibri_t30_sgtl5000_ops = {
+ .hw_params = colibri_t30_sgtl5000_hw_params,
+ .hw_free = tegra_hw_free,
+};
+
+static struct snd_soc_ops tegra_spdif_ops = {
+ .hw_params = tegra_spdif_hw_params,
+ .hw_free = tegra_hw_free,
+};
+
+/* Colibri T30 machine DAPM widgets */
+static const struct snd_soc_dapm_widget colibri_t30_sgtl5000_dapm_widgets[] = {
+ SND_SOC_DAPM_HP("HEADPHONE", NULL),
+ SND_SOC_DAPM_LINE("LINEIN", NULL),
+ SND_SOC_DAPM_MIC("MIC_IN", NULL),
+};
+
+/* Colibri T30 machine audio map (connections to the codec pins) */
+static const struct snd_soc_dapm_route colibri_t30_sgtl5000_dapm_route[] = {
+ /* Colibri SODIMM pin 1 (MIC_IN)
+ Colibri Evaluation Board: Audio jack X26 bottom pink
+ Iris: Audio header X9 pin 2
+ Orchid: Audio jack X11 bottom pink MIC in */
+//mic bias GPIO handling
+// [ 9.359733] tegra-snd-colibri_t30-sgtl5000 tegra-snd-colibri_t30-sgtl5000.0: Failed to add route MICIN->MIC_IN
+// { "MIC_IN", NULL, "MIC_IN" },
+
+ /* Colibri SODIMM pin 5 & 7 (LINEIN_L/R)
+ Colibri Evaluation Board: Audio jack X26 top blue
+ Iris: Audio header X9 pin 4 & 3
+ MECS Tellurium: Audio jack X11 pin 1 & 2
+ Orchid: Audio jack X11 top blue line in */
+ { "LINEIN", NULL, "LINE_IN" },
+
+ /* Colibri SODIMM pin 15 & 17 (HEADPHONE_L/R)
+ Colibri Evaluation Board: Audio jack X26 middle green
+ Iris: Audio jack X8
+ MECS Tellurium: Audio jack X11 pin 4 & 5 (HEADPHONE_LF/RF)
+ Orchid: Audio jack X11 middle green line out
+ Protea: Audio jack X53 line out */
+//HP PGA handling
+ { "HEADPHONE", NULL, "HP_OUT" },
+};
+
+static int colibri_t30_sgtl5000_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+ struct snd_soc_card *card = codec->card;
+ struct colibri_t30_sgtl5000 *machine = snd_soc_card_get_drvdata(card);
+ int ret;
+
+ machine->bias_level = SND_SOC_BIAS_STANDBY;
+
+ ret = tegra_asoc_utils_register_ctls(&machine->util_data);
+ if (ret < 0)
+ return ret;
+
+ snd_soc_dapm_nc_pin(dapm, "LINE_OUT");
+
+ snd_soc_dapm_sync(dapm);
+
+ return 0;
+}
+
+static struct snd_soc_dai_link colibri_t30_sgtl5000_dai[] = {
+ {
+ .name = "SGTL5000",
+ .stream_name = "SGTL5000 PCM",
+ .codec_name = "sgtl5000.4-000a",
+ .platform_name = "tegra-pcm-audio",
+ .cpu_dai_name = "tegra30-i2s.2",
+ .codec_dai_name = "sgtl5000",
+ .init = colibri_t30_sgtl5000_init,
+ .ops = &colibri_t30_sgtl5000_ops,
+ },
+ {
+ .name = "SPDIF",
+ .stream_name = "SPDIF PCM",
+ .codec_name = "spdif-dit.0",
+ .platform_name = "tegra-pcm-audio",
+ .cpu_dai_name = "tegra30-spdif",
+ .codec_dai_name = "dit-hifi",
+ .ops = &tegra_spdif_ops,
+ },
+};
+
+static struct snd_soc_card snd_soc_colibri_t30_sgtl5000 = {
+ .name = "colibri_t30-sgtl5000",
+ .dai_link = colibri_t30_sgtl5000_dai,
+ .num_links = ARRAY_SIZE(colibri_t30_sgtl5000_dai),
+// .set_bias_level
+// .set_bias_level_post
+};
+
+static __devinit int colibri_t30_sgtl5000_driver_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &snd_soc_colibri_t30_sgtl5000;
+ struct colibri_t30_sgtl5000 *machine;
+ struct tegra_asoc_platform_data *pdata;
+ int ret;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ dev_err(&pdev->dev, "No platform data supplied\n");
+ return -EINVAL;
+ }
+
+ machine = kzalloc(sizeof(struct colibri_t30_sgtl5000), GFP_KERNEL);
+ if (!machine) {
+ dev_err(&pdev->dev, "Can't allocate colibri_t30_sgtl5000 struct\n");
+ return -ENOMEM;
+ }
+
+ machine->pdata = pdata;
+
+ ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev, card);
+ if (ret)
+ goto err_free_machine;
+
+ card->dev = &pdev->dev;
+ platform_set_drvdata(pdev, card);
+ snd_soc_card_set_drvdata(card, machine);
+
+ card->dapm_widgets = colibri_t30_sgtl5000_dapm_widgets;
+ card->num_dapm_widgets = ARRAY_SIZE(colibri_t30_sgtl5000_dapm_widgets);
+
+ card->dapm_routes = colibri_t30_sgtl5000_dapm_route;
+ card->num_dapm_routes = ARRAY_SIZE(colibri_t30_sgtl5000_dapm_route);
+
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+ ret);
+ goto err_fini_utils;
+ }
+
+ if (!card->instantiated) {
+ ret = -ENODEV;
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+ ret);
+ goto err_unregister_card;
+ }
+
+ ret = tegra_asoc_utils_set_parent(&machine->util_data,
+ pdata->i2s_param[HIFI_CODEC].is_i2s_master);
+ if (ret) {
+ dev_err(&pdev->dev, "tegra_asoc_utils_set_parent failed (%d)\n",
+ ret);
+ goto err_unregister_card;
+ }
+
+ return 0;
+
+err_unregister_card:
+ snd_soc_unregister_card(card);
+err_fini_utils:
+ tegra_asoc_utils_fini(&machine->util_data);
+err_free_machine:
+ kfree(machine);
+ return ret;
+}
+
+static int __devexit colibri_t30_sgtl5000_driver_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct colibri_t30_sgtl5000 *machine = snd_soc_card_get_drvdata(card);
+
+ snd_soc_unregister_card(card);
+
+ tegra_asoc_utils_fini(&machine->util_data);
+
+ kfree(machine);
+
+ return 0;
+}
+
+static struct platform_driver colibri_t30_sgtl5000_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ },
+ .probe = colibri_t30_sgtl5000_driver_probe,
+ .remove = __devexit_p(colibri_t30_sgtl5000_driver_remove),
+};
+
+static int __init colibri_t30_sgtl5000_modinit(void)
+{
+ return platform_driver_register(&colibri_t30_sgtl5000_driver);
+}
+module_init(colibri_t30_sgtl5000_modinit);
+
+static void __exit colibri_t30_sgtl5000_modexit(void)
+{
+ platform_driver_unregister(&colibri_t30_sgtl5000_driver);
+}
+module_exit(colibri_t30_sgtl5000_modexit);
+
+/* Module information */
+MODULE_AUTHOR("Marcel Ziswiler <marcel.ziswiler@toradex.com>");
+MODULE_DESCRIPTION("ALSA SoC SGTL5000 on Toradex Colibri T30");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c
new file mode 100644
index 000000000000..9b7ddb667860
--- /dev/null
+++ b/sound/soc/tegra/tegra20_ac97.c
@@ -0,0 +1,651 @@
+/*
+ * sound/soc/tegra/tegra20_ac97.c
+ *
+ * Copyright (C) 2012 Toradex, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <mach/ac97.h>
+#include <mach/audio.h>
+#include <mach/dma.h>
+#include <mach/gpio.h>
+#include <mach/iomap.h>
+
+#include <sound/ac97_codec.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm_params.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#include "../../../arch/arm/mach-tegra/gpio-names.h"
+#include "tegra_pcm.h"
+#include "tegra20_ac97.h"
+#include "tegra20_das.h"
+
+#define DRV_NAME "tegra20-ac97"
+
+//required?
+static DEFINE_MUTEX(car_mutex);
+
+#define check_ifc(n, ...) if ((n) > TEGRA_DAI_AC97_MODEM) { \
+ pr_err("%s: invalid AC97 interface %d\n", __func__, (n)); \
+ return __VA_ARGS__; \
+}
+
+/* required due to AC97 codec drivers not adhering to proper platform driver
+ model */
+static struct tegra20_ac97 *ac97;
+
+static int tegra20_ac97_set_fmt(struct snd_soc_dai *dai,
+ unsigned int fmt)
+{
+pr_info("%s %u fmt=%d", __func__, __LINE__, fmt);
+ return 0;
+}
+
+phys_addr_t ac97_get_fifo_phy_base(struct tegra20_ac97 *ac97, int ifc, int fifo)
+{
+ check_ifc(ifc, 0);
+
+ if (ifc == TEGRA_DAI_AC97_PCM)
+ return (phys_addr_t)ac97->phys + (fifo ? AC_AC_FIFO_IN1_0 : AC_AC_FIFO_OUT1_0);
+ else
+ return (phys_addr_t)ac97->phys + (fifo ? AC_AC_FIFO_IN2_0 : AC_AC_FIFO_OUT2_0);
+}
+
+static int tegra20_ac97_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct tegra20_ac97 *ac97 = snd_soc_dai_get_drvdata(dai);
+
+ pr_info("%s(): dai->id=%d, %s\n", __func__, dai->id, (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)?"play":"rec");
+
+//TODO: adaptable sample size
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ ac97->playback_dma_data.addr =
+ ac97_get_fifo_phy_base(ac97, dai->id, AC97_FIFO_TX);
+ ac97->playback_dma_data.wrap = 4;
+ ac97->playback_dma_data.width = 32;
+ } else {
+ ac97->capture_dma_data.addr =
+ ac97_get_fifo_phy_base(ac97, dai->id, AC97_FIFO_RX);
+ ac97->capture_dma_data.wrap = 4;
+ ac97->capture_dma_data.width = 32;
+ }
+
+ return 0;
+}
+
+int ac97_fifo_set_attention_level(struct tegra20_ac97 *ac97, int ifc, int fifo, unsigned level)
+{
+ u32 val;
+
+ pr_info("%s()\n", __func__);
+
+ check_ifc(ifc, -EINVAL);
+
+ if (ifc == TEGRA_DAI_AC97_PCM)
+ val = readl(ac97->regs + AC_AC_FIFO1_SCR_0);
+ else
+ val = readl(ac97->regs + AC_AC_FIFO2_SCR_0);
+
+ if (fifo) {
+ val &= ~(AC_AC_FIFOx_SCR_REC_FIFOx_FULL_EN |
+ AC_AC_FIFOx_SCR_REC_FIFOx_3QRT_FULL_EN |
+ AC_AC_FIFOx_SCR_REC_FIFOx_QRT_FULL_EN |
+ AC_AC_FIFOx_SCR_REC_FIFOx_NOT_MT_EN);
+ switch (level) {
+ case AC97_FIFO_ATN_LVL_NONE:
+ break;
+ case AC97_FIFO_ATN_LVL_FULL:
+ val |= AC_AC_FIFOx_SCR_REC_FIFOx_FULL_EN;
+ break;
+ case AC97_FIFO_ATN_LVL_3QUART:
+ val |= AC_AC_FIFOx_SCR_REC_FIFOx_3QRT_FULL_EN;
+ break;
+ case AC97_FIFO_ATN_LVL_QUART:
+ val |= AC_AC_FIFOx_SCR_REC_FIFOx_QRT_FULL_EN;
+ break;
+ case AC97_FIFO_ATN_LVL_EMPTY:
+ val |= AC_AC_FIFOx_SCR_REC_FIFOx_NOT_MT_EN;
+ break;
+ default:
+ pr_err("%s: invalid FIFO level selector %d\n", __func__,
+ level);
+ return -EINVAL;
+ }
+ }
+ else {
+ val &= ~(AC_AC_FIFOx_SCR_PB_FIFOx_NOT_FULL_EN |
+ AC_AC_FIFOx_SCR_PB_FIFOx_QRT_MT_EN |
+ AC_AC_FIFOx_SCR_PB_FIFOx_3QRT_MT_EN |
+ AC_AC_FIFOx_SCR_PB_FIFOx_MT_EN);
+ switch (level) {
+ case AC97_FIFO_ATN_LVL_NONE:
+ break;
+ case AC97_FIFO_ATN_LVL_FULL:
+ val |= AC_AC_FIFOx_SCR_PB_FIFOx_NOT_FULL_EN;
+ break;
+ case AC97_FIFO_ATN_LVL_3QUART:
+ val |= AC_AC_FIFOx_SCR_PB_FIFOx_3QRT_MT_EN;
+ break;
+ case AC97_FIFO_ATN_LVL_QUART:
+ val |= AC_AC_FIFOx_SCR_PB_FIFOx_QRT_MT_EN;
+ break;
+ case AC97_FIFO_ATN_LVL_EMPTY:
+ val |= AC_AC_FIFOx_SCR_PB_FIFOx_MT_EN;
+ break;
+ default:
+ pr_err("%s: invalid FIFO level selector %d\n", __func__,
+ level);
+ return -EINVAL;
+ }
+ }
+
+ if (ifc == TEGRA_DAI_AC97_PCM)
+ writel(val, ac97->regs + AC_AC_FIFO1_SCR_0);
+ else
+ writel(val, ac97->regs + AC_AC_FIFO2_SCR_0);
+
+ return 0;
+}
+
+void ac97_slot_enable(struct tegra20_ac97 *ac97, int ifc, int fifo, int on)
+{
+ pr_info("%s()\n", __func__);
+
+ check_ifc(ifc);
+
+ if (!fifo) {
+ u32 val;
+
+ val = readl(ac97->regs + AC_AC_CTRL_0);
+
+ if (ifc == TEGRA_DAI_AC97_PCM)
+ if (on) {
+#ifndef TEGRA_AC97_32BIT_PLAYBACK
+ /* Enable packed mode for now */
+ val |= AC_AC_CTRL_STM_EN;
+#endif
+ val |= AC_AC_CTRL_PCM_DAC_EN;
+ } else
+ val &= ~AC_AC_CTRL_PCM_DAC_EN;
+ else
+ if (on) {
+#ifndef TEGRA_AC97_32BIT_PLAYBACK
+ /* Enable packed mode for now */
+ val |= AC_AC_CTRL_STM2_EN;
+#endif
+ val |= AC_AC_CTRL_LINE1_DAC_EN;
+ } else
+ val &= ~AC_AC_CTRL_LINE1_DAC_EN;
+
+ writel(val, ac97->regs + AC_AC_CTRL_0);
+ }
+}
+
+/* playback */
+static inline void tegra20_ac97_start_playback(struct snd_soc_dai *cpu_dai)
+{
+ struct tegra20_ac97 *ac97 = snd_soc_dai_get_drvdata(cpu_dai);
+
+ pr_info("%s()\n", __func__);
+
+ ac97_fifo_set_attention_level(ac97, cpu_dai->id, AC97_FIFO_TX,
+ /* Only FIFO level proven stable for video playback */
+#ifdef TEGRA_AC97_32BIT_PLAYBACK
+ AC97_FIFO_ATN_LVL_QUART);
+#else
+ AC97_FIFO_ATN_LVL_EMPTY);
+#endif
+ ac97_slot_enable(ac97, cpu_dai->id, AC97_FIFO_TX, 1);
+}
+
+static inline void tegra20_ac97_stop_playback(struct snd_soc_dai *cpu_dai)
+{
+ struct tegra20_ac97 *ac97 = snd_soc_dai_get_drvdata(cpu_dai);
+ int delay_cnt = 10; /* 1ms max wait for fifo to drain */
+
+ pr_info("%s()\n", __func__);
+
+ ac97_fifo_set_attention_level(ac97, cpu_dai->id, AC97_FIFO_TX,
+ AC97_FIFO_ATN_LVL_NONE);
+
+//something wrong?
+ while (!(readl(ac97->regs + AC_AC_CTRL_0) &
+ AC_AC_FIFOx_SCR_PB_FIFOx_UNDERRUN_INT_STA) &&
+ delay_cnt)
+ {
+ udelay(100);
+ delay_cnt--;
+ }
+
+ ac97_slot_enable(ac97, cpu_dai->id, AC97_FIFO_TX, 0);
+}
+
+/* recording */
+static inline void tegra20_ac97_start_capture(struct snd_soc_dai *cpu_dai)
+{
+ struct tegra20_ac97 *ac97 = snd_soc_dai_get_drvdata(cpu_dai);
+//check slot validity in received tag information
+ ac97_fifo_set_attention_level(ac97, cpu_dai->id, AC97_FIFO_RX,
+ AC97_FIFO_ATN_LVL_FULL);
+}
+
+static inline void tegra20_ac97_stop_capture(struct snd_soc_dai *cpu_dai)
+{
+ struct tegra20_ac97 *ac97 = snd_soc_dai_get_drvdata(cpu_dai);
+ ac97_fifo_set_attention_level(ac97, cpu_dai->id, AC97_FIFO_RX,
+ AC97_FIFO_ATN_LVL_NONE);
+
+//wait?
+}
+
+static int tegra20_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ int ret = 0;
+
+ pr_info("%s()\n", __func__);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ tegra20_ac97_start_playback(dai);
+ else
+ tegra20_ac97_start_capture(dai);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ tegra20_ac97_stop_playback(dai);
+ else
+ tegra20_ac97_stop_capture(dai);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static void tegra20_ac97_reset(struct snd_ac97 *ac97)
+{
+ int gpio_status;
+
+ pr_info("%s()\n", __func__);
+
+ /* do wolfson hard reset */
+#define GPIO_AC97_nRESET TEGRA_GPIO_PV0
+ gpio_status = gpio_request(GPIO_AC97_nRESET, "WOLFSON_RESET");
+ if (gpio_status < 0) {
+ pr_info("WOLFSON_RESET request GPIO FAILED\n");
+ WARN_ON(1);
+ }
+ gpio_status = gpio_direction_output(GPIO_AC97_nRESET, 0);
+ if (gpio_status < 0) {
+ pr_info("WOLFSON_RESET request GPIO DIRECTION FAILED\n");
+ WARN_ON(1);
+ }
+ udelay(2);
+ gpio_set_value(GPIO_AC97_nRESET, 1);
+ udelay(2);
+}
+
+static void tegra20_ac97_warm_reset(struct snd_ac97 *ac97)
+{
+ int gpio_status;
+
+ pr_info("%s()\n", __func__);
+
+ /* do wolfson warm reset by toggling SYNC */
+#define GPIO_AC97_SYNC TEGRA_GPIO_PP0
+ gpio_status = gpio_request(GPIO_AC97_SYNC, "WOLFSON_SYNC");
+ if (gpio_status < 0) {
+ pr_info("WOLFSON_SYNC request GPIO FAILED\n");
+ WARN_ON(1);
+ }
+ gpio_status = gpio_direction_output(GPIO_AC97_SYNC, 1);
+ if (gpio_status < 0) {
+ pr_info("WOLFSON_SYNC request GPIO DIRECTION FAILED\n");
+ WARN_ON(1);
+ }
+ udelay(2);
+ gpio_set_value(GPIO_AC97_SYNC, 0);
+ udelay(2);
+ gpio_free(GPIO_AC97_SYNC);
+}
+
+static unsigned short tegra20_ac97_read(struct snd_ac97 *ac97_snd, unsigned short reg)
+{
+// struct tegra20_ac97 *ac97 = ac97_snd->private_data;
+ u32 val;
+ int timeout = 100;
+
+//pr_info("%s(0x%04x)", __func__, reg);
+
+// mutex_lock(&car_mutex);
+
+ /* Set MSB=1 to indicate Read Command! */
+ writel((((reg | 0x80) << AC_AC_CMD_CMD_ADDR_SHIFT) &
+ AC_AC_CMD_CMD_ADDR_MASK) |
+ /* Set Busy Bit to start Command!! */
+ AC_AC_CMD_BUSY, ac97->regs + AC_AC_CMD_0);
+
+ while (!((val = readl(ac97->regs + AC_AC_STATUS1_0)) &
+ AC_AC_STATUS1_STA_VALID1) && timeout--)
+ mdelay(1);
+
+// mutex_unlock(&car_mutex);
+
+//pr_info(" = 0x%04x\n", (val & AC_AC_STATUS1_STA_DATA1_MASK) >> AC_AC_STATUS1_STA_DATA1_SHIFT);
+
+ return (val & AC_AC_STATUS1_STA_DATA1_MASK) >>
+ AC_AC_STATUS1_STA_DATA1_SHIFT;
+}
+
+static void tegra20_ac97_write(struct snd_ac97 *ac97_snd, unsigned short reg,
+ unsigned short val)
+{
+// struct tegra20_ac97 *ac97 = ac97_snd->private_data;
+ int timeout = 100;
+
+//pr_info("%s(0x%04x, 0x%04x)\n", __func__, reg, val);
+
+// mutex_lock(&car_mutex);
+
+ writel(((reg << AC_AC_CMD_CMD_ADDR_SHIFT) & AC_AC_CMD_CMD_ADDR_MASK) |
+ ((val << AC_AC_CMD_CMD_DATA_SHIFT) &
+ AC_AC_CMD_CMD_DATA_MASK) |
+ /* Set Busy Bit to start Command!! */
+ AC_AC_CMD_BUSY, ac97->regs + AC_AC_CMD_0);
+
+ while (((val = readl(ac97->regs + AC_AC_CMD_0)) &
+ AC_AC_CMD_BUSY) && timeout--)
+ mdelay(1);
+
+// mutex_unlock(&car_mutex);
+}
+
+/* required by sound/soc/codecs/wm9712.c */
+struct snd_ac97_bus_ops soc_ac97_ops = {
+ .read = tegra20_ac97_read,
+ .reset = tegra20_ac97_reset,
+ .warm_reset = tegra20_ac97_warm_reset,
+ .write = tegra20_ac97_write,
+};
+EXPORT_SYMBOL_GPL(soc_ac97_ops);
+
+static struct snd_ac97_bus_ops tegra20_ac97_ops = {
+ .read = tegra20_ac97_read,
+ /* reset already done above */
+ .write = tegra20_ac97_write,
+};
+
+static int tegra20_ac97_probe(struct snd_soc_dai *dai)
+{
+//hw_probe: reset GPIO, clk_get, clk_enable, request_irq
+ struct tegra20_ac97 *ac97 = snd_soc_dai_get_drvdata(dai);
+
+ pr_info("%s()\n", __func__);
+ pr_info("ac97->capture_dma_data=%p\n", &ac97->capture_dma_data);
+ pr_info("ac97->playback_dma_data=%p\n", &ac97->playback_dma_data);
+
+ dai->capture_dma_data = &ac97->capture_dma_data;
+ dai->playback_dma_data = &ac97->playback_dma_data;
+
+ return 0;
+}
+
+//TODO: power management
+
+static struct snd_soc_dai_ops tegra20_ac97_dai_ops = {
+ .hw_params = tegra20_ac97_hw_params,
+//
+ .set_fmt = tegra20_ac97_set_fmt,
+//
+ .trigger = tegra20_ac97_trigger,
+};
+
+struct snd_soc_dai_driver tegra20_ac97_dai[] = {
+ {
+ .name = DRV_NAME "-pcm",
+// .id = 0,
+ .probe = tegra20_ac97_probe,
+//.resume
+ .playback = {
+// .stream_name = "AC97 PCM Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AC97_SAMPLE_RATES,
+#ifndef TEGRA_AC97_32BIT_PLAYBACK
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+#else
+ .formats = SNDRV_PCM_FMTBIT_S32_LE,
+#endif
+ },
+ .capture = {
+// .stream_name = "AC97 PCM Recording",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AC97_SAMPLE_RATES,
+ .formats = SNDRV_PCM_FMTBIT_S32_LE,
+ },
+ .ops = &tegra20_ac97_dai_ops,
+ .symmetric_rates = 1,
+ },
+#if 0
+ {
+ .name = DRV_NAME "-modem",
+// .id = 1,
+ .playback = {
+ .stream_name = "AC97 Modem Playback",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = AC97_SAMPLE_RATES,
+#ifndef TEGRA_AC97_32BIT_PLAYBACK
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+#else
+ .formats = SNDRV_PCM_FMTBIT_S32_LE,
+#endif
+ },
+ .capture = {
+ .stream_name = "AC97 Modem Recording",
+ .channels_min = 1,
+ .channels_max = 1,
+ .rates = AC97_SAMPLE_RATES,
+ .formats = SNDRV_PCM_FMTBIT_S32_LE,
+ },
+ .ops = &tegra20_ac97_dai_ops,
+ .symmetric_rates = 1,
+ },
+#endif
+};
+
+static __devinit int tegra20_ac97_platform_probe(struct platform_device *pdev)
+{
+ struct resource *mem, *memregion, *dmareq;
+ int ret;
+ struct snd_ac97_bus *ac97_bus;
+
+ pr_info("%s()\n", __func__);
+
+ ac97 = kzalloc(sizeof(struct tegra20_ac97), GFP_KERNEL);
+ if (!ac97) {
+ dev_err(&pdev->dev, "Can't allocate tegra20_ac97\n");
+ ret = -ENOMEM;
+ goto exit;
+ }
+ dev_set_drvdata(&pdev->dev, ac97);
+
+ ac97->clk_ac97 = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(ac97->clk_ac97)) {
+ dev_err(&pdev->dev, "Can't retrieve AC97 clock\n");
+ ret = PTR_ERR(ac97->clk_ac97);
+ goto err_free;
+ }
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "No memory resource\n");
+ ret = -ENODEV;
+ goto err_clk_put;
+ }
+ ac97->phys = mem->start;
+
+ dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!dmareq) {
+ dev_err(&pdev->dev, "No DMA resource\n");
+ ret = -ENODEV;
+ goto err_clk_put;
+ }
+
+ memregion = request_mem_region(mem->start, resource_size(mem),
+ DRV_NAME);
+ if (!memregion) {
+ dev_err(&pdev->dev, "Memory region already claimed\n");
+ ret = -EBUSY;
+ goto err_clk_put;
+ }
+
+ ac97->regs = ioremap(mem->start, resource_size(mem));
+ if (!ac97->regs) {
+ dev_err(&pdev->dev, "ioremap failed\n");
+ ret = -ENOMEM;
+ goto err_release;
+ }
+
+ ac97->capture_dma_data.req_sel = dmareq->start;
+ ac97->playback_dma_data.req_sel = dmareq->start;
+
+ ret = snd_soc_register_dais(&pdev->dev, tegra20_ac97_dai, ARRAY_SIZE(tegra20_ac97_dai));
+ if (ret) {
+ dev_err(&pdev->dev, "Could not register DAIs\n");
+ goto err_unmap;
+ }
+
+//required?
+#if 1
+//use 1 in order for actual card to get 0 which is used as default e.g. in Android
+// ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+ ret = snd_card_create(1, SNDRV_DEFAULT_STR1,
+ THIS_MODULE, 0, &ac97->card);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed creating snd_card!\n");
+ goto err_create;
+ }
+
+ ac97->card->dev = &pdev->dev;
+ strncpy(ac97->card->driver, pdev->dev.driver->name, sizeof(ac97->card->driver));
+#endif
+
+pr_info("%s() %u\n", __func__, __LINE__);
+ /* put propper DAC to DAP DAS path in place */
+
+ ret = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAP_SEL_DAC3,
+ TEGRA20_DAS_DAP_ID_3);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to set dap-dac path\n");
+ goto err_create;
+ }
+
+ ret = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_3,
+ TEGRA20_DAS_DAP_SEL_DAC3);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to set dac-dap path\n");
+ goto err_create;
+ }
+
+pr_info("%s() %u\n", __func__, __LINE__);
+ ret = snd_ac97_bus(ac97->card, 0, &tegra20_ac97_ops, NULL, &ac97_bus);
+ if (ret) {
+ dev_err(&pdev->dev, "failed registerign ac97_bus!\n");
+ goto err_create;
+ }
+
+ return 0;
+
+err_create:
+ snd_card_free(ac97->card);
+err_unmap:
+ iounmap(ac97->regs);
+err_release:
+ release_mem_region(mem->start, resource_size(mem));
+err_clk_put:
+ clk_put(ac97->clk_ac97);
+err_free:
+ kfree(ac97);
+exit:
+pr_info("%s() %u\n", __func__, __LINE__);
+ return ret;
+}
+
+static int __devexit tegra20_ac97_platform_remove(struct platform_device *pdev)
+{
+ struct tegra20_ac97 *ac97 = dev_get_drvdata(&pdev->dev);
+ struct resource *res;
+
+ snd_card_free(ac97->card);
+
+ snd_soc_unregister_dai(&pdev->dev);
+
+ iounmap(ac97->regs);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, resource_size(res));
+
+ clk_put(ac97->clk_ac97);
+
+ kfree(ac97);
+
+ return 0;
+}
+
+static struct platform_driver tegra20_ac97_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = tegra20_ac97_platform_probe,
+ .remove = __devexit_p(tegra20_ac97_platform_remove),
+};
+
+static int __init snd_tegra20_ac97_init(void)
+{
+ return platform_driver_register(&tegra20_ac97_driver);
+}
+module_init(snd_tegra20_ac97_init);
+
+static void __exit snd_tegra20_ac97_exit(void)
+{
+ platform_driver_unregister(&tegra20_ac97_driver);
+}
+module_exit(snd_tegra20_ac97_exit);
+
+MODULE_AUTHOR("Marcel Ziswiler <marcel.ziswiler@toradex.com>");
+MODULE_DESCRIPTION("Tegra AC97 ASoC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra20_ac97.h b/sound/soc/tegra/tegra20_ac97.h
new file mode 100644
index 000000000000..430ecc1500f4
--- /dev/null
+++ b/sound/soc/tegra/tegra20_ac97.h
@@ -0,0 +1,43 @@
+/*
+ * linux/sound/soc/tegra/tegra20_ac97.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _TEGRA_AC97_H
+#define _TEGRA_AC97_H
+
+#include "tegra_pcm.h"
+
+/* Tegra DAI ID's */
+#define TEGRA_DAI_AC97_PCM 0 /* slot 3: PCM left channel */
+ /* slot 4: PCM right channel */
+#define TEGRA_DAI_AC97_MODEM 1 /* slot 5: modem line 1 */
+
+ /* slot 11: touch panel digitizer data */
+
+#define AC97_FIFO_ATN_LVL_NONE 0
+#define AC97_FIFO_ATN_LVL_EMPTY 1
+#define AC97_FIFO_ATN_LVL_QUART 2
+#define AC97_FIFO_ATN_LVL_3QUART 3
+#define AC97_FIFO_ATN_LVL_FULL 4
+
+#define AC97_FIFO_TX 0
+#define AC97_FIFO_RX 1
+
+#define AC97_SAMPLE_RATES SNDRV_PCM_RATE_8000_48000
+
+/* AC97 controller */
+struct tegra20_ac97 {
+ struct clk *dap_mclk;
+ struct clk *clk_ac97;
+ struct snd_card *card;
+ struct tegra_pcm_dma_params capture_dma_data;
+ phys_addr_t phys;
+ struct tegra_pcm_dma_params playback_dma_data;
+ void __iomem *regs;
+};
+
+#endif
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index a7c9c0a110f9..8bd0af7df610 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -42,6 +42,12 @@
#define DRV_NAME "tegra-pcm-audio"
+#ifdef CONFIG_SND_SOC_TEGRA20_AC97
+/* AC97 capture conversion buffer pointers and sizes */
+static uint *conv_buf[MAX_DMA_REQ_COUNT];
+static uint conv_size[MAX_DMA_REQ_COUNT];
+#endif /* CONFIG_SND_SOC_TEGRA20_AC97 */
+
static const struct snd_pcm_hardware tegra_pcm_hardware = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -67,22 +73,28 @@ static void tegra_pcm_queue_dma(struct tegra_runtime_data *prtd)
unsigned long addr;
dma_req = &prtd->dma_req[prtd->dma_req_idx];
- if (++prtd->dma_req_idx >= prtd->dma_req_count)
- prtd->dma_req_idx -= prtd->dma_req_count;
if (prtd->avp_dma_addr)
addr = prtd->avp_dma_addr + prtd->dma_pos;
else
addr = buf->addr + prtd->dma_pos;
- prtd->dma_pos += dma_req->size;
- if (prtd->dma_pos >= prtd->dma_pos_end)
- prtd->dma_pos = 0;
-
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
dma_req->source_addr = addr;
- else
+ else {
+#ifdef CONFIG_SND_SOC_TEGRA20_AC97
+ conv_buf[prtd->dma_req_idx] = (uint *)(buf->area + prtd->dma_pos);
+ conv_size[prtd->dma_req_idx] = dma_req->size;
+#endif /* CONFIG_SND_SOC_TEGRA20_AC97 */
dma_req->dest_addr = addr;
+ }
+
+ /* Do index and DMA position update last */
+ if (++prtd->dma_req_idx >= prtd->dma_req_count)
+ prtd->dma_req_idx -= prtd->dma_req_count;
+ prtd->dma_pos += dma_req->size;
+ if (prtd->dma_pos >= prtd->dma_pos_end)
+ prtd->dma_pos = 0;
tegra_dma_enqueue_req(prtd->dma_chan, dma_req);
}
@@ -100,6 +112,17 @@ static void dma_complete_callback(struct tegra_dma_req *req)
return;
}
+#ifdef CONFIG_SND_SOC_TEGRA20_AC97
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ while (conv_size[prtd->dma_req_idx]) {
+ /* Convert 20-bit AC97 sample to 32-bit */
+ *conv_buf[prtd->dma_req_idx] <<= 12;
+ conv_buf[prtd->dma_req_idx]++;
+ conv_size[prtd->dma_req_idx]-=4;
+ }
+ }
+#endif /* CONFIG_SND_SOC_TEGRA20_AC97 */
+
if (++prtd->period_index >= runtime->periods)
prtd->period_index = 0;