From 8775cd3a02a2eb38e20465b0ca5db05de1f75125 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:24:19 +0100 Subject: [PATCH 001/196] Main bcm2708 linux port Signed-off-by: popcornmix --- arch/arm/Kconfig | 16 + arch/arm/Kconfig.debug | 8 + arch/arm/Makefile | 1 + arch/arm/configs/bcmrpi_cutdown_defconfig | 474 +++++++ arch/arm/configs/bcmrpi_defconfig | 510 ++++++++ arch/arm/configs/bcmrpi_emergency_defconfig | 532 ++++++++ arch/arm/kernel/process.c | 2 +- arch/arm/mach-bcm2708/Kconfig | 34 + arch/arm/mach-bcm2708/Makefile | 8 + arch/arm/mach-bcm2708/Makefile.boot | 3 + arch/arm/mach-bcm2708/armctrl.c | 208 ++++ arch/arm/mach-bcm2708/armctrl.h | 27 + arch/arm/mach-bcm2708/bcm2708.c | 695 +++++++++++ arch/arm/mach-bcm2708/bcm2708.h | 51 + arch/arm/mach-bcm2708/bcm2708_gpio.c | 339 +++++ arch/arm/mach-bcm2708/clock.c | 61 + arch/arm/mach-bcm2708/clock.h | 24 + arch/arm/mach-bcm2708/dma.c | 399 ++++++ arch/arm/mach-bcm2708/include/mach/arm_control.h | 419 +++++++ arch/arm/mach-bcm2708/include/mach/arm_power.h | 60 + arch/arm/mach-bcm2708/include/mach/clkdev.h | 7 + arch/arm/mach-bcm2708/include/mach/debug-macro.S | 22 + arch/arm/mach-bcm2708/include/mach/dma.h | 86 ++ arch/arm/mach-bcm2708/include/mach/entry-macro.S | 69 ++ arch/arm/mach-bcm2708/include/mach/frc.h | 38 + arch/arm/mach-bcm2708/include/mach/gpio.h | 18 + arch/arm/mach-bcm2708/include/mach/hardware.h | 28 + arch/arm/mach-bcm2708/include/mach/io.h | 27 + arch/arm/mach-bcm2708/include/mach/irqs.h | 196 +++ arch/arm/mach-bcm2708/include/mach/memory.h | 57 + arch/arm/mach-bcm2708/include/mach/platform.h | 220 ++++ arch/arm/mach-bcm2708/include/mach/power.h | 26 + arch/arm/mach-bcm2708/include/mach/system.h | 38 + arch/arm/mach-bcm2708/include/mach/timex.h | 23 + arch/arm/mach-bcm2708/include/mach/uncompress.h | 85 ++ arch/arm/mach-bcm2708/include/mach/vc_mem.h | 36 + arch/arm/mach-bcm2708/include/mach/vcio.h | 141 +++ arch/arm/mach-bcm2708/include/mach/vmalloc.h | 20 + arch/arm/mach-bcm2708/power.c | 194 +++ arch/arm/mach-bcm2708/vc_mem.c | 462 +++++++ arch/arm/mach-bcm2708/vcio.c | 474 +++++++ arch/arm/mm/Kconfig | 2 +- arch/arm/mm/proc-v6.S | 15 +- arch/arm/tools/mach-types | 1 + drivers/mmc/host/Kconfig | 21 + drivers/mmc/host/Makefile | 1 + drivers/mmc/host/sdhci-bcm2708.c | 1425 ++++++++++++++++++++++ drivers/mmc/host/sdhci.c | 209 +++- drivers/mmc/host/sdhci.h | 37 + include/linux/mmc/sdhci.h | 2 + 50 files changed, 7779 insertions(+), 72 deletions(-) create mode 100644 arch/arm/configs/bcmrpi_cutdown_defconfig create mode 100644 arch/arm/configs/bcmrpi_defconfig create mode 100644 arch/arm/configs/bcmrpi_emergency_defconfig create mode 100644 arch/arm/mach-bcm2708/Kconfig create mode 100644 arch/arm/mach-bcm2708/Makefile create mode 100644 arch/arm/mach-bcm2708/Makefile.boot create mode 100644 arch/arm/mach-bcm2708/armctrl.c create mode 100644 arch/arm/mach-bcm2708/armctrl.h create mode 100644 arch/arm/mach-bcm2708/bcm2708.c create mode 100644 arch/arm/mach-bcm2708/bcm2708.h create mode 100644 arch/arm/mach-bcm2708/bcm2708_gpio.c create mode 100644 arch/arm/mach-bcm2708/clock.c create mode 100644 arch/arm/mach-bcm2708/clock.h create mode 100644 arch/arm/mach-bcm2708/dma.c create mode 100644 arch/arm/mach-bcm2708/include/mach/arm_control.h create mode 100644 arch/arm/mach-bcm2708/include/mach/arm_power.h create mode 100644 arch/arm/mach-bcm2708/include/mach/clkdev.h create mode 100644 arch/arm/mach-bcm2708/include/mach/debug-macro.S create mode 100644 arch/arm/mach-bcm2708/include/mach/dma.h create mode 100644 arch/arm/mach-bcm2708/include/mach/entry-macro.S create mode 100644 arch/arm/mach-bcm2708/include/mach/frc.h create mode 100644 arch/arm/mach-bcm2708/include/mach/gpio.h create mode 100644 arch/arm/mach-bcm2708/include/mach/hardware.h create mode 100644 arch/arm/mach-bcm2708/include/mach/io.h create mode 100644 arch/arm/mach-bcm2708/include/mach/irqs.h create mode 100644 arch/arm/mach-bcm2708/include/mach/memory.h create mode 100644 arch/arm/mach-bcm2708/include/mach/platform.h create mode 100644 arch/arm/mach-bcm2708/include/mach/power.h create mode 100644 arch/arm/mach-bcm2708/include/mach/system.h create mode 100644 arch/arm/mach-bcm2708/include/mach/timex.h create mode 100644 arch/arm/mach-bcm2708/include/mach/uncompress.h create mode 100644 arch/arm/mach-bcm2708/include/mach/vc_mem.h create mode 100644 arch/arm/mach-bcm2708/include/mach/vcio.h create mode 100644 arch/arm/mach-bcm2708/include/mach/vmalloc.h create mode 100644 arch/arm/mach-bcm2708/power.c create mode 100644 arch/arm/mach-bcm2708/vc_mem.c create mode 100644 arch/arm/mach-bcm2708/vcio.c create mode 100644 drivers/mmc/host/sdhci-bcm2708.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 18a9f5e..eb291c7 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -361,6 +361,21 @@ config ARCH_AT91 This enables support for systems based on Atmel AT91RM9200 and AT91SAM9* processors. +config ARCH_BCM2708 + bool "Broadcom BCM2708 family" + select CPU_V6 + select ARM_AMBA + select HAVE_CLK + select HAVE_SCHED_CLOCK + select NEED_MACH_MEMORY_H + select CLKDEV_LOOKUP + select GENERIC_CLOCKEVENTS + select ARM_ERRATA_411920 + select MACH_BCM2708 + select VC4 + help + This enables support for Broadcom BCM2708 boards. + config ARCH_CLPS711X bool "Cirrus Logic CLPS711x/EP721x/EP731x-based" select ARCH_REQUIRE_GPIOLIB @@ -1025,6 +1040,7 @@ source "arch/arm/mach-virt/Kconfig" source "arch/arm/mach-vt8500/Kconfig" source "arch/arm/mach-w90x900/Kconfig" +source "arch/arm/mach-bcm2708/Kconfig" source "arch/arm/mach-zynq/Kconfig" diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 1d41908..52377c9 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -519,6 +519,14 @@ choice For more details about semihosting, please see chapter 8 of DUI0203I_rvct_developer_guide.pdf from ARM Ltd. + config DEBUG_BCM2708_UART0 + bool "Broadcom BCM2708 UART0 (PL011)" + depends on MACH_BCM2708 + help + Say Y here if you want the debug print routines to direct + their output to UART 0. The port must have been initialised + by the boot-loader before use. + endchoice config DEBUG_EXYNOS_UART diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 1ba358b..fb73cf0 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -139,6 +139,7 @@ textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000 # by CONFIG_* macro name. machine-$(CONFIG_ARCH_AT91) += at91 machine-$(CONFIG_ARCH_BCM) += bcm +machine-$(CONFIG_ARCH_BCM2708) += bcm2708 machine-$(CONFIG_ARCH_BCM2835) += bcm2835 machine-$(CONFIG_ARCH_CLPS711X) += clps711x machine-$(CONFIG_ARCH_CNS3XXX) += cns3xxx diff --git a/arch/arm/configs/bcmrpi_cutdown_defconfig b/arch/arm/configs/bcmrpi_cutdown_defconfig new file mode 100644 index 0000000..74f2dc9 --- /dev/null +++ b/arch/arm/configs/bcmrpi_cutdown_defconfig @@ -0,0 +1,474 @@ +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_UID16 is not set +# CONFIG_KALLSYMS is not set +CONFIG_EMBEDDED=y +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_ARCH_BCM2708=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_AEABI=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rootwait" +CONFIG_CPU_IDLE=y +CONFIG_VFP=y +CONFIG_BINFMT_MISC=m +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_RARP=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +CONFIG_NET_PKTGEN=m +CONFIG_IRDA=m +CONFIG_IRLAN=m +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +CONFIG_IRTTY_SIR=m +CONFIG_KINGSUN_DONGLE=m +CONFIG_KSDAZZLE_DONGLE=m +CONFIG_KS959_DONGLE=m +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=y +CONFIG_BT_SCO=y +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +CONFIG_BT_ATH3K=m +CONFIG_CFG80211=m +CONFIG_MAC80211=m +CONFIG_MAC80211_RC_PID=y +CONFIG_MAC80211_MESH=y +CONFIG_WIMAX=m +CONFIG_NET_9P=m +CONFIG_NFC=m +CONFIG_NFC_PN533=m +CONFIG_DEVTMPFS=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_MISC_DEVICES=y +CONFIG_SCSI=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=m +CONFIG_BLK_DEV_SR=m +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_NETDEVICES=y +CONFIG_TUN=m +CONFIG_PHYLIB=m +CONFIG_MDIO_BITBANG=m +CONFIG_NET_ETHERNET=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +CONFIG_LIBERTAS_THINFIRM=m +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_AT76C50X_USB=m +CONFIG_USB_ZD1201=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_RTL8187=m +CONFIG_MAC80211_HWSIM=m +CONFIG_ATH_COMMON=m +CONFIG_ATH9K=m +CONFIG_ATH9K_HTC=m +CONFIG_CARL9170=m +CONFIG_B43=m +CONFIG_B43LEGACY=m +CONFIG_HOSTAP=m +CONFIG_IWM=m +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_SDIO=m +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +CONFIG_RT2X00=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT53XX=y +CONFIG_RTL8192CU=m +CONFIG_WL1251=m +CONFIG_WL12XX_MENU=m +CONFIG_ZD1211RW=m +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_WIMAX_I2400M_USB=m +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=y +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=y +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_KC2190=y +# CONFIG_USB_NET_ZAURUS is not set +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_IPHETH=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m +CONFIG_PPP=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_NETCONSOLE=m +CONFIG_INPUT_POLLDEV=m +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=m +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_AD714X=m +CONFIG_INPUT_ATI_REMOTE=m +CONFIG_INPUT_ATI_REMOTE2=m +CONFIG_INPUT_KEYSPAN_REMOTE=m +CONFIG_INPUT_POWERMATE=m +CONFIG_INPUT_YEALINK=m +CONFIG_INPUT_CM109=m +CONFIG_INPUT_UINPUT=m +CONFIG_INPUT_GPIO_ROTARY_ENCODER=m +CONFIG_INPUT_ADXL34X=m +CONFIG_INPUT_CMA3000=m +CONFIG_SERIO=m +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +# CONFIG_HW_RANDOM is not set +CONFIG_RAW_DRIVER=y +CONFIG_GPIO_SYSFS=y +# CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_BCM2708_WDT=m +# CONFIG_MFD_SUPPORT is not set +CONFIG_FB=y +CONFIG_FB_BCM2708=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y +CONFIG_HID_A4TECH=m +CONFIG_HID_ACRUX=m +CONFIG_HID_APPLE=m +CONFIG_HID_BELKIN=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_DRAGONRISE=m +CONFIG_HID_EMS_FF=m +CONFIG_HID_ELECOM=m +CONFIG_HID_EZKEY=m +CONFIG_HID_HOLTEK=m +CONFIG_HID_KEYTOUCH=m +CONFIG_HID_KYE=m +CONFIG_HID_UCLOGIC=m +CONFIG_HID_WALTOP=m +CONFIG_HID_GYRATION=m +CONFIG_HID_TWINHAN=m +CONFIG_HID_KENSINGTON=m +CONFIG_HID_LCPOWER=m +CONFIG_HID_LOGITECH=m +CONFIG_HID_MAGICMOUSE=m +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_MULTITOUCH=m +CONFIG_HID_NTRIG=m +CONFIG_HID_ORTEK=m +CONFIG_HID_PANTHERLORD=m +CONFIG_HID_PETALYNX=m +CONFIG_HID_PICOLCD=m +CONFIG_HID_QUANTA=m +CONFIG_HID_ROCCAT=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_HID_SPEEDLINK=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_GREENASIA=m +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_HID_TOPSEED=m +CONFIG_HID_THRUSTMASTER=m +CONFIG_HID_WACOM=m +CONFIG_HID_WIIMOTE=m +CONFIG_HID_ZEROPLUS=m +CONFIG_HID_ZYDACRON=m +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_MON=m +CONFIG_USB_DWCOTG=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_REALTEK=m +CONFIG_USB_STORAGE_DATAFAB=m +CONFIG_USB_STORAGE_FREECOM=m +CONFIG_USB_STORAGE_ISD200=m +CONFIG_USB_STORAGE_USBAT=m +CONFIG_USB_STORAGE_SDDR09=m +CONFIG_USB_STORAGE_SDDR55=m +CONFIG_USB_STORAGE_JUMPSHOT=m +CONFIG_USB_STORAGE_ALAUDA=m +CONFIG_USB_STORAGE_ONETOUCH=m +CONFIG_USB_STORAGE_KARMA=m +CONFIG_USB_STORAGE_CYPRESS_ATACB=m +CONFIG_USB_STORAGE_ENE_UB6250=m +CONFIG_USB_UAS=m +CONFIG_USB_LIBUSUAL=y +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MOTOROLA=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SIEMENS_MPI=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m +CONFIG_USB_SERIAL_ZIO=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_DEBUG=m +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_ADUTUX=m +CONFIG_USB_SEVSEG=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +CONFIG_USB_CYPRESS_CY7C63=m +CONFIG_USB_CYTHERM=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_FTDI_ELAN=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_LD=m +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_IOWARRIOR=m +CONFIG_USB_TEST=m +CONFIG_USB_ISIGHTFW=m +CONFIG_USB_YUREX=m +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_BCM2708=y +CONFIG_MMC_SDHCI_BCM2708_DMA=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_HEARTBEAT=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=m +CONFIG_UIO=m +CONFIG_UIO_PDRV=m +CONFIG_UIO_PDRV_GENIRQ=m +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_REISERFS_FS=m +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_RT=y +CONFIG_GFS2_FS=m +CONFIG_OCFS2_FS=m +CONFIG_BTRFS_FS=m +CONFIG_BTRFS_FS_POSIX_ACL=y +CONFIG_NILFS2_FS=m +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=m +CONFIG_CUSE=m +CONFIG_FSCACHE=y +CONFIG_CACHEFILES=y +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +CONFIG_NTFS_FS=m +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_CONFIGFS_FS=y +CONFIG_SQUASHFS=m +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y +CONFIG_NFS_FSCACHE=y +CONFIG_CIFS=m +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_9P_FS=m +CONFIG_PARTITION_ADVANCED=y +CONFIG_MAC_PARTITION=y +CONFIG_EFI_PARTITION=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m +# CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_FTRACE is not set +# CONFIG_ARM_UNWIND is not set +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_SEQIV=m +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_DEFLATE=m +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig new file mode 100644 index 0000000..339aabf --- /dev/null +++ b/arch/arm/configs/bcmrpi_defconfig @@ -0,0 +1,510 @@ +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_FHANDLE=y +CONFIG_AUDIT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_BLK_CGROUP=y +CONFIG_NAMESPACES=y +CONFIG_SCHED_AUTOGROUP=y +CONFIG_EMBEDDED=y +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_BLK_DEV_THROTTLING=y +CONFIG_CFQ_GROUP_IOSCHED=y +CONFIG_ARCH_BCM2708=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_AEABI=y +CONFIG_SECCOMP=y +CONFIG_CC_STACKPROTECTOR=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rootwait" +CONFIG_KEXEC=y +CONFIG_CPU_IDLE=y +CONFIG_VFP=y +CONFIG_BINFMT_MISC=m +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_RARP=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +CONFIG_NET_PKTGEN=m +CONFIG_IRDA=m +CONFIG_IRLAN=m +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +CONFIG_IRTTY_SIR=m +CONFIG_KINGSUN_DONGLE=m +CONFIG_KSDAZZLE_DONGLE=m +CONFIG_KS959_DONGLE=m +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=y +CONFIG_BT_SCO=y +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +CONFIG_BT_ATH3K=m +CONFIG_CFG80211=m +CONFIG_MAC80211=m +CONFIG_MAC80211_RC_PID=y +CONFIG_MAC80211_MESH=y +CONFIG_WIMAX=m +CONFIG_NET_9P=m +CONFIG_NFC=m +CONFIG_NFC_PN533=m +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_MISC_DEVICES=y +CONFIG_SCSI=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=m +CONFIG_BLK_DEV_SR=m +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y +CONFIG_NETDEVICES=y +CONFIG_TUN=m +CONFIG_PHYLIB=m +CONFIG_MDIO_BITBANG=m +CONFIG_NET_ETHERNET=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +CONFIG_LIBERTAS_THINFIRM=m +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_AT76C50X_USB=m +CONFIG_USB_ZD1201=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_RTL8187=m +CONFIG_MAC80211_HWSIM=m +CONFIG_ATH_COMMON=m +CONFIG_ATH9K=m +CONFIG_ATH9K_HTC=m +CONFIG_CARL9170=m +CONFIG_B43=m +CONFIG_B43LEGACY=m +CONFIG_HOSTAP=m +CONFIG_IWM=m +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_SDIO=m +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +CONFIG_RT2X00=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT53XX=y +CONFIG_RTL8192CU=m +CONFIG_WL1251=m +CONFIG_WL12XX_MENU=m +CONFIG_ZD1211RW=m +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_WIMAX_I2400M_USB=m +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=y +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=y +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_KC2190=y +# CONFIG_USB_NET_ZAURUS is not set +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_IPHETH=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m +CONFIG_PPP=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_NETCONSOLE=m +CONFIG_INPUT_POLLDEV=m +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=m +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_AD714X=m +CONFIG_INPUT_ATI_REMOTE=m +CONFIG_INPUT_ATI_REMOTE2=m +CONFIG_INPUT_KEYSPAN_REMOTE=m +CONFIG_INPUT_POWERMATE=m +CONFIG_INPUT_YEALINK=m +CONFIG_INPUT_CM109=m +CONFIG_INPUT_UINPUT=m +CONFIG_INPUT_GPIO_ROTARY_ENCODER=m +CONFIG_INPUT_ADXL34X=m +CONFIG_INPUT_CMA3000=m +CONFIG_SERIO=m +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +# CONFIG_HW_RANDOM is not set +CONFIG_RAW_DRIVER=y +CONFIG_GPIO_SYSFS=y +# CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_BCM2708_WDT=m +# CONFIG_MFD_SUPPORT is not set +CONFIG_FB=y +CONFIG_FB_BCM2708=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y +CONFIG_HID_A4TECH=m +CONFIG_HID_ACRUX=m +CONFIG_HID_APPLE=m +CONFIG_HID_BELKIN=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_DRAGONRISE=m +CONFIG_HID_EMS_FF=m +CONFIG_HID_ELECOM=m +CONFIG_HID_EZKEY=m +CONFIG_HID_HOLTEK=m +CONFIG_HID_KEYTOUCH=m +CONFIG_HID_KYE=m +CONFIG_HID_UCLOGIC=m +CONFIG_HID_WALTOP=m +CONFIG_HID_GYRATION=m +CONFIG_HID_TWINHAN=m +CONFIG_HID_KENSINGTON=m +CONFIG_HID_LCPOWER=m +CONFIG_HID_LOGITECH=m +CONFIG_HID_MAGICMOUSE=m +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_MULTITOUCH=m +CONFIG_HID_NTRIG=m +CONFIG_HID_ORTEK=m +CONFIG_HID_PANTHERLORD=m +CONFIG_HID_PETALYNX=m +CONFIG_HID_PICOLCD=m +CONFIG_HID_QUANTA=m +CONFIG_HID_ROCCAT=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_HID_SPEEDLINK=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_GREENASIA=m +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_HID_TOPSEED=m +CONFIG_HID_THRUSTMASTER=m +CONFIG_HID_WACOM=m +CONFIG_HID_WIIMOTE=m +CONFIG_HID_ZEROPLUS=m +CONFIG_HID_ZYDACRON=m +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_MON=m +CONFIG_USB_DWCOTG=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_REALTEK=m +CONFIG_USB_STORAGE_DATAFAB=m +CONFIG_USB_STORAGE_FREECOM=m +CONFIG_USB_STORAGE_ISD200=m +CONFIG_USB_STORAGE_USBAT=m +CONFIG_USB_STORAGE_SDDR09=m +CONFIG_USB_STORAGE_SDDR55=m +CONFIG_USB_STORAGE_JUMPSHOT=m +CONFIG_USB_STORAGE_ALAUDA=m +CONFIG_USB_STORAGE_ONETOUCH=m +CONFIG_USB_STORAGE_KARMA=m +CONFIG_USB_STORAGE_CYPRESS_ATACB=m +CONFIG_USB_STORAGE_ENE_UB6250=m +CONFIG_USB_UAS=m +CONFIG_USB_LIBUSUAL=y +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MOTOROLA=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SIEMENS_MPI=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m +CONFIG_USB_SERIAL_ZIO=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_DEBUG=m +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_ADUTUX=m +CONFIG_USB_SEVSEG=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +CONFIG_USB_CYPRESS_CY7C63=m +CONFIG_USB_CYTHERM=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_FTDI_ELAN=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_LD=m +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_IOWARRIOR=m +CONFIG_USB_TEST=m +CONFIG_USB_ISIGHTFW=m +CONFIG_USB_YUREX=m +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_BCM2708=y +CONFIG_MMC_SDHCI_BCM2708_DMA=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_HEARTBEAT=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=m +CONFIG_UIO=m +CONFIG_UIO_PDRV=m +CONFIG_UIO_PDRV_GENIRQ=m +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_REISERFS_FS=m +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +CONFIG_JFS_STATISTICS=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_RT=y +CONFIG_GFS2_FS=m +CONFIG_OCFS2_FS=m +CONFIG_BTRFS_FS=m +CONFIG_BTRFS_FS_POSIX_ACL=y +CONFIG_NILFS2_FS=m +CONFIG_FANOTIFY=y +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=m +CONFIG_CUSE=m +CONFIG_FSCACHE=y +CONFIG_FSCACHE_STATS=y +CONFIG_FSCACHE_HISTOGRAM=y +CONFIG_CACHEFILES=y +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +CONFIG_NTFS_FS=m +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_CONFIGFS_FS=y +CONFIG_SQUASHFS=m +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y +CONFIG_NFS_FSCACHE=y +CONFIG_CIFS=m +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_9P_FS=m +CONFIG_9P_FS_POSIX_ACL=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_MAC_PARTITION=y +CONFIG_EFI_PARTITION=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m +CONFIG_PRINTK_TIME=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_TIMER_STATS=y +CONFIG_DEBUG_STACK_USAGE=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_BOOT_PRINTK_DELAY=y +CONFIG_LATENCYTOP=y +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_IRQSOFF_TRACER=y +CONFIG_SCHED_TRACER=y +CONFIG_STACK_TRACER=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_FUNCTION_PROFILER=y +CONFIG_KGDB=y +CONFIG_KGDB_KDB=y +CONFIG_KDB_KEYBOARD=y +CONFIG_STRICT_DEVMEM=y +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_SEQIV=m +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_DEFLATE=m +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y diff --git a/arch/arm/configs/bcmrpi_emergency_defconfig b/arch/arm/configs/bcmrpi_emergency_defconfig new file mode 100644 index 0000000..3b40c49 --- /dev/null +++ b/arch/arm/configs/bcmrpi_emergency_defconfig @@ -0,0 +1,532 @@ +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_FHANDLE=y +CONFIG_AUDIT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="../target_fs" +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_BLK_CGROUP=y +CONFIG_NAMESPACES=y +CONFIG_SCHED_AUTOGROUP=y +CONFIG_EMBEDDED=y +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_BLK_DEV_THROTTLING=y +CONFIG_CFQ_GROUP_IOSCHED=y +CONFIG_ARCH_BCM2708=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_AEABI=y +CONFIG_SECCOMP=y +CONFIG_CC_STACKPROTECTOR=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rootwait" +CONFIG_KEXEC=y +CONFIG_CPU_IDLE=y +CONFIG_VFP=y +CONFIG_BINFMT_MISC=m +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_RARP=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +CONFIG_NET_PKTGEN=m +CONFIG_IRDA=m +CONFIG_IRLAN=m +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +CONFIG_IRTTY_SIR=m +CONFIG_KINGSUN_DONGLE=m +CONFIG_KSDAZZLE_DONGLE=m +CONFIG_KS959_DONGLE=m +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=y +CONFIG_BT_SCO=y +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +CONFIG_BT_ATH3K=m +CONFIG_CFG80211=m +CONFIG_MAC80211=m +CONFIG_MAC80211_RC_PID=y +CONFIG_MAC80211_MESH=y +CONFIG_WIMAX=m +CONFIG_NET_9P=m +CONFIG_NFC=m +CONFIG_NFC_PN533=m +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_MISC_DEVICES=y +CONFIG_SCSI=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_DEV_SR=m +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y +CONFIG_NETDEVICES=y +CONFIG_TUN=m +CONFIG_PHYLIB=m +CONFIG_MDIO_BITBANG=m +CONFIG_NET_ETHERNET=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +CONFIG_LIBERTAS_THINFIRM=m +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_AT76C50X_USB=m +CONFIG_USB_ZD1201=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_RTL8187=m +CONFIG_MAC80211_HWSIM=m +CONFIG_ATH_COMMON=m +CONFIG_ATH9K=m +CONFIG_ATH9K_HTC=m +CONFIG_CARL9170=m +CONFIG_B43=m +CONFIG_B43LEGACY=m +CONFIG_HOSTAP=m +CONFIG_IWM=m +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_SDIO=m +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +CONFIG_RT2X00=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT53XX=y +CONFIG_RTL8192CU=m +CONFIG_WL1251=m +CONFIG_WL12XX_MENU=m +CONFIG_ZD1211RW=m +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_WIMAX_I2400M_USB=m +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=y +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=y +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_KC2190=y +# CONFIG_USB_NET_ZAURUS is not set +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_IPHETH=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m +CONFIG_PPP=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_NETCONSOLE=m +CONFIG_INPUT_POLLDEV=m +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=m +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_AD714X=m +CONFIG_INPUT_ATI_REMOTE=m +CONFIG_INPUT_ATI_REMOTE2=m +CONFIG_INPUT_KEYSPAN_REMOTE=m +CONFIG_INPUT_POWERMATE=m +CONFIG_INPUT_YEALINK=m +CONFIG_INPUT_CM109=m +CONFIG_INPUT_UINPUT=m +CONFIG_INPUT_GPIO_ROTARY_ENCODER=m +CONFIG_INPUT_ADXL34X=m +CONFIG_INPUT_CMA3000=m +CONFIG_SERIO=m +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +# CONFIG_HW_RANDOM is not set +CONFIG_RAW_DRIVER=y +CONFIG_GPIO_SYSFS=y +# CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_BCM2708_WDT=m +# CONFIG_MFD_SUPPORT is not set +CONFIG_FB=y +CONFIG_FB_BCM2708=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_SOUND=y +CONFIG_SND=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=m +CONFIG_SND_DUMMY=m +CONFIG_SND_ALOOP=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_MPU401=m +CONFIG_SND_BCM2835=m +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_UA101=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_6FIRE=m +CONFIG_SOUND_PRIME=m +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y +CONFIG_HID_A4TECH=m +CONFIG_HID_ACRUX=m +CONFIG_HID_APPLE=m +CONFIG_HID_BELKIN=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_DRAGONRISE=m +CONFIG_HID_EMS_FF=m +CONFIG_HID_ELECOM=m +CONFIG_HID_EZKEY=m +CONFIG_HID_HOLTEK=m +CONFIG_HID_KEYTOUCH=m +CONFIG_HID_KYE=m +CONFIG_HID_UCLOGIC=m +CONFIG_HID_WALTOP=m +CONFIG_HID_GYRATION=m +CONFIG_HID_TWINHAN=m +CONFIG_HID_KENSINGTON=m +CONFIG_HID_LCPOWER=m +CONFIG_HID_LOGITECH=m +CONFIG_HID_MAGICMOUSE=m +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_MULTITOUCH=m +CONFIG_HID_NTRIG=m +CONFIG_HID_ORTEK=m +CONFIG_HID_PANTHERLORD=m +CONFIG_HID_PETALYNX=m +CONFIG_HID_PICOLCD=m +CONFIG_HID_QUANTA=m +CONFIG_HID_ROCCAT=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_HID_SPEEDLINK=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_GREENASIA=m +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_HID_TOPSEED=m +CONFIG_HID_THRUSTMASTER=m +CONFIG_HID_WACOM=m +CONFIG_HID_WIIMOTE=m +CONFIG_HID_ZEROPLUS=m +CONFIG_HID_ZYDACRON=m +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_MON=m +CONFIG_USB_DWCOTG=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_REALTEK=m +CONFIG_USB_STORAGE_DATAFAB=m +CONFIG_USB_STORAGE_FREECOM=m +CONFIG_USB_STORAGE_ISD200=m +CONFIG_USB_STORAGE_USBAT=m +CONFIG_USB_STORAGE_SDDR09=m +CONFIG_USB_STORAGE_SDDR55=m +CONFIG_USB_STORAGE_JUMPSHOT=m +CONFIG_USB_STORAGE_ALAUDA=m +CONFIG_USB_STORAGE_ONETOUCH=m +CONFIG_USB_STORAGE_KARMA=m +CONFIG_USB_STORAGE_CYPRESS_ATACB=m +CONFIG_USB_STORAGE_ENE_UB6250=m +CONFIG_USB_UAS=y +CONFIG_USB_LIBUSUAL=y +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MOTOROLA=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SIEMENS_MPI=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m +CONFIG_USB_SERIAL_ZIO=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_DEBUG=m +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_ADUTUX=m +CONFIG_USB_SEVSEG=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +CONFIG_USB_CYPRESS_CY7C63=m +CONFIG_USB_CYTHERM=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_FTDI_ELAN=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_LD=m +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_IOWARRIOR=m +CONFIG_USB_TEST=m +CONFIG_USB_ISIGHTFW=m +CONFIG_USB_YUREX=m +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_BCM2708=y +CONFIG_MMC_SDHCI_BCM2708_DMA=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_HEARTBEAT=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=m +CONFIG_UIO=m +CONFIG_UIO_PDRV=m +CONFIG_UIO_PDRV_GENIRQ=m +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_REISERFS_FS=m +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +CONFIG_JFS_STATISTICS=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_RT=y +CONFIG_GFS2_FS=m +CONFIG_OCFS2_FS=m +CONFIG_BTRFS_FS=m +CONFIG_BTRFS_FS_POSIX_ACL=y +CONFIG_NILFS2_FS=m +CONFIG_FANOTIFY=y +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=m +CONFIG_CUSE=m +CONFIG_FSCACHE=y +CONFIG_FSCACHE_STATS=y +CONFIG_FSCACHE_HISTOGRAM=y +CONFIG_CACHEFILES=y +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +CONFIG_NTFS_FS=m +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_CONFIGFS_FS=y +CONFIG_SQUASHFS=m +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y +CONFIG_NFS_FSCACHE=y +CONFIG_CIFS=m +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_9P_FS=m +CONFIG_9P_FS_POSIX_ACL=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_MAC_PARTITION=y +CONFIG_EFI_PARTITION=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m +CONFIG_PRINTK_TIME=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_TIMER_STATS=y +CONFIG_DEBUG_STACK_USAGE=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_BOOT_PRINTK_DELAY=y +CONFIG_LATENCYTOP=y +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_IRQSOFF_TRACER=y +CONFIG_SCHED_TRACER=y +CONFIG_STACK_TRACER=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_FUNCTION_PROFILER=y +CONFIG_KGDB=y +CONFIG_KGDB_KDB=y +CONFIG_KDB_KEYBOARD=y +CONFIG_STRICT_DEVMEM=y +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_SEQIV=m +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_DEFLATE=m +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index ac4c2e5..d3a6810 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -174,7 +174,7 @@ void arch_cpu_idle(void) default_idle(); } -static char reboot_mode = 'h'; +char reboot_mode = 'h'; int __init reboot_setup(char *str) { diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig new file mode 100644 index 0000000..63bb76c --- /dev/null +++ b/arch/arm/mach-bcm2708/Kconfig @@ -0,0 +1,34 @@ +menu "Broadcom BCM2708 Implementations" + depends on ARCH_BCM2708 + +config MACH_BCM2708 + bool "Broadcom BCM2708 Development Platform" + select NEED_MACH_MEMORY_H + select NEED_MACH_IO_H + select CPU_V6 + help + Include support for the Broadcom(R) BCM2708 platform. + +config BCM2708_GPIO + bool "BCM2708 gpio support" + depends on MACH_BCM2708 + select ARCH_REQUIRE_GPIOLIB + default y + help + Include support for the Broadcom(R) BCM2708 gpio. + +config BCM2708_VCMEM + bool "Videocore Memory" + depends on MACH_BCM2708 + default y + help + Helper for videocore memory access and total size allocation. + +config BCM2708_NOL2CACHE + bool "Videocore L2 cache disable" + depends on MACH_BCM2708 + default n + help + Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt. + +endmenu diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile new file mode 100644 index 0000000..164ecb2 --- /dev/null +++ b/arch/arm/mach-bcm2708/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the linux kernel. +# + +obj-$(CONFIG_MACH_BCM2708) += clock.o bcm2708.o armctrl.o vcio.o power.o dma.o +obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o +obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o + diff --git a/arch/arm/mach-bcm2708/Makefile.boot b/arch/arm/mach-bcm2708/Makefile.boot new file mode 100644 index 0000000..67039c3 --- /dev/null +++ b/arch/arm/mach-bcm2708/Makefile.boot @@ -0,0 +1,3 @@ + zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 +initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c new file mode 100644 index 0000000..da18725 --- /dev/null +++ b/arch/arm/mach-bcm2708/armctrl.c @@ -0,0 +1,208 @@ +/* + * linux/arch/arm/mach-bcm2708/armctrl.c + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include "armctrl.h" + +/* For support of kernels >= 3.0 assume only one VIC for now*/ +static unsigned int remap_irqs[(INTERRUPT_ARASANSDIO + 1) - INTERRUPT_JPEG] = { + INTERRUPT_VC_JPEG, + INTERRUPT_VC_USB, + INTERRUPT_VC_3D, + INTERRUPT_VC_DMA2, + INTERRUPT_VC_DMA3, + INTERRUPT_VC_I2C, + INTERRUPT_VC_SPI, + INTERRUPT_VC_I2SPCM, + INTERRUPT_VC_SDIO, + INTERRUPT_VC_UART, + INTERRUPT_VC_ARASANSDIO +}; + +static void armctrl_mask_irq(struct irq_data *d) +{ + static const unsigned int disables[4] = { + ARM_IRQ_DIBL1, + ARM_IRQ_DIBL2, + ARM_IRQ_DIBL3, + 0 + }; + + unsigned int data = (unsigned int)irq_get_chip_data(d->irq); + writel(1 << (data & 0x1f), __io_address(disables[(data >> 5) & 0x3])); +} + +static void armctrl_unmask_irq(struct irq_data *d) +{ + static const unsigned int enables[4] = { + ARM_IRQ_ENBL1, + ARM_IRQ_ENBL2, + ARM_IRQ_ENBL3, + 0 + }; + + unsigned int data = (unsigned int)irq_get_chip_data(d->irq); + writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3])); +} + +#if defined(CONFIG_PM) + +/* for kernels 3.xx use the new syscore_ops apis but for older kernels use the sys dev class */ + +/* Static defines + * struct armctrl_device - VIC PM device (< 3.xx) + * @sysdev: The system device which is registered. (< 3.xx) + * @irq: The IRQ number for the base of the VIC. + * @base: The register base for the VIC. + * @resume_sources: A bitmask of interrupts for resume. + * @resume_irqs: The IRQs enabled for resume. + * @int_select: Save for VIC_INT_SELECT. + * @int_enable: Save for VIC_INT_ENABLE. + * @soft_int: Save for VIC_INT_SOFT. + * @protect: Save for VIC_PROTECT. + */ +struct armctrl_info { + void __iomem *base; + int irq; + u32 resume_sources; + u32 resume_irqs; + u32 int_select; + u32 int_enable; + u32 soft_int; + u32 protect; +} armctrl; + +static int armctrl_suspend(void) +{ + return 0; +} + +static void armctrl_resume(void) +{ + return; +} + +/** + * armctrl_pm_register - Register a VIC for later power management control + * @base: The base address of the VIC. + * @irq: The base IRQ for the VIC. + * @resume_sources: bitmask of interrupts allowed for resume sources. + * + * For older kernels (< 3.xx) do - + * Register the VIC with the system device tree so that it can be notified + * of suspend and resume requests and ensure that the correct actions are + * taken to re-instate the settings on resume. + */ +static void __init armctrl_pm_register(void __iomem * base, unsigned int irq, + u32 resume_sources) +{ + armctrl.base = base; + armctrl.resume_sources = resume_sources; + armctrl.irq = irq; +} + +static int armctrl_set_wake(struct irq_data *d, unsigned int on) +{ + unsigned int off = d->irq & 31; + u32 bit = 1 << off; + + if (!(bit & armctrl.resume_sources)) + return -EINVAL; + + if (on) + armctrl.resume_irqs |= bit; + else + armctrl.resume_irqs &= ~bit; + + return 0; +} + +#else +static inline void armctrl_pm_register(void __iomem * base, unsigned int irq, + u32 arg1) +{ +} + +#define armctrl_suspend NULL +#define armctrl_resume NULL +#define armctrl_set_wake NULL +#endif /* CONFIG_PM */ + +static struct syscore_ops armctrl_syscore_ops = { + .suspend = armctrl_suspend, + .resume = armctrl_resume, +}; + +/** + * armctrl_syscore_init - initicall to register VIC pm functions + * + * This is called via late_initcall() to register + * the resources for the VICs due to the early + * nature of the VIC's registration. +*/ +static int __init armctrl_syscore_init(void) +{ + register_syscore_ops(&armctrl_syscore_ops); + return 0; +} + +late_initcall(armctrl_syscore_init); + +static struct irq_chip armctrl_chip = { + .name = "ARMCTRL", + .irq_ack = armctrl_mask_irq, + .irq_mask = armctrl_mask_irq, + .irq_unmask = armctrl_unmask_irq, + .irq_set_wake = armctrl_set_wake, +}; + +/** + * armctrl_init - initialise a vectored interrupt controller + * @base: iomem base address + * @irq_start: starting interrupt number, must be muliple of 32 + * @armctrl_sources: bitmask of interrupt sources to allow + * @resume_sources: bitmask of interrupt sources to allow for resume + */ +int __init armctrl_init(void __iomem * base, unsigned int irq_start, + u32 armctrl_sources, u32 resume_sources) +{ + unsigned int irq; + + for (irq = 0; irq < NR_IRQS; irq++) { + unsigned int data = irq; + if (irq >= INTERRUPT_JPEG && irq <= INTERRUPT_ARASANSDIO) + data = remap_irqs[irq - INTERRUPT_JPEG]; + + irq_set_chip(irq, &armctrl_chip); + irq_set_chip_data(irq, (void *)data); + irq_set_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_DISABLED); + } + + armctrl_pm_register(base, irq_start, resume_sources); + return 0; +} diff --git a/arch/arm/mach-bcm2708/armctrl.h b/arch/arm/mach-bcm2708/armctrl.h new file mode 100644 index 0000000..0aa916e --- /dev/null +++ b/arch/arm/mach-bcm2708/armctrl.h @@ -0,0 +1,27 @@ +/* + * linux/arch/arm/mach-bcm2708/armctrl.h + * + * Copyright (C) 2010 Broadcom + * + * 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 __BCM2708_ARMCTRL_H +#define __BCM2708_ARMCTRL_H + +extern int __init armctrl_init(void __iomem * base, unsigned int irq_start, + u32 armctrl_sources, u32 resume_sources); + +#endif diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c new file mode 100644 index 0000000..64a2783 --- /dev/null +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -0,0 +1,695 @@ +/* + * linux/arch/arm/mach-bcm2708/bcm2708.c + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "bcm2708.h" +#include "armctrl.h" +#include "clock.h" + +/* Effectively we have an IOMMU (ARM<->VideoCore map) that is set up to + * give us IO access only to 64Mbytes of physical memory (26 bits). We could + * represent this window by setting our dmamasks to 26 bits but, in fact + * we're not going to use addresses outside this range (they're not in real + * memory) so we don't bother. + * + * In the future we might include code to use this IOMMU to remap other + * physical addresses onto VideoCore memory then the use of 32-bits would be + * more legitimate. + */ +#define DMA_MASK_BITS_COMMON 32 + +/* command line parameters */ +static unsigned boardrev, serial; +static unsigned uart_clock; +static unsigned reboot_part = 0; + +static void __init bcm2708_init_led(void); + +void __init bcm2708_init_irq(void) +{ + armctrl_init(__io_address(ARMCTRL_IC_BASE), 0, 0, 0); +} + +static struct map_desc bcm2708_io_desc[] __initdata = { + { + .virtual = IO_ADDRESS(ARMCTRL_BASE), + .pfn = __phys_to_pfn(ARMCTRL_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(UART0_BASE), + .pfn = __phys_to_pfn(UART0_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(UART1_BASE), + .pfn = __phys_to_pfn(UART1_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(DMA_BASE), + .pfn = __phys_to_pfn(DMA_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(MCORE_BASE), + .pfn = __phys_to_pfn(MCORE_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(ST_BASE), + .pfn = __phys_to_pfn(ST_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(USB_BASE), + .pfn = __phys_to_pfn(USB_BASE), + .length = SZ_128K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(PM_BASE), + .pfn = __phys_to_pfn(PM_BASE), + .length = SZ_4K, + .type = MT_DEVICE}, + { + .virtual = IO_ADDRESS(GPIO_BASE), + .pfn = __phys_to_pfn(GPIO_BASE), + .length = SZ_4K, + .type = MT_DEVICE} +}; + +void __init bcm2708_map_io(void) +{ + iotable_init(bcm2708_io_desc, ARRAY_SIZE(bcm2708_io_desc)); +} + +/* The STC is a free running counter that increments at the rate of 1MHz */ +#define STC_FREQ_HZ 1000000 + +static inline uint32_t timer_read(void) +{ + /* STC: a free running counter that increments at the rate of 1MHz */ + return readl(__io_address(ST_BASE + 0x04)); +} + +static unsigned long bcm2708_read_current_timer(void) +{ + return timer_read(); +} + +static u32 notrace bcm2708_read_sched_clock(void) +{ + return timer_read(); +} + +static cycle_t clksrc_read(struct clocksource *cs) +{ + return timer_read(); +} + +static struct clocksource clocksource_stc = { + .name = "stc", + .rating = 300, + .read = clksrc_read, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +unsigned long frc_clock_ticks32(void) +{ + return timer_read(); +} + +static void __init bcm2708_clocksource_init(void) +{ + if (clocksource_register_hz(&clocksource_stc, STC_FREQ_HZ)) { + printk(KERN_ERR "timer: failed to initialize clock " + "source %s\n", clocksource_stc.name); + } +} + + +/* + * These are fixed clocks. + */ +static struct clk ref24_clk = { + .rate = UART0_CLOCK, /* The UART is clocked at 3MHz via APB_CLK */ +}; + +static struct clk osc_clk = { +#ifdef CONFIG_ARCH_BCM2708_CHIPIT + .rate = 27000000, +#else + .rate = 500000000, /* ARM clock is set from the VideoCore booter */ +#endif +}; + +/* warning - the USB needs a clock > 34MHz */ + +#ifdef CONFIG_MMC_BCM2708 +static struct clk sdhost_clk = { +#ifdef CONFIG_ARCH_BCM2708_CHIPIT + .rate = 4000000, /* 4MHz */ +#else + .rate = 250000000, /* 250MHz */ +#endif +}; +#endif + +static struct clk_lookup lookups[] = { + { /* UART0 */ + .dev_id = "dev:f1", + .clk = &ref24_clk, + }, + { /* USB */ + .dev_id = "bcm2708_usb", + .clk = &osc_clk, + } +}; + +#define UART0_IRQ { IRQ_UART, 0 /*NO_IRQ*/ } +#define UART0_DMA { 15, 14 } + +AMBA_DEVICE(uart0, "dev:f1", UART0, NULL); + +static struct amba_device *amba_devs[] __initdata = { + &uart0_device, +}; + +static struct resource bcm2708_dmaman_resources[] = { + { + .start = DMA_BASE, + .end = DMA_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device bcm2708_dmaman_device = { + .name = BCM_DMAMAN_DRIVER_NAME, + .id = 0, /* first bcm2708_dma */ + .resource = bcm2708_dmaman_resources, + .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources), +}; + +static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_fb_device = { + .name = "bcm2708_fb", + .id = -1, /* only one bcm2708_fb */ + .resource = NULL, + .num_resources = 0, + .dev = { + .dma_mask = &fb_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; + +static struct plat_serial8250_port bcm2708_uart1_platform_data[] = { + { + .mapbase = UART1_BASE + 0x40, + .irq = IRQ_AUX, + .uartclk = 125000000, + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_FIXED_TYPE | UPF_IOREMAP | UPF_SKIP_TEST, + .type = PORT_8250, + }, + {}, +}; + +static struct platform_device bcm2708_uart1_device = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = bcm2708_uart1_platform_data, + }, +}; + +static struct resource bcm2708_usb_resources[] = { + [0] = { + .start = USB_BASE, + .end = USB_BASE + SZ_128K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_USB, + .end = IRQ_USB, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_usb_device = { + .name = "bcm2708_usb", + .id = -1, /* only one bcm2708_usb */ + .resource = bcm2708_usb_resources, + .num_resources = ARRAY_SIZE(bcm2708_usb_resources), + .dev = { + .dma_mask = &usb_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; + +static struct resource bcm2708_vcio_resources[] = { + [0] = { /* mailbox/semaphore/doorbell access */ + .start = MCORE_BASE, + .end = MCORE_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_vcio_device = { + .name = BCM_VCIO_DRIVER_NAME, + .id = -1, /* only one VideoCore I/O area */ + .resource = bcm2708_vcio_resources, + .num_resources = ARRAY_SIZE(bcm2708_vcio_resources), + .dev = { + .dma_mask = &vcio_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; + +#ifdef CONFIG_BCM2708_GPIO +#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" + +static struct resource bcm2708_gpio_resources[] = { + [0] = { /* general purpose I/O */ + .start = GPIO_BASE, + .end = GPIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static u64 gpio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_gpio_device = { + .name = BCM_GPIO_DRIVER_NAME, + .id = -1, /* only one VideoCore I/O area */ + .resource = bcm2708_gpio_resources, + .num_resources = ARRAY_SIZE(bcm2708_gpio_resources), + .dev = { + .dma_mask = &gpio_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; +#endif + +static struct resource bcm2708_systemtimer_resources[] = { + [0] = { /* system timer access */ + .start = ST_BASE, + .end = ST_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_TIMER3, + .end = IRQ_TIMER3, + .flags = IORESOURCE_IRQ, + } + +}; + +static u64 systemtimer_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_systemtimer_device = { + .name = "bcm2708_systemtimer", + .id = -1, /* only one VideoCore I/O area */ + .resource = bcm2708_systemtimer_resources, + .num_resources = ARRAY_SIZE(bcm2708_systemtimer_resources), + .dev = { + .dma_mask = &systemtimer_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), + }, +}; + +#ifdef CONFIG_MMC_SDHCI_BCM2708 /* Arasan emmc SD */ +static struct resource bcm2708_emmc_resources[] = { + [0] = { + .start = EMMC_BASE, + .end = EMMC_BASE + SZ_256 - 1, /* we only need this area */ + /* the memory map actually makes SZ_4K available */ + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_ARASANSDIO, + .end = IRQ_ARASANSDIO, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 bcm2708_emmc_dmamask = 0xffffffffUL; + +struct platform_device bcm2708_emmc_device = { + .name = "bcm2708_sdhci", + .id = 0, + .num_resources = ARRAY_SIZE(bcm2708_emmc_resources), + .resource = bcm2708_emmc_resources, + .dev = { + .dma_mask = &bcm2708_emmc_dmamask, + .coherent_dma_mask = 0xffffffffUL}, +}; +#endif /* CONFIG_MMC_SDHCI_BCM2708 */ + +static struct resource bcm2708_powerman_resources[] = { + [0] = { + .start = PM_BASE, + .end = PM_BASE + SZ_256 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static u64 powerman_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +struct platform_device bcm2708_powerman_device = { + .name = "bcm2708_powerman", + .id = 0, + .num_resources = ARRAY_SIZE(bcm2708_powerman_resources), + .resource = bcm2708_powerman_resources, + .dev = { + .dma_mask = &powerman_dmamask, + .coherent_dma_mask = 0xffffffffUL}, +}; + +int __init bcm_register_device(struct platform_device *pdev) +{ + int ret; + + ret = platform_device_register(pdev); + if (ret) + pr_debug("Unable to register platform device '%s': %d\n", + pdev->name, ret); + + return ret; +} + +int calc_rsts(int partition) +{ + return PM_PASSWORD | + ((partition & (1 << 0)) << 0) | + ((partition & (1 << 1)) << 1) | + ((partition & (1 << 2)) << 2) | + ((partition & (1 << 3)) << 3) | + ((partition & (1 << 4)) << 4) | + ((partition & (1 << 5)) << 5); +} + +static void bcm2708_restart(char mode, const char *cmd) +{ + uint32_t pm_rstc, pm_wdog; + uint32_t timeout = 10; + uint32_t pm_rsts = 0; + + if(mode == 'q') + { + // NOOBS < 1.3 booting with reboot=q + pm_rsts = readl(__io_address(PM_RSTS)); + pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRQ_SET; + } + else if(mode == 'p') + { + // NOOBS < 1.3 halting + pm_rsts = readl(__io_address(PM_RSTS)); + pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRH_SET; + } + else + { + pm_rsts = calc_rsts(reboot_part); + } + + writel(pm_rsts, __io_address(PM_RSTS)); + + /* Setup watchdog for reset */ + pm_rstc = readl(__io_address(PM_RSTC)); + + pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); // watchdog timer = timer clock / 16; need password (31:16) + value (11:0) + pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; + + writel(pm_wdog, __io_address(PM_WDOG)); + writel(pm_rstc, __io_address(PM_RSTC)); +} + +/* We can't really power off, but if we do the normal reset scheme, and indicate to bootcode.bin not to reboot, then most of the chip will be powered off */ +static void bcm2708_power_off(void) +{ + extern char reboot_mode; + + if(reboot_mode == 'q') + { + // NOOBS < v1.3 + bcm2708_restart('p', ""); + } + else + { + /* partition 63 is special code for HALT the bootloader knows not to boot*/ + reboot_part = 63; + /* continue with normal reset mechanism */ + bcm2708_restart(0, ""); + } +} + +void __init bcm2708_init(void) +{ + int i; + + printk("bcm2708.uart_clock = %d\n", uart_clock); + pm_power_off = bcm2708_power_off; + + if (uart_clock) + lookups[0].clk->rate = uart_clock; + + for (i = 0; i < ARRAY_SIZE(lookups); i++) + clkdev_add(&lookups[i]); + + bcm_register_device(&bcm2708_dmaman_device); + bcm_register_device(&bcm2708_vcio_device); +#ifdef CONFIG_BCM2708_GPIO + bcm_register_device(&bcm2708_gpio_device); +#endif + bcm_register_device(&bcm2708_systemtimer_device); + bcm_register_device(&bcm2708_fb_device); + bcm_register_device(&bcm2708_usb_device); + bcm_register_device(&bcm2708_uart1_device); + bcm_register_device(&bcm2708_powerman_device); + +#ifdef CONFIG_MMC_SDHCI_BCM2708 + bcm_register_device(&bcm2708_emmc_device); +#endif + bcm2708_init_led(); + + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; + amba_device_register(d, &iomem_resource); + } + system_rev = boardrev; + system_serial_low = serial; +} + +static void timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + switch (mode) { + case CLOCK_EVT_MODE_ONESHOT: /* Leave the timer disabled, .set_next_event will enable it */ + case CLOCK_EVT_MODE_SHUTDOWN: + break; + case CLOCK_EVT_MODE_PERIODIC: + + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_RESUME: + + default: + printk(KERN_ERR "timer_set_mode: unhandled mode:%d\n", + (int)mode); + break; + } + +} + +static int timer_set_next_event(unsigned long cycles, + struct clock_event_device *unused) +{ + unsigned long stc; + + stc = readl(__io_address(ST_BASE + 0x04)); + writel(stc + cycles, __io_address(ST_BASE + 0x18)); /* stc3 */ + return 0; +} + +static struct clock_event_device timer0_clockevent = { + .name = "timer0", + .shift = 32, + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_mode = timer_set_mode, + .set_next_event = timer_set_next_event, +}; + +/* + * IRQ handler for the timer + */ +static irqreturn_t bcm2708_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = &timer0_clockevent; + + writel(1 << 3, __io_address(ST_BASE + 0x00)); /* stcs clear timer int */ + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct irqaction bcm2708_timer_irq = { + .name = "BCM2708 Timer Tick", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcm2708_timer_interrupt, +}; + +/* + * Set up timer interrupt, and return the current time in seconds. + */ + +static struct delay_timer bcm2708_delay_timer = { + .read_current_timer = bcm2708_read_current_timer, + .freq = STC_FREQ_HZ, +}; + +static void __init bcm2708_timer_init(void) +{ + /* init high res timer */ + bcm2708_clocksource_init(); + + /* + * Initialise to a known state (all timers off) + */ + writel(0, __io_address(ARM_T_CONTROL)); + /* + * Make irqs happen for the system timer + */ + setup_irq(IRQ_TIMER3, &bcm2708_timer_irq); + + setup_sched_clock(bcm2708_read_sched_clock, 32, STC_FREQ_HZ); + + timer0_clockevent.mult = + div_sc(STC_FREQ_HZ, NSEC_PER_SEC, timer0_clockevent.shift); + timer0_clockevent.max_delta_ns = + clockevent_delta2ns(0xffffffff, &timer0_clockevent); + timer0_clockevent.min_delta_ns = + clockevent_delta2ns(0xf, &timer0_clockevent); + + timer0_clockevent.cpumask = cpumask_of(0); + clockevents_register_device(&timer0_clockevent); + + register_current_timer_delay(&bcm2708_delay_timer); +} + +#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) +#include + +static struct gpio_led bcm2708_leds[] = { + [0] = { + .gpio = 16, + .name = "led0", + .default_trigger = "mmc0", + .active_low = 1, + }, +}; + +static struct gpio_led_platform_data bcm2708_led_pdata = { + .num_leds = ARRAY_SIZE(bcm2708_leds), + .leds = bcm2708_leds, +}; + +static struct platform_device bcm2708_led_device = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &bcm2708_led_pdata, + }, +}; + +static void __init bcm2708_init_led(void) +{ + platform_device_register(&bcm2708_led_device); +} +#else +static inline void bcm2708_init_led(void) +{ +} +#endif + +void __init bcm2708_init_early(void) +{ + /* + * Some devices allocate their coherent buffers from atomic + * context. Increase size of atomic coherent pool to make sure such + * the allocations won't fail. + */ + init_dma_coherent_pool_size(SZ_4M); +} + +MACHINE_START(BCM2708, "BCM2708") + /* Maintainer: Broadcom Europe Ltd. */ + .map_io = bcm2708_map_io, + .init_irq = bcm2708_init_irq, + .init_time = bcm2708_timer_init, + .init_machine = bcm2708_init, + .init_early = bcm2708_init_early, + .restart = bcm2708_restart, +MACHINE_END + +module_param(boardrev, uint, 0644); +module_param(serial, uint, 0644); +module_param(uart_clock, uint, 0644); +module_param(reboot_part, uint, 0644); diff --git a/arch/arm/mach-bcm2708/bcm2708.h b/arch/arm/mach-bcm2708/bcm2708.h new file mode 100644 index 0000000..dfe8700 --- /dev/null +++ b/arch/arm/mach-bcm2708/bcm2708.h @@ -0,0 +1,51 @@ +/* + * linux/arch/arm/mach-bcm2708/bcm2708.h + * + * BCM2708 machine support header + * + * Copyright (C) 2010 Broadcom + * + * 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 __BCM2708_BCM2708_H +#define __BCM2708_BCM2708_H + +#include + +extern void __init bcm2708_init(void); +extern void __init bcm2708_init_irq(void); +extern void __init bcm2708_map_io(void); +extern struct sys_timer bcm2708_timer; +extern unsigned int mmc_status(struct device *dev); + +#define AMBA_DEVICE(name, busid, base, plat) \ +static struct amba_device name##_device = { \ + .dev = { \ + .coherent_dma_mask = ~0, \ + .init_name = busid, \ + .platform_data = plat, \ + }, \ + .res = { \ + .start = base##_BASE, \ + .end = (base##_BASE) + SZ_4K - 1,\ + .flags = IORESOURCE_MEM, \ + }, \ + .dma_mask = ~0, \ + .irq = base##_IRQ, \ + /* .dma = base##_DMA,*/ \ +} + +#endif diff --git a/arch/arm/mach-bcm2708/bcm2708_gpio.c b/arch/arm/mach-bcm2708/bcm2708_gpio.c new file mode 100644 index 0000000..d0339eb --- /dev/null +++ b/arch/arm/mach-bcm2708/bcm2708_gpio.c @@ -0,0 +1,339 @@ +/* + * linux/arch/arm/mach-bcm2708/bcm2708_gpio.c + * + * Copyright (C) 2010 Broadcom + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" +#define DRIVER_NAME BCM_GPIO_DRIVER_NAME +#define BCM_GPIO_USE_IRQ 1 + +#define GPIOFSEL(x) (0x00+(x)*4) +#define GPIOSET(x) (0x1c+(x)*4) +#define GPIOCLR(x) (0x28+(x)*4) +#define GPIOLEV(x) (0x34+(x)*4) +#define GPIOEDS(x) (0x40+(x)*4) +#define GPIOREN(x) (0x4c+(x)*4) +#define GPIOFEN(x) (0x58+(x)*4) +#define GPIOHEN(x) (0x64+(x)*4) +#define GPIOLEN(x) (0x70+(x)*4) +#define GPIOAREN(x) (0x7c+(x)*4) +#define GPIOAFEN(x) (0x88+(x)*4) +#define GPIOUD(x) (0x94+(x)*4) +#define GPIOUDCLK(x) (0x98+(x)*4) + +enum { GPIO_FSEL_INPUT, GPIO_FSEL_OUTPUT, + GPIO_FSEL_ALT5, GPIO_FSEL_ALT_4, + GPIO_FSEL_ALT0, GPIO_FSEL_ALT1, + GPIO_FSEL_ALT2, GPIO_FSEL_ALT3, +}; + + /* Each of the two spinlocks protects a different set of hardware + * regiters and data structurs. This decouples the code of the IRQ from + * the GPIO code. This also makes the case of a GPIO routine call from + * the IRQ code simpler. + */ +static DEFINE_SPINLOCK(lock); /* GPIO registers */ + +struct bcm2708_gpio { + struct list_head list; + void __iomem *base; + struct gpio_chip gc; + unsigned long rising; + unsigned long falling; +}; + +static int bcm2708_set_function(struct gpio_chip *gc, unsigned offset, + int function) +{ + struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); + unsigned long flags; + unsigned gpiodir; + unsigned gpio_bank = offset / 10; + unsigned gpio_field_offset = (offset - 10 * gpio_bank) * 3; + +//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set_function %p (%d,%d)\n", gc, offset, function); + if (offset >= ARCH_NR_GPIOS) + return -EINVAL; + + spin_lock_irqsave(&lock, flags); + + gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank)); + gpiodir &= ~(7 << gpio_field_offset); + gpiodir |= function << gpio_field_offset; + writel(gpiodir, gpio->base + GPIOFSEL(gpio_bank)); + spin_unlock_irqrestore(&lock, flags); + gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank)); + + return 0; +} + +static int bcm2708_gpio_dir_in(struct gpio_chip *gc, unsigned offset) +{ + return bcm2708_set_function(gc, offset, GPIO_FSEL_INPUT); +} + +static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value); +static int bcm2708_gpio_dir_out(struct gpio_chip *gc, unsigned offset, + int value) +{ + int ret; + ret = bcm2708_set_function(gc, offset, GPIO_FSEL_OUTPUT); + if (ret >= 0) + bcm2708_gpio_set(gc, offset, value); + return ret; +} + +static int bcm2708_gpio_get(struct gpio_chip *gc, unsigned offset) +{ + struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); + unsigned gpio_bank = offset / 32; + unsigned gpio_field_offset = (offset - 32 * gpio_bank); + unsigned lev; + + if (offset >= ARCH_NR_GPIOS) + return 0; + lev = readl(gpio->base + GPIOLEV(gpio_bank)); +//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_get %p (%d)=%d\n", gc, offset, 0x1 & (lev>>gpio_field_offset)); + return 0x1 & (lev >> gpio_field_offset); +} + +static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value) +{ + struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); + unsigned gpio_bank = offset / 32; + unsigned gpio_field_offset = (offset - 32 * gpio_bank); +//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set %p (%d=%d)\n", gc, offset, value); + if (offset >= ARCH_NR_GPIOS) + return; + if (value) + writel(1 << gpio_field_offset, gpio->base + GPIOSET(gpio_bank)); + else + writel(1 << gpio_field_offset, gpio->base + GPIOCLR(gpio_bank)); +} + +/************************************************************************************************************************* + * bcm2708 GPIO IRQ + */ + +#if BCM_GPIO_USE_IRQ + +static int bcm2708_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) +{ + return gpio_to_irq(gpio); +} + +static int bcm2708_gpio_irq_set_type(struct irq_data *d, unsigned type) +{ + unsigned irq = d->irq; + struct bcm2708_gpio *gpio = irq_get_chip_data(irq); + + if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) + return -EINVAL; + + if (type & IRQ_TYPE_EDGE_RISING) { + gpio->rising |= (1 << irq_to_gpio(irq)); + } else { + gpio->rising &= ~(1 << irq_to_gpio(irq)); + } + + if (type & IRQ_TYPE_EDGE_FALLING) { + gpio->falling |= (1 << irq_to_gpio(irq)); + } else { + gpio->falling &= ~(1 << irq_to_gpio(irq)); + } + return 0; +} + +static void bcm2708_gpio_irq_mask(struct irq_data *d) +{ + unsigned irq = d->irq; + struct bcm2708_gpio *gpio = irq_get_chip_data(irq); + unsigned gn = irq_to_gpio(irq); + unsigned gb = gn / 32; + unsigned long rising = readl(gpio->base + GPIOREN(gb)); + unsigned long falling = readl(gpio->base + GPIOFEN(gb)); + + gn = gn % 32; + + writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb)); + writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb)); +} + +static void bcm2708_gpio_irq_unmask(struct irq_data *d) +{ + unsigned irq = d->irq; + struct bcm2708_gpio *gpio = irq_get_chip_data(irq); + unsigned gn = irq_to_gpio(irq); + unsigned gb = gn / 32; + unsigned long rising = readl(gpio->base + GPIOREN(gb)); + unsigned long falling = readl(gpio->base + GPIOFEN(gb)); + + gn = gn % 32; + + writel(1 << gn, gpio->base + GPIOEDS(gb)); + + if (gpio->rising & (1 << gn)) { + writel(rising | (1 << gn), gpio->base + GPIOREN(gb)); + } else { + writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb)); + } + + if (gpio->falling & (1 << gn)) { + writel(falling | (1 << gn), gpio->base + GPIOFEN(gb)); + } else { + writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb)); + } +} + +static struct irq_chip bcm2708_irqchip = { + .name = "GPIO", + .irq_enable = bcm2708_gpio_irq_unmask, + .irq_disable = bcm2708_gpio_irq_mask, + .irq_unmask = bcm2708_gpio_irq_unmask, + .irq_mask = bcm2708_gpio_irq_mask, + .irq_set_type = bcm2708_gpio_irq_set_type, +}; + +static irqreturn_t bcm2708_gpio_interrupt(int irq, void *dev_id) +{ + unsigned long edsr; + unsigned bank; + int i; + unsigned gpio; + for (bank = 0; bank <= 1; bank++) { + edsr = readl(__io_address(GPIO_BASE) + GPIOEDS(bank)); + for_each_set_bit(i, &edsr, 32) { + gpio = i + bank * 32; + generic_handle_irq(gpio_to_irq(gpio)); + } + writel(0xffffffff, __io_address(GPIO_BASE) + GPIOEDS(bank)); + } + return IRQ_HANDLED; +} + +static struct irqaction bcm2708_gpio_irq = { + .name = "BCM2708 GPIO catchall handler", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = bcm2708_gpio_interrupt, +}; + +static void bcm2708_gpio_irq_init(struct bcm2708_gpio *ucb) +{ + unsigned irq; + + ucb->gc.to_irq = bcm2708_gpio_to_irq; + + for (irq = GPIO_IRQ_START; irq < (GPIO_IRQ_START + GPIO_IRQS); irq++) { + irq_set_chip_data(irq, ucb); + irq_set_chip(irq, &bcm2708_irqchip); + set_irq_flags(irq, IRQF_VALID); + } + setup_irq(IRQ_GPIO3, &bcm2708_gpio_irq); +} + +#else + +static void bcm2708_gpio_irq_init(struct bcm2708_gpio *ucb) +{ +} + +#endif /* #if BCM_GPIO_USE_IRQ ***************************************************************************************************************** */ + +static int bcm2708_gpio_probe(struct platform_device *dev) +{ + struct bcm2708_gpio *ucb; + struct resource *res; + int err = 0; + + printk(KERN_INFO DRIVER_NAME ": bcm2708_gpio_probe %p\n", dev); + + ucb = kzalloc(sizeof(*ucb), GFP_KERNEL); + if (NULL == ucb) { + printk(KERN_ERR DRIVER_NAME ": failed to allocate " + "mailbox memory\n"); + err = -ENOMEM; + goto err; + } + + res = platform_get_resource(dev, IORESOURCE_MEM, 0); + + platform_set_drvdata(dev, ucb); + ucb->base = __io_address(GPIO_BASE); + + ucb->gc.label = "bcm2708_gpio"; + ucb->gc.base = 0; + ucb->gc.ngpio = ARCH_NR_GPIOS; + ucb->gc.owner = THIS_MODULE; + + ucb->gc.direction_input = bcm2708_gpio_dir_in; + ucb->gc.direction_output = bcm2708_gpio_dir_out; + ucb->gc.get = bcm2708_gpio_get; + ucb->gc.set = bcm2708_gpio_set; + ucb->gc.can_sleep = 0; + + bcm2708_gpio_irq_init(ucb); + + err = gpiochip_add(&ucb->gc); + if (err) + goto err; + +err: + return err; + +} + +static int bcm2708_gpio_remove(struct platform_device *dev) +{ + int err = 0; + struct bcm2708_gpio *ucb = platform_get_drvdata(dev); + + printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_remove %p\n", dev); + + err = gpiochip_remove(&ucb->gc); + + platform_set_drvdata(dev, NULL); + kfree(ucb); + + return err; +} + +static struct platform_driver bcm2708_gpio_driver = { + .probe = bcm2708_gpio_probe, + .remove = bcm2708_gpio_remove, + .driver = { + .name = "bcm2708_gpio"}, +}; + +static int __init bcm2708_gpio_init(void) +{ + return platform_driver_register(&bcm2708_gpio_driver); +} + +static void __exit bcm2708_gpio_exit(void) +{ + platform_driver_unregister(&bcm2708_gpio_driver); +} + +module_init(bcm2708_gpio_init); +module_exit(bcm2708_gpio_exit); + +MODULE_DESCRIPTION("Broadcom BCM2708 GPIO driver"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-bcm2708/clock.c b/arch/arm/mach-bcm2708/clock.c new file mode 100644 index 0000000..4fc556e --- /dev/null +++ b/arch/arm/mach-bcm2708/clock.c @@ -0,0 +1,61 @@ +/* + * linux/arch/arm/mach-bcm2708/clock.c + * + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clock.h" + +int clk_enable(struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + return clk->rate; +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + return -EIO; +} +EXPORT_SYMBOL(clk_set_rate); diff --git a/arch/arm/mach-bcm2708/clock.h b/arch/arm/mach-bcm2708/clock.h new file mode 100644 index 0000000..5f9d725 --- /dev/null +++ b/arch/arm/mach-bcm2708/clock.h @@ -0,0 +1,24 @@ +/* + * linux/arch/arm/mach-bcm2708/clock.h + * + * Copyright (C) 2010 Broadcom + * + * 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 + */ +struct module; + +struct clk { + unsigned long rate; +}; diff --git a/arch/arm/mach-bcm2708/dma.c b/arch/arm/mach-bcm2708/dma.c new file mode 100644 index 0000000..51d147a --- /dev/null +++ b/arch/arm/mach-bcm2708/dma.c @@ -0,0 +1,399 @@ +/* + * linux/arch/arm/mach-bcm2708/dma.c + * + * Copyright (C) 2010 Broadcom + * + * 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 +#include +#include +#include +#include + +#include +#include + +/*****************************************************************************\ + * * + * Configuration * + * * +\*****************************************************************************/ + +#define CACHE_LINE_MASK 31 +#define DRIVER_NAME BCM_DMAMAN_DRIVER_NAME +#define DEFAULT_DMACHAN_BITMAP 0x10 /* channel 4 only */ + +/* valid only for channels 0 - 14, 15 has its own base address */ +#define BCM2708_DMA_CHAN(n) ((n)<<8) /* base address */ +#define BCM2708_DMA_CHANIO(dma_base, n) \ + ((void __iomem *)((char *)(dma_base)+BCM2708_DMA_CHAN(n))) + + +/*****************************************************************************\ + * * + * DMA Auxilliary Functions * + * * +\*****************************************************************************/ + +/* A DMA buffer on an arbitrary boundary may separate a cache line into a + section inside the DMA buffer and another section outside it. + Even if we flush DMA buffers from the cache there is always the chance that + during a DMA someone will access the part of a cache line that is outside + the DMA buffer - which will then bring in unwelcome data. + Without being able to dictate our own buffer pools we must insist that + DMA buffers consist of a whole number of cache lines. +*/ + +extern int +bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len) +{ + int i; + + for (i = 0; i < sg_len; i++) { + if (sg_ptr[i].offset & CACHE_LINE_MASK || + sg_ptr[i].length & CACHE_LINE_MASK) + return 0; + } + + return 1; +} +EXPORT_SYMBOL_GPL(bcm_sg_suitable_for_dma); + +extern void +bcm_dma_start(void __iomem *dma_chan_base, dma_addr_t control_block) +{ + dsb(); /* ARM data synchronization (push) operation */ + + writel(control_block, dma_chan_base + BCM2708_DMA_ADDR); + writel(BCM2708_DMA_ACTIVE, dma_chan_base + BCM2708_DMA_CS); +} + +extern void bcm_dma_wait_idle(void __iomem *dma_chan_base) +{ + dsb(); + + /* ugly busy wait only option for now */ + while (readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE) + cpu_relax(); +} + +EXPORT_SYMBOL_GPL(bcm_dma_start); + +/* Complete an ongoing DMA (assuming its results are to be ignored) + Does nothing if there is no DMA in progress. + This routine waits for the current AXI transfer to complete before + terminating the current DMA. If the current transfer is hung on a DREQ used + by an uncooperative peripheral the AXI transfer may never complete. In this + case the routine times out and return a non-zero error code. + Use of this routine doesn't guarantee that the ongoing or aborted DMA + does not produce an interrupt. +*/ +extern int +bcm_dma_abort(void __iomem *dma_chan_base) +{ + unsigned long int cs; + int rc = 0; + + cs = readl(dma_chan_base + BCM2708_DMA_CS); + + if (BCM2708_DMA_ACTIVE & cs) { + long int timeout = 10000; + + /* write 0 to the active bit - pause the DMA */ + writel(0, dma_chan_base + BCM2708_DMA_CS); + + /* wait for any current AXI transfer to complete */ + while (0 != (cs & BCM2708_DMA_ISPAUSED) && --timeout >= 0) + cs = readl(dma_chan_base + BCM2708_DMA_CS); + + if (0 != (cs & BCM2708_DMA_ISPAUSED)) { + /* we'll un-pause when we set of our next DMA */ + rc = -ETIMEDOUT; + + } else if (BCM2708_DMA_ACTIVE & cs) { + /* terminate the control block chain */ + writel(0, dma_chan_base + BCM2708_DMA_NEXTCB); + + /* abort the whole DMA */ + writel(BCM2708_DMA_ABORT | BCM2708_DMA_ACTIVE, + dma_chan_base + BCM2708_DMA_CS); + } + } + + return rc; +} +EXPORT_SYMBOL_GPL(bcm_dma_abort); + + +/***************************************************************************** \ + * * + * DMA Manager Device Methods * + * * +\*****************************************************************************/ + +struct vc_dmaman { + void __iomem *dma_base; + u32 chan_available; /* bitmap of available channels */ + u32 has_feature[BCM_DMA_FEATURE_COUNT]; /* bitmap of feature presence */ +}; + +static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base, + u32 chans_available) +{ + dmaman->dma_base = dma_base; + dmaman->chan_available = chans_available; + dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* chans 2 & 3 */ + dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01; /* chan 0 */ +} + +static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman, + unsigned preferred_feature_set) +{ + u32 chans; + int feature; + + chans = dmaman->chan_available; + for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++) + /* select the subset of available channels with the desired + feature so long as some of the candidate channels have that + feature */ + if ((preferred_feature_set & (1 << feature)) && + (chans & dmaman->has_feature[feature])) + chans &= dmaman->has_feature[feature]; + + if (chans) { + int chan = 0; + /* return the ordinal of the first channel in the bitmap */ + while (chans != 0 && (chans & 1) == 0) { + chans >>= 1; + chan++; + } + /* claim the channel */ + dmaman->chan_available &= ~(1 << chan); + return chan; + } else + return -ENOMEM; +} + +static int vc_dmaman_chan_free(struct vc_dmaman *dmaman, int chan) +{ + if (chan < 0) + return -EINVAL; + else if ((1 << chan) & dmaman->chan_available) + return -EIDRM; + else { + dmaman->chan_available |= (1 << chan); + return 0; + } +} + +/*****************************************************************************\ + * * + * DMA IRQs * + * * +\*****************************************************************************/ + +static unsigned char bcm_dma_irqs[] = { + IRQ_DMA0, + IRQ_DMA1, + IRQ_DMA2, + IRQ_DMA3, + IRQ_DMA4, + IRQ_DMA5, + IRQ_DMA6, + IRQ_DMA7, + IRQ_DMA8, + IRQ_DMA9, + IRQ_DMA10, + IRQ_DMA11, + IRQ_DMA12 +}; + + +/***************************************************************************** \ + * * + * DMA Manager Monitor * + * * +\*****************************************************************************/ + +static struct device *dmaman_dev; /* we assume there's only one! */ + +extern int bcm_dma_chan_alloc(unsigned preferred_feature_set, + void __iomem **out_dma_base, int *out_dma_irq) +{ + if (!dmaman_dev) + return -ENODEV; + else { + struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); + int rc; + + device_lock(dmaman_dev); + rc = vc_dmaman_chan_alloc(dmaman, preferred_feature_set); + if (rc >= 0) { + *out_dma_base = BCM2708_DMA_CHANIO(dmaman->dma_base, + rc); + *out_dma_irq = bcm_dma_irqs[rc]; + } + device_unlock(dmaman_dev); + + return rc; + } +} +EXPORT_SYMBOL_GPL(bcm_dma_chan_alloc); + +extern int bcm_dma_chan_free(int channel) +{ + if (dmaman_dev) { + struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev); + int rc; + + device_lock(dmaman_dev); + rc = vc_dmaman_chan_free(dmaman, channel); + device_unlock(dmaman_dev); + + return rc; + } else + return -ENODEV; +} +EXPORT_SYMBOL_GPL(bcm_dma_chan_free); + +static int dev_dmaman_register(const char *dev_name, struct device *dev) +{ + int rc = dmaman_dev ? -EINVAL : 0; + dmaman_dev = dev; + return rc; +} + +static void dev_dmaman_deregister(const char *dev_name, struct device *dev) +{ + dmaman_dev = NULL; +} + +/*****************************************************************************\ + * * + * DMA Device * + * * +\*****************************************************************************/ + +static int dmachans = -1; /* module parameter */ + +static int bcm_dmaman_probe(struct platform_device *pdev) +{ + int ret = 0; + struct vc_dmaman *dmaman; + struct resource *dma_res = NULL; + void __iomem *dma_base = NULL; + int have_dma_region = 0; + + dmaman = kzalloc(sizeof(*dmaman), GFP_KERNEL); + if (NULL == dmaman) { + printk(KERN_ERR DRIVER_NAME ": failed to allocate " + "DMA management memory\n"); + ret = -ENOMEM; + } else { + + dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (dma_res == NULL) { + printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " + "resource\n"); + ret = -ENODEV; + } else if (!request_mem_region(dma_res->start, + resource_size(dma_res), + DRIVER_NAME)) { + dev_err(&pdev->dev, "cannot obtain DMA region\n"); + ret = -EBUSY; + } else { + have_dma_region = 1; + dma_base = ioremap(dma_res->start, + resource_size(dma_res)); + if (!dma_base) { + dev_err(&pdev->dev, "cannot map DMA region\n"); + ret = -ENOMEM; + } else { + /* use module parameter if one was provided */ + if (dmachans > 0) + vc_dmaman_init(dmaman, dma_base, + dmachans); + else + vc_dmaman_init(dmaman, dma_base, + DEFAULT_DMACHAN_BITMAP); + + platform_set_drvdata(pdev, dmaman); + dev_dmaman_register(DRIVER_NAME, &pdev->dev); + + printk(KERN_INFO DRIVER_NAME ": DMA manager " + "at %p\n", dma_base); + } + } + } + if (ret != 0) { + if (dma_base) + iounmap(dma_base); + if (dma_res && have_dma_region) + release_mem_region(dma_res->start, + resource_size(dma_res)); + if (dmaman) + kfree(dmaman); + } + return ret; +} + +static int bcm_dmaman_remove(struct platform_device *pdev) +{ + struct vc_dmaman *dmaman = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + dev_dmaman_deregister(DRIVER_NAME, &pdev->dev); + kfree(dmaman); + + return 0; +} + +static struct platform_driver bcm_dmaman_driver = { + .probe = bcm_dmaman_probe, + .remove = bcm_dmaman_remove, + + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, +}; + +/*****************************************************************************\ + * * + * Driver init/exit * + * * +\*****************************************************************************/ + +static int __init bcm_dmaman_drv_init(void) +{ + int ret; + + ret = platform_driver_register(&bcm_dmaman_driver); + if (ret != 0) { + printk(KERN_ERR DRIVER_NAME ": failed to register " + "on platform\n"); + } + + return ret; +} + +static void __exit bcm_dmaman_drv_exit(void) +{ + platform_driver_unregister(&bcm_dmaman_driver); +} + +module_init(bcm_dmaman_drv_init); +module_exit(bcm_dmaman_drv_exit); + +module_param(dmachans, int, 0644); + +MODULE_AUTHOR("Gray Girling "); +MODULE_DESCRIPTION("DMA channel manager driver"); +MODULE_LICENSE("GPL"); + +MODULE_PARM_DESC(dmachans, "Bitmap of DMA channels available to the ARM"); diff --git a/arch/arm/mach-bcm2708/include/mach/arm_control.h b/arch/arm/mach-bcm2708/include/mach/arm_control.h new file mode 100644 index 0000000..a82bb92 --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/arm_control.h @@ -0,0 +1,419 @@ +/* + * linux/arch/arm/mach-bcm2708/arm_control.h + * + * Copyright (C) 2010 Broadcom + * + * 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 __BCM2708_ARM_CONTROL_H +#define __BCM2708_ARM_CONTROL_H + +/* + * Definitions and addresses for the ARM CONTROL logic + * This file is manually generated. + */ + +#define ARM_BASE 0x7E00B000 + +/* Basic configuration */ +#define ARM_CONTROL0 HW_REGISTER_RW(ARM_BASE+0x000) +#define ARM_C0_SIZ128M 0x00000000 +#define ARM_C0_SIZ256M 0x00000001 +#define ARM_C0_SIZ512M 0x00000002 +#define ARM_C0_SIZ1G 0x00000003 +#define ARM_C0_BRESP0 0x00000000 +#define ARM_C0_BRESP1 0x00000004 +#define ARM_C0_BRESP2 0x00000008 +#define ARM_C0_BOOTHI 0x00000010 +#define ARM_C0_UNUSED05 0x00000020 /* free */ +#define ARM_C0_FULLPERI 0x00000040 +#define ARM_C0_UNUSED78 0x00000180 /* free */ +#define ARM_C0_JTAGMASK 0x00000E00 +#define ARM_C0_JTAGOFF 0x00000000 +#define ARM_C0_JTAGBASH 0x00000800 /* Debug on GPIO off */ +#define ARM_C0_JTAGGPIO 0x00000C00 /* Debug on GPIO on */ +#define ARM_C0_APROTMSK 0x0000F000 +#define ARM_C0_DBG0SYNC 0x00010000 /* VPU0 halt sync */ +#define ARM_C0_DBG1SYNC 0x00020000 /* VPU1 halt sync */ +#define ARM_C0_SWDBGREQ 0x00040000 /* HW debug request */ +#define ARM_C0_PASSHALT 0x00080000 /* ARM halt passed to debugger */ +#define ARM_C0_PRIO_PER 0x00F00000 /* per priority mask */ +#define ARM_C0_PRIO_L2 0x0F000000 +#define ARM_C0_PRIO_UC 0xF0000000 + +#define ARM_C0_APROTPASS 0x0000A000 /* Translate 1:1 */ +#define ARM_C0_APROTUSER 0x00000000 /* Only user mode */ +#define ARM_C0_APROTSYST 0x0000F000 /* Only system mode */ + + +#define ARM_CONTROL1 HW_REGISTER_RW(ARM_BASE+0x440) +#define ARM_C1_TIMER 0x00000001 /* re-route timer IRQ to VC */ +#define ARM_C1_MAIL 0x00000002 /* re-route Mail IRQ to VC */ +#define ARM_C1_BELL0 0x00000004 /* re-route Doorbell 0 to VC */ +#define ARM_C1_BELL1 0x00000008 /* re-route Doorbell 1 to VC */ +#define ARM_C1_PERSON 0x00000100 /* peripherals on */ +#define ARM_C1_REQSTOP 0x00000200 /* ASYNC bridge request stop */ + +#define ARM_STATUS HW_REGISTER_RW(ARM_BASE+0x444) +#define ARM_S_ACKSTOP 0x80000000 /* Bridge stopped */ +#define ARM_S_READPEND 0x000003FF /* pending reads counter */ +#define ARM_S_WRITPEND 0x000FFC00 /* pending writes counter */ + +#define ARM_ERRHALT HW_REGISTER_RW(ARM_BASE+0x448) +#define ARM_EH_PERIBURST 0x00000001 /* Burst write seen on peri bus */ +#define ARM_EH_ILLADDRS1 0x00000002 /* Address bits 25-27 error */ +#define ARM_EH_ILLADDRS2 0x00000004 /* Address bits 31-28 error */ +#define ARM_EH_VPU0HALT 0x00000008 /* VPU0 halted & in debug mode */ +#define ARM_EH_VPU1HALT 0x00000010 /* VPU1 halted & in debug mode */ +#define ARM_EH_ARMHALT 0x00000020 /* ARM in halted debug mode */ + +#define ARM_ID_SECURE HW_REGISTER_RW(ARM_BASE+0x00C) +#define ARM_ID HW_REGISTER_RW(ARM_BASE+0x44C) +#define ARM_IDVAL 0x364D5241 + +/* Translation memory */ +#define ARM_TRANSLATE HW_REGISTER_RW(ARM_BASE+0x100) +/* 32 locations: 0x100.. 0x17F */ +/* 32 spare means we CAN go to 64 pages.... */ + + +/* Interrupts */ +#define ARM_IRQ_PEND0 HW_REGISTER_RW(ARM_BASE+0x200) /* Top IRQ bits */ +#define ARM_I0_TIMER 0x00000001 /* timer IRQ */ +#define ARM_I0_MAIL 0x00000002 /* Mail IRQ */ +#define ARM_I0_BELL0 0x00000004 /* Doorbell 0 */ +#define ARM_I0_BELL1 0x00000008 /* Doorbell 1 */ +#define ARM_I0_BANK1 0x00000100 /* Bank1 IRQ */ +#define ARM_I0_BANK2 0x00000200 /* Bank2 IRQ */ + +#define ARM_IRQ_PEND1 HW_REGISTER_RW(ARM_BASE+0x204) /* All bank1 IRQ bits */ +/* todo: all I1_interrupt sources */ +#define ARM_IRQ_PEND2 HW_REGISTER_RW(ARM_BASE+0x208) /* All bank2 IRQ bits */ +/* todo: all I2_interrupt sources */ + +#define ARM_IRQ_FAST HW_REGISTER_RW(ARM_BASE+0x20C) /* FIQ control */ +#define ARM_IF_INDEX 0x0000007F /* FIQ select */ +#define ARM_IF_ENABLE 0x00000080 /* FIQ enable */ +#define ARM_IF_VCMASK 0x0000003F /* FIQ = (index from VC source) */ +#define ARM_IF_TIMER 0x00000040 /* FIQ = ARM timer */ +#define ARM_IF_MAIL 0x00000041 /* FIQ = ARM Mail */ +#define ARM_IF_BELL0 0x00000042 /* FIQ = ARM Doorbell 0 */ +#define ARM_IF_BELL1 0x00000043 /* FIQ = ARM Doorbell 1 */ +#define ARM_IF_VP0HALT 0x00000044 /* FIQ = VPU0 Halt seen */ +#define ARM_IF_VP1HALT 0x00000045 /* FIQ = VPU1 Halt seen */ +#define ARM_IF_ILLEGAL 0x00000046 /* FIQ = Illegal access seen */ + +#define ARM_IRQ_ENBL1 HW_REGISTER_RW(ARM_BASE+0x210) /* Bank1 enable bits */ +#define ARM_IRQ_ENBL2 HW_REGISTER_RW(ARM_BASE+0x214) /* Bank2 enable bits */ +#define ARM_IRQ_ENBL3 HW_REGISTER_RW(ARM_BASE+0x218) /* ARM irqs enable bits */ +#define ARM_IRQ_DIBL1 HW_REGISTER_RW(ARM_BASE+0x21C) /* Bank1 disable bits */ +#define ARM_IRQ_DIBL2 HW_REGISTER_RW(ARM_BASE+0x220) /* Bank2 disable bits */ +#define ARM_IRQ_DIBL3 HW_REGISTER_RW(ARM_BASE+0x224) /* ARM irqs disable bits */ +#define ARM_IE_TIMER 0x00000001 /* Timer IRQ */ +#define ARM_IE_MAIL 0x00000002 /* Mail IRQ */ +#define ARM_IE_BELL0 0x00000004 /* Doorbell 0 */ +#define ARM_IE_BELL1 0x00000008 /* Doorbell 1 */ +#define ARM_IE_VP0HALT 0x00000010 /* VPU0 Halt */ +#define ARM_IE_VP1HALT 0x00000020 /* VPU1 Halt */ +#define ARM_IE_ILLEGAL 0x00000040 /* Illegal access seen */ + +/* Timer */ +/* For reg. fields see sp804 spec. */ +#define ARM_T_LOAD HW_REGISTER_RW(ARM_BASE+0x400) +#define ARM_T_VALUE HW_REGISTER_RW(ARM_BASE+0x404) +#define ARM_T_CONTROL HW_REGISTER_RW(ARM_BASE+0x408) +#define ARM_T_IRQCNTL HW_REGISTER_RW(ARM_BASE+0x40C) +#define ARM_T_RAWIRQ HW_REGISTER_RW(ARM_BASE+0x410) +#define ARM_T_MSKIRQ HW_REGISTER_RW(ARM_BASE+0x414) +#define ARM_T_RELOAD HW_REGISTER_RW(ARM_BASE+0x418) +#define ARM_T_PREDIV HW_REGISTER_RW(ARM_BASE+0x41c) +#define ARM_T_FREECNT HW_REGISTER_RW(ARM_BASE+0x420) + +#define TIMER_CTRL_ONESHOT (1 << 0) +#define TIMER_CTRL_32BIT (1 << 1) +#define TIMER_CTRL_DIV1 (0 << 2) +#define TIMER_CTRL_DIV16 (1 << 2) +#define TIMER_CTRL_DIV256 (2 << 2) +#define TIMER_CTRL_IE (1 << 5) +#define TIMER_CTRL_PERIODIC (1 << 6) +#define TIMER_CTRL_ENABLE (1 << 7) +#define TIMER_CTRL_DBGHALT (1 << 8) +#define TIMER_CTRL_ENAFREE (1 << 9) +#define TIMER_CTRL_FREEDIV_SHIFT 16) +#define TIMER_CTRL_FREEDIV_MASK 0xff + +/* Semaphores, Doorbells, Mailboxes */ +#define ARM_SBM_OWN0 (ARM_BASE+0x800) +#define ARM_SBM_OWN1 (ARM_BASE+0x900) +#define ARM_SBM_OWN2 (ARM_BASE+0xA00) +#define ARM_SBM_OWN3 (ARM_BASE+0xB00) + +/* MAILBOXES + * Register flags are common across all + * owner registers. See end of this section + * + * Semaphores, Doorbells, Mailboxes Owner 0 + * + */ + +#define ARM_0_SEMS HW_REGISTER_RW(ARM_SBM_OWN0+0x00) +#define ARM_0_SEM0 HW_REGISTER_RW(ARM_SBM_OWN0+0x00) +#define ARM_0_SEM1 HW_REGISTER_RW(ARM_SBM_OWN0+0x04) +#define ARM_0_SEM2 HW_REGISTER_RW(ARM_SBM_OWN0+0x08) +#define ARM_0_SEM3 HW_REGISTER_RW(ARM_SBM_OWN0+0x0C) +#define ARM_0_SEM4 HW_REGISTER_RW(ARM_SBM_OWN0+0x10) +#define ARM_0_SEM5 HW_REGISTER_RW(ARM_SBM_OWN0+0x14) +#define ARM_0_SEM6 HW_REGISTER_RW(ARM_SBM_OWN0+0x18) +#define ARM_0_SEM7 HW_REGISTER_RW(ARM_SBM_OWN0+0x1C) +#define ARM_0_BELL0 HW_REGISTER_RW(ARM_SBM_OWN0+0x40) +#define ARM_0_BELL1 HW_REGISTER_RW(ARM_SBM_OWN0+0x44) +#define ARM_0_BELL2 HW_REGISTER_RW(ARM_SBM_OWN0+0x48) +#define ARM_0_BELL3 HW_REGISTER_RW(ARM_SBM_OWN0+0x4C) +/* MAILBOX 0 access in Owner 0 area */ +/* Some addresses should ONLY be used by owner 0 */ +#define ARM_0_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN0+0x80) /* .. 0x8C (4 locations) */ +#define ARM_0_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN0+0x80) /* .. 0x8C (4 locations) Normal read */ +#define ARM_0_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN0+0x90) /* none-pop read */ +#define ARM_0_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN0+0x94) /* Sender read (only LS 2 bits) */ +#define ARM_0_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN0+0x98) /* Status read */ +#define ARM_0_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN0+0x9C) /* Config read/write */ +/* MAILBOX 1 access in Owner 0 area */ +/* Owner 0 should only WRITE to this mailbox */ +#define ARM_0_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN0+0xA0) /* .. 0xAC (4 locations) */ +/*#define ARM_0_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN0+0xA0) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_0_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN0+0xB0) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_0_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN0+0xB4) */ /* DO NOT USE THIS !!!!! */ +#define ARM_0_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN0+0xB8) /* Status read */ +/*#define ARM_0_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN0+0xBC) */ /* DO NOT USE THIS !!!!! */ +/* General SEM, BELL, MAIL config/status */ +#define ARM_0_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN0+0xE0) /* semaphore clear/debug register */ +#define ARM_0_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN0+0xE4) /* Doorbells clear/debug register */ +#define ARM_0_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN0+0xF8) /* ALL interrupts */ +#define ARM_0_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN0+0xFC) /* IRQS pending for owner 0 */ + +/* Semaphores, Doorbells, Mailboxes Owner 1 */ +#define ARM_1_SEMS HW_REGISTER_RW(ARM_SBM_OWN1+0x00) +#define ARM_1_SEM0 HW_REGISTER_RW(ARM_SBM_OWN1+0x00) +#define ARM_1_SEM1 HW_REGISTER_RW(ARM_SBM_OWN1+0x04) +#define ARM_1_SEM2 HW_REGISTER_RW(ARM_SBM_OWN1+0x08) +#define ARM_1_SEM3 HW_REGISTER_RW(ARM_SBM_OWN1+0x0C) +#define ARM_1_SEM4 HW_REGISTER_RW(ARM_SBM_OWN1+0x10) +#define ARM_1_SEM5 HW_REGISTER_RW(ARM_SBM_OWN1+0x14) +#define ARM_1_SEM6 HW_REGISTER_RW(ARM_SBM_OWN1+0x18) +#define ARM_1_SEM7 HW_REGISTER_RW(ARM_SBM_OWN1+0x1C) +#define ARM_1_BELL0 HW_REGISTER_RW(ARM_SBM_OWN1+0x40) +#define ARM_1_BELL1 HW_REGISTER_RW(ARM_SBM_OWN1+0x44) +#define ARM_1_BELL2 HW_REGISTER_RW(ARM_SBM_OWN1+0x48) +#define ARM_1_BELL3 HW_REGISTER_RW(ARM_SBM_OWN1+0x4C) +/* MAILBOX 0 access in Owner 0 area */ +/* Owner 1 should only WRITE to this mailbox */ +#define ARM_1_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN1+0x80) /* .. 0x8C (4 locations) */ +/*#define ARM_1_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN1+0x80) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_1_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN1+0x90) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_1_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN1+0x94) */ /* DO NOT USE THIS !!!!! */ +#define ARM_1_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN1+0x98) /* Status read */ +/*#define ARM_1_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN1+0x9C) */ /* DO NOT USE THIS !!!!! */ +/* MAILBOX 1 access in Owner 0 area */ +#define ARM_1_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN1+0xA0) /* .. 0xAC (4 locations) */ +#define ARM_1_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN1+0xA0) /* .. 0xAC (4 locations) Normal read */ +#define ARM_1_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN1+0xB0) /* none-pop read */ +#define ARM_1_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN1+0xB4) /* Sender read (only LS 2 bits) */ +#define ARM_1_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN1+0xB8) /* Status read */ +#define ARM_1_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN1+0xBC) +/* General SEM, BELL, MAIL config/status */ +#define ARM_1_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN1+0xE0) /* semaphore clear/debug register */ +#define ARM_1_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN1+0xE4) /* Doorbells clear/debug register */ +#define ARM_1_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN1+0xFC) /* IRQS pending for owner 1 */ +#define ARM_1_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN1+0xF8) /* ALL interrupts */ + +/* Semaphores, Doorbells, Mailboxes Owner 2 */ +#define ARM_2_SEMS HW_REGISTER_RW(ARM_SBM_OWN2+0x00) +#define ARM_2_SEM0 HW_REGISTER_RW(ARM_SBM_OWN2+0x00) +#define ARM_2_SEM1 HW_REGISTER_RW(ARM_SBM_OWN2+0x04) +#define ARM_2_SEM2 HW_REGISTER_RW(ARM_SBM_OWN2+0x08) +#define ARM_2_SEM3 HW_REGISTER_RW(ARM_SBM_OWN2+0x0C) +#define ARM_2_SEM4 HW_REGISTER_RW(ARM_SBM_OWN2+0x10) +#define ARM_2_SEM5 HW_REGISTER_RW(ARM_SBM_OWN2+0x14) +#define ARM_2_SEM6 HW_REGISTER_RW(ARM_SBM_OWN2+0x18) +#define ARM_2_SEM7 HW_REGISTER_RW(ARM_SBM_OWN2+0x1C) +#define ARM_2_BELL0 HW_REGISTER_RW(ARM_SBM_OWN2+0x40) +#define ARM_2_BELL1 HW_REGISTER_RW(ARM_SBM_OWN2+0x44) +#define ARM_2_BELL2 HW_REGISTER_RW(ARM_SBM_OWN2+0x48) +#define ARM_2_BELL3 HW_REGISTER_RW(ARM_SBM_OWN2+0x4C) +/* MAILBOX 0 access in Owner 2 area */ +/* Owner 2 should only WRITE to this mailbox */ +#define ARM_2_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN2+0x80) /* .. 0x8C (4 locations) */ +/*#define ARM_2_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN2+0x80) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_2_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN2+0x90) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_2_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN2+0x94) */ /* DO NOT USE THIS !!!!! */ +#define ARM_2_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN2+0x98) /* Status read */ +/*#define ARM_2_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN2+0x9C) */ /* DO NOT USE THIS !!!!! */ +/* MAILBOX 1 access in Owner 2 area */ +/* Owner 2 should only WRITE to this mailbox */ +#define ARM_2_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN2+0xA0) /* .. 0xAC (4 locations) */ +/*#define ARM_2_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN2+0xA0) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_2_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN2+0xB0) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_2_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN2+0xB4) */ /* DO NOT USE THIS !!!!! */ +#define ARM_2_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN2+0xB8) /* Status read */ +/*#define ARM_2_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN2+0xBC) */ /* DO NOT USE THIS !!!!! */ +/* General SEM, BELL, MAIL config/status */ +#define ARM_2_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN2+0xE0) /* semaphore clear/debug register */ +#define ARM_2_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN2+0xE4) /* Doorbells clear/debug register */ +#define ARM_2_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN2+0xFC) /* IRQS pending for owner 2 */ +#define ARM_2_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN2+0xF8) /* ALL interrupts */ + +/* Semaphores, Doorbells, Mailboxes Owner 3 */ +#define ARM_3_SEMS HW_REGISTER_RW(ARM_SBM_OWN3+0x00) +#define ARM_3_SEM0 HW_REGISTER_RW(ARM_SBM_OWN3+0x00) +#define ARM_3_SEM1 HW_REGISTER_RW(ARM_SBM_OWN3+0x04) +#define ARM_3_SEM2 HW_REGISTER_RW(ARM_SBM_OWN3+0x08) +#define ARM_3_SEM3 HW_REGISTER_RW(ARM_SBM_OWN3+0x0C) +#define ARM_3_SEM4 HW_REGISTER_RW(ARM_SBM_OWN3+0x10) +#define ARM_3_SEM5 HW_REGISTER_RW(ARM_SBM_OWN3+0x14) +#define ARM_3_SEM6 HW_REGISTER_RW(ARM_SBM_OWN3+0x18) +#define ARM_3_SEM7 HW_REGISTER_RW(ARM_SBM_OWN3+0x1C) +#define ARM_3_BELL0 HW_REGISTER_RW(ARM_SBM_OWN3+0x40) +#define ARM_3_BELL1 HW_REGISTER_RW(ARM_SBM_OWN3+0x44) +#define ARM_3_BELL2 HW_REGISTER_RW(ARM_SBM_OWN3+0x48) +#define ARM_3_BELL3 HW_REGISTER_RW(ARM_SBM_OWN3+0x4C) +/* MAILBOX 0 access in Owner 3 area */ +/* Owner 3 should only WRITE to this mailbox */ +#define ARM_3_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN3+0x80) /* .. 0x8C (4 locations) */ +/*#define ARM_3_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN3+0x80) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_3_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN3+0x90) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_3_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN3+0x94) */ /* DO NOT USE THIS !!!!! */ +#define ARM_3_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN3+0x98) /* Status read */ +/*#define ARM_3_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN3+0x9C) */ /* DO NOT USE THIS !!!!! */ +/* MAILBOX 1 access in Owner 3 area */ +/* Owner 3 should only WRITE to this mailbox */ +#define ARM_3_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN3+0xA0) /* .. 0xAC (4 locations) */ +/*#define ARM_3_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN3+0xA0) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_3_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN3+0xB0) */ /* DO NOT USE THIS !!!!! */ +/*#define ARM_3_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN3+0xB4) */ /* DO NOT USE THIS !!!!! */ +#define ARM_3_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN3+0xB8) /* Status read */ +/*#define ARM_3_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN3+0xBC) */ /* DO NOT USE THIS !!!!! */ +/* General SEM, BELL, MAIL config/status */ +#define ARM_3_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN3+0xE0) /* semaphore clear/debug register */ +#define ARM_3_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN3+0xE4) /* Doorbells clear/debug register */ +#define ARM_3_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN3+0xFC) /* IRQS pending for owner 3 */ +#define ARM_3_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN3+0xF8) /* ALL interrupts */ + + + +/* Mailbox flags. Valid for all owners */ + +/* Mailbox status register (...0x98) */ +#define ARM_MS_FULL 0x80000000 +#define ARM_MS_EMPTY 0x40000000 +#define ARM_MS_LEVEL 0x400000FF /* Max. value depdnds on mailbox depth parameter */ + +/* MAILBOX config/status register (...0x9C) */ +/* ANY write to this register clears the error bits! */ +#define ARM_MC_IHAVEDATAIRQEN 0x00000001 /* mailbox irq enable: has data */ +#define ARM_MC_IHAVESPACEIRQEN 0x00000002 /* mailbox irq enable: has space */ +#define ARM_MC_OPPISEMPTYIRQEN 0x00000004 /* mailbox irq enable: Opp. is empty */ +#define ARM_MC_MAIL_CLEAR 0x00000008 /* mailbox clear write 1, then 0 */ +#define ARM_MC_IHAVEDATAIRQPEND 0x00000010 /* mailbox irq pending: has space */ +#define ARM_MC_IHAVESPACEIRQPEND 0x00000020 /* mailbox irq pending: Opp. is empty */ +#define ARM_MC_OPPISEMPTYIRQPEND 0x00000040 /* mailbox irq pending */ +/* Bit 7 is unused */ +#define ARM_MC_ERRNOOWN 0x00000100 /* error : none owner read from mailbox */ +#define ARM_MC_ERROVERFLW 0x00000200 /* error : write to fill mailbox */ +#define ARM_MC_ERRUNDRFLW 0x00000400 /* error : read from empty mailbox */ + +/* Semaphore clear/debug register (...0xE0) */ +#define ARM_SD_OWN0 0x00000003 /* Owner of sem 0 */ +#define ARM_SD_OWN1 0x0000000C /* Owner of sem 1 */ +#define ARM_SD_OWN2 0x00000030 /* Owner of sem 2 */ +#define ARM_SD_OWN3 0x000000C0 /* Owner of sem 3 */ +#define ARM_SD_OWN4 0x00000300 /* Owner of sem 4 */ +#define ARM_SD_OWN5 0x00000C00 /* Owner of sem 5 */ +#define ARM_SD_OWN6 0x00003000 /* Owner of sem 6 */ +#define ARM_SD_OWN7 0x0000C000 /* Owner of sem 7 */ +#define ARM_SD_SEM0 0x00010000 /* Status of sem 0 */ +#define ARM_SD_SEM1 0x00020000 /* Status of sem 1 */ +#define ARM_SD_SEM2 0x00040000 /* Status of sem 2 */ +#define ARM_SD_SEM3 0x00080000 /* Status of sem 3 */ +#define ARM_SD_SEM4 0x00100000 /* Status of sem 4 */ +#define ARM_SD_SEM5 0x00200000 /* Status of sem 5 */ +#define ARM_SD_SEM6 0x00400000 /* Status of sem 6 */ +#define ARM_SD_SEM7 0x00800000 /* Status of sem 7 */ + +/* Doorbells clear/debug register (...0xE4) */ +#define ARM_BD_OWN0 0x00000003 /* Owner of doorbell 0 */ +#define ARM_BD_OWN1 0x0000000C /* Owner of doorbell 1 */ +#define ARM_BD_OWN2 0x00000030 /* Owner of doorbell 2 */ +#define ARM_BD_OWN3 0x000000C0 /* Owner of doorbell 3 */ +#define ARM_BD_BELL0 0x00000100 /* Status of doorbell 0 */ +#define ARM_BD_BELL1 0x00000200 /* Status of doorbell 1 */ +#define ARM_BD_BELL2 0x00000400 /* Status of doorbell 2 */ +#define ARM_BD_BELL3 0x00000800 /* Status of doorbell 3 */ + +/* MY IRQS register (...0xF8) */ +#define ARM_MYIRQ_BELL 0x00000001 /* This owner has a doorbell IRQ */ +#define ARM_MYIRQ_MAIL 0x00000002 /* This owner has a mailbox IRQ */ + +/* ALL IRQS register (...0xF8) */ +#define ARM_AIS_BELL0 0x00000001 /* Doorbell 0 IRQ pending */ +#define ARM_AIS_BELL1 0x00000002 /* Doorbell 1 IRQ pending */ +#define ARM_AIS_BELL2 0x00000004 /* Doorbell 2 IRQ pending */ +#define ARM_AIS_BELL3 0x00000008 /* Doorbell 3 IRQ pending */ +#define ARM_AIS0_HAVEDATA 0x00000010 /* MAIL 0 has data IRQ pending */ +#define ARM_AIS0_HAVESPAC 0x00000020 /* MAIL 0 has space IRQ pending */ +#define ARM_AIS0_OPPEMPTY 0x00000040 /* MAIL 0 opposite is empty IRQ */ +#define ARM_AIS1_HAVEDATA 0x00000080 /* MAIL 1 has data IRQ pending */ +#define ARM_AIS1_HAVESPAC 0x00000100 /* MAIL 1 has space IRQ pending */ +#define ARM_AIS1_OPPEMPTY 0x00000200 /* MAIL 1 opposite is empty IRQ */ +/* Note that bell-0, bell-1 and MAIL0 IRQ go only to the ARM */ +/* Whilst that bell-2, bell-3 and MAIL1 IRQ go only to the VC */ +/* */ +/* ARM JTAG BASH */ +/* */ +#define AJB_BASE 0x7e2000c0 + +#define AJBCONF HW_REGISTER_RW(AJB_BASE+0x00) +#define AJB_BITS0 0x000000 +#define AJB_BITS4 0x000004 +#define AJB_BITS8 0x000008 +#define AJB_BITS12 0x00000C +#define AJB_BITS16 0x000010 +#define AJB_BITS20 0x000014 +#define AJB_BITS24 0x000018 +#define AJB_BITS28 0x00001C +#define AJB_BITS32 0x000020 +#define AJB_BITS34 0x000022 +#define AJB_OUT_MS 0x000040 +#define AJB_OUT_LS 0x000000 +#define AJB_INV_CLK 0x000080 +#define AJB_D0_RISE 0x000100 +#define AJB_D0_FALL 0x000000 +#define AJB_D1_RISE 0x000200 +#define AJB_D1_FALL 0x000000 +#define AJB_IN_RISE 0x000400 +#define AJB_IN_FALL 0x000000 +#define AJB_ENABLE 0x000800 +#define AJB_HOLD0 0x000000 +#define AJB_HOLD1 0x001000 +#define AJB_HOLD2 0x002000 +#define AJB_HOLD3 0x003000 +#define AJB_RESETN 0x004000 +#define AJB_CLKSHFT 16 +#define AJB_BUSY 0x80000000 +#define AJBTMS HW_REGISTER_RW(AJB_BASE+0x04) +#define AJBTDI HW_REGISTER_RW(AJB_BASE+0x08) +#define AJBTDO HW_REGISTER_RW(AJB_BASE+0x0c) + +#endif diff --git a/arch/arm/mach-bcm2708/include/mach/arm_power.h b/arch/arm/mach-bcm2708/include/mach/arm_power.h new file mode 100644 index 0000000..aae9136 --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/arm_power.h @@ -0,0 +1,60 @@ +/* + * linux/arch/arm/mach-bcm2708/include/mach/arm_power.h + * + * Copyright (C) 2010 Broadcom + * + * 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 _ARM_POWER_H +#define _ARM_POWER_H + +/* Use meaningful names on each side */ +#ifdef __VIDEOCORE__ +#define PREFIX(x) ARM_##x +#else +#define PREFIX(x) BCM_##x +#endif + +enum { + PREFIX(POWER_SDCARD_BIT), + PREFIX(POWER_UART_BIT), + PREFIX(POWER_MINIUART_BIT), + PREFIX(POWER_USB_BIT), + PREFIX(POWER_I2C0_BIT), + PREFIX(POWER_I2C1_BIT), + PREFIX(POWER_I2C2_BIT), + PREFIX(POWER_SPI_BIT), + PREFIX(POWER_CCP2TX_BIT), + + PREFIX(POWER_MAX) +}; + +enum { + PREFIX(POWER_SDCARD) = (1 << PREFIX(POWER_SDCARD_BIT)), + PREFIX(POWER_UART) = (1 << PREFIX(POWER_UART_BIT)), + PREFIX(POWER_MINIUART) = (1 << PREFIX(POWER_MINIUART_BIT)), + PREFIX(POWER_USB) = (1 << PREFIX(POWER_USB_BIT)), + PREFIX(POWER_I2C0) = (1 << PREFIX(POWER_I2C0_BIT)), + PREFIX(POWER_I2C1_MASK) = (1 << PREFIX(POWER_I2C1_BIT)), + PREFIX(POWER_I2C2_MASK) = (1 << PREFIX(POWER_I2C2_BIT)), + PREFIX(POWER_SPI_MASK) = (1 << PREFIX(POWER_SPI_BIT)), + PREFIX(POWER_CCP2TX_MASK) = (1 << PREFIX(POWER_CCP2TX_BIT)), + + PREFIX(POWER_MASK) = (1 << PREFIX(POWER_MAX)) - 1, + PREFIX(POWER_NONE) = 0 +}; + +#endif diff --git a/arch/arm/mach-bcm2708/include/mach/clkdev.h b/arch/arm/mach-bcm2708/include/mach/clkdev.h new file mode 100644 index 0000000..04b37a8 --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/clkdev.h @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif diff --git a/arch/arm/mach-bcm2708/include/mach/debug-macro.S b/arch/arm/mach-bcm2708/include/mach/debug-macro.S new file mode 100644 index 0000000..2d0dc1c --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/debug-macro.S @@ -0,0 +1,22 @@ +/* arch/arm/mach-bcm2708/include/mach/debug-macro.S + * + * Debugging macro include header + * + * Copyright (C) 2010 Broadcom + * Copyright (C) 1994-1999 Russell King + * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks + * + * 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 + + .macro addruart, rp, rv, tmp + ldr \rp, =UART0_BASE + ldr \rv, =IO_ADDRESS(UART0_BASE) + .endm + +#include diff --git a/arch/arm/mach-bcm2708/include/mach/dma.h b/arch/arm/mach-bcm2708/include/mach/dma.h new file mode 100644 index 0000000..ac7a4a0 --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/dma.h @@ -0,0 +1,86 @@ +/* + * linux/arch/arm/mach-bcm2708/include/mach/dma.h + * + * Copyright (C) 2010 Broadcom + * + * 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 _MACH_BCM2708_DMA_H +#define _MACH_BCM2708_DMA_H + +#define BCM_DMAMAN_DRIVER_NAME "bcm2708_dma" + +/* DMA CS Control and Status bits */ +#define BCM2708_DMA_ACTIVE (1 << 0) +#define BCM2708_DMA_INT (1 << 2) +#define BCM2708_DMA_ISPAUSED (1 << 4) /* Pause requested or not active */ +#define BCM2708_DMA_ISHELD (1 << 5) /* Is held by DREQ flow control */ +#define BCM2708_DMA_ERR (1 << 8) +#define BCM2708_DMA_ABORT (1 << 30) /* stop current CB, go to next, WO */ +#define BCM2708_DMA_RESET (1 << 31) /* WO, self clearing */ + +/* DMA control block "info" field bits */ +#define BCM2708_DMA_INT_EN (1 << 0) +#define BCM2708_DMA_TDMODE (1 << 1) +#define BCM2708_DMA_WAIT_RESP (1 << 3) +#define BCM2708_DMA_D_INC (1 << 4) +#define BCM2708_DMA_D_WIDTH (1 << 5) +#define BCM2708_DMA_D_DREQ (1 << 6) +#define BCM2708_DMA_S_INC (1 << 8) +#define BCM2708_DMA_S_WIDTH (1 << 9) +#define BCM2708_DMA_S_DREQ (1 << 10) + +#define BCM2708_DMA_BURST(x) (((x)&0xf) << 12) +#define BCM2708_DMA_PER_MAP(x) ((x) << 16) +#define BCM2708_DMA_WAITS(x) (((x)&0x1f) << 21) + +#define BCM2708_DMA_DREQ_EMMC 11 +#define BCM2708_DMA_DREQ_SDHOST 13 + +#define BCM2708_DMA_CS 0x00 /* Control and Status */ +#define BCM2708_DMA_ADDR 0x04 +/* the current control block appears in the following registers - read only */ +#define BCM2708_DMA_INFO 0x08 +#define BCM2708_DMA_NEXTCB 0x1C +#define BCM2708_DMA_DEBUG 0x20 + +#define BCM2708_DMA4_CS (BCM2708_DMA_CHAN(4)+BCM2708_DMA_CS) +#define BCM2708_DMA4_ADDR (BCM2708_DMA_CHAN(4)+BCM2708_DMA_ADDR) + +#define BCM2708_DMA_TDMODE_LEN(w, h) ((h) << 16 | (w)) + +struct bcm2708_dma_cb { + unsigned long info; + unsigned long src; + unsigned long dst; + unsigned long length; + unsigned long stride; + unsigned long next; + unsigned long pad[2]; +}; + +extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len); +extern void bcm_dma_start(void __iomem *dma_chan_base, + dma_addr_t control_block); +extern void bcm_dma_wait_idle(void __iomem *dma_chan_base); +extern int /*rc*/ bcm_dma_abort(void __iomem *dma_chan_base); + +/* When listing features we can ask for when allocating DMA channels give + those with higher priority smaller ordinal numbers */ +#define BCM_DMA_FEATURE_FAST_ORD 0 +#define BCM_DMA_FEATURE_BULK_ORD 1 +#define BCM_DMA_FEATURE_FAST (1< + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + ldr \base, =IO_ADDRESS(ARMCTRL_IC_BASE) + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + /* get masked status */ + ldr \irqstat, [\base, #(ARM_IRQ_PEND0 - ARMCTRL_IC_BASE)] + mov \irqnr, #(ARM_IRQ0_BASE + 31) + and \tmp, \irqstat, #0x300 @ save bits 8 and 9 + /* clear bits 8 and 9, and test */ + bics \irqstat, \irqstat, #0x300 + bne 1010f + + tst \tmp, #0x100 + ldrne \irqstat, [\base, #(ARM_IRQ_PEND1 - ARMCTRL_IC_BASE)] + movne \irqnr, #(ARM_IRQ1_BASE + 31) + @ Mask out the interrupts also present in PEND0 - see SW-5809 + bicne \irqstat, #((1<<7) | (1<<9) | (1<<10)) + bicne \irqstat, #((1<<18) | (1<<19)) + bne 1010f + + tst \tmp, #0x200 + ldrne \irqstat, [\base, #(ARM_IRQ_PEND2 - ARMCTRL_IC_BASE)] + movne \irqnr, #(ARM_IRQ2_BASE + 31) + @ Mask out the interrupts also present in PEND0 - see SW-5809 + bicne \irqstat, #((1<<21) | (1<<22) | (1<<23) | (1<<24) | (1<<25)) + bicne \irqstat, #((1<<30)) + beq 1020f + +1010: + @ For non-zero x, LSB(x) = 31 - CLZ(x^(x-1)) + @ N.B. CLZ is an ARM5 instruction. + sub \tmp, \irqstat, #1 + eor \irqstat, \irqstat, \tmp + clz \tmp, \irqstat + sub \irqnr, \tmp + +1020: @ EQ will be set if no irqs pending + + .endm diff --git a/arch/arm/mach-bcm2708/include/mach/frc.h b/arch/arm/mach-bcm2708/include/mach/frc.h new file mode 100644 index 0000000..dd51e07 --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/frc.h @@ -0,0 +1,38 @@ +/* + * arch/arm/mach-bcm2708/include/mach/timex.h + * + * BCM2708 free running counter (timer) + * + * Copyright (C) 2010 Broadcom + * + * 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 _MACH_FRC_H +#define _MACH_FRC_H + +#define FRC_TICK_RATE (1000000) + +/*! Free running counter incrementing at the CLOCK_TICK_RATE + (slightly faster than frc_clock_ticks63() + */ +extern unsigned long frc_clock_ticks32(void); + +/*! Free running counter incrementing at the CLOCK_TICK_RATE + * Note - top bit should be ignored (see cnt32_to_63) + */ +extern unsigned long long frc_clock_ticks63(void); + +#endif diff --git a/arch/arm/mach-bcm2708/include/mach/gpio.h b/arch/arm/mach-bcm2708/include/mach/gpio.h new file mode 100644 index 0000000..f600bc7 --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/gpio.h @@ -0,0 +1,18 @@ +/* + * arch/arm/mach-bcm2708/include/mach/gpio.h + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __ASM_ARCH_GPIO_H +#define __ASM_ARCH_GPIO_H + +#define ARCH_NR_GPIOS 54 // number of gpio lines + +#define gpio_to_irq(x) ((x) + GPIO_IRQ_START) +#define irq_to_gpio(x) ((x) - GPIO_IRQ_START) + +#endif + diff --git a/arch/arm/mach-bcm2708/include/mach/hardware.h b/arch/arm/mach-bcm2708/include/mach/hardware.h new file mode 100644 index 0000000..c2954e8 --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/hardware.h @@ -0,0 +1,28 @@ +/* + * arch/arm/mach-bcm2708/include/mach/hardware.h + * + * This file contains the hardware definitions of the BCM2708 devices. + * + * Copyright (C) 2010 Broadcom + * + * 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 __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +#include +#include + +#endif diff --git a/arch/arm/mach-bcm2708/include/mach/io.h b/arch/arm/mach-bcm2708/include/mach/io.h new file mode 100644 index 0000000..e6eb84d --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/io.h @@ -0,0 +1,27 @@ +/* + * arch/arm/mach-bcm2708/include/mach/io.h + * + * Copyright (C) 2003 ARM Limited + * + * 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 __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +#define __io(a) __typesafe_io(a) + +#endif diff --git a/arch/arm/mach-bcm2708/include/mach/irqs.h b/arch/arm/mach-bcm2708/include/mach/irqs.h new file mode 100644 index 0000000..e8bb068 --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/irqs.h @@ -0,0 +1,196 @@ +/* + * arch/arm/mach-bcm2708/include/mach/irqs.h + * + * Copyright (C) 2010 Broadcom + * Copyright (C) 2003 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _BCM2708_IRQS_H_ +#define _BCM2708_IRQS_H_ + +#include + +/* + * IRQ interrupts definitions are the same as the INT definitions + * held within platform.h + */ +#define IRQ_ARMCTRL_START 0 +#define IRQ_TIMER0 (IRQ_ARMCTRL_START + INTERRUPT_TIMER0) +#define IRQ_TIMER1 (IRQ_ARMCTRL_START + INTERRUPT_TIMER1) +#define IRQ_TIMER2 (IRQ_ARMCTRL_START + INTERRUPT_TIMER2) +#define IRQ_TIMER3 (IRQ_ARMCTRL_START + INTERRUPT_TIMER3) +#define IRQ_CODEC0 (IRQ_ARMCTRL_START + INTERRUPT_CODEC0) +#define IRQ_CODEC1 (IRQ_ARMCTRL_START + INTERRUPT_CODEC1) +#define IRQ_CODEC2 (IRQ_ARMCTRL_START + INTERRUPT_CODEC2) +#define IRQ_JPEG (IRQ_ARMCTRL_START + INTERRUPT_JPEG) +#define IRQ_ISP (IRQ_ARMCTRL_START + INTERRUPT_ISP) +#define IRQ_USB (IRQ_ARMCTRL_START + INTERRUPT_USB) +#define IRQ_3D (IRQ_ARMCTRL_START + INTERRUPT_3D) +#define IRQ_TRANSPOSER (IRQ_ARMCTRL_START + INTERRUPT_TRANSPOSER) +#define IRQ_MULTICORESYNC0 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC0) +#define IRQ_MULTICORESYNC1 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC1) +#define IRQ_MULTICORESYNC2 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC2) +#define IRQ_MULTICORESYNC3 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC3) +#define IRQ_DMA0 (IRQ_ARMCTRL_START + INTERRUPT_DMA0) +#define IRQ_DMA1 (IRQ_ARMCTRL_START + INTERRUPT_DMA1) +#define IRQ_DMA2 (IRQ_ARMCTRL_START + INTERRUPT_DMA2) +#define IRQ_DMA3 (IRQ_ARMCTRL_START + INTERRUPT_DMA3) +#define IRQ_DMA4 (IRQ_ARMCTRL_START + INTERRUPT_DMA4) +#define IRQ_DMA5 (IRQ_ARMCTRL_START + INTERRUPT_DMA5) +#define IRQ_DMA6 (IRQ_ARMCTRL_START + INTERRUPT_DMA6) +#define IRQ_DMA7 (IRQ_ARMCTRL_START + INTERRUPT_DMA7) +#define IRQ_DMA8 (IRQ_ARMCTRL_START + INTERRUPT_DMA8) +#define IRQ_DMA9 (IRQ_ARMCTRL_START + INTERRUPT_DMA9) +#define IRQ_DMA10 (IRQ_ARMCTRL_START + INTERRUPT_DMA10) +#define IRQ_DMA11 (IRQ_ARMCTRL_START + INTERRUPT_DMA11) +#define IRQ_DMA12 (IRQ_ARMCTRL_START + INTERRUPT_DMA12) +#define IRQ_AUX (IRQ_ARMCTRL_START + INTERRUPT_AUX) +#define IRQ_ARM (IRQ_ARMCTRL_START + INTERRUPT_ARM) +#define IRQ_VPUDMA (IRQ_ARMCTRL_START + INTERRUPT_VPUDMA) +#define IRQ_HOSTPORT (IRQ_ARMCTRL_START + INTERRUPT_HOSTPORT) +#define IRQ_VIDEOSCALER (IRQ_ARMCTRL_START + INTERRUPT_VIDEOSCALER) +#define IRQ_CCP2TX (IRQ_ARMCTRL_START + INTERRUPT_CCP2TX) +#define IRQ_SDC (IRQ_ARMCTRL_START + INTERRUPT_SDC) +#define IRQ_DSI0 (IRQ_ARMCTRL_START + INTERRUPT_DSI0) +#define IRQ_AVE (IRQ_ARMCTRL_START + INTERRUPT_AVE) +#define IRQ_CAM0 (IRQ_ARMCTRL_START + INTERRUPT_CAM0) +#define IRQ_CAM1 (IRQ_ARMCTRL_START + INTERRUPT_CAM1) +#define IRQ_HDMI0 (IRQ_ARMCTRL_START + INTERRUPT_HDMI0) +#define IRQ_HDMI1 (IRQ_ARMCTRL_START + INTERRUPT_HDMI1) +#define IRQ_PIXELVALVE1 (IRQ_ARMCTRL_START + INTERRUPT_PIXELVALVE1) +#define IRQ_I2CSPISLV (IRQ_ARMCTRL_START + INTERRUPT_I2CSPISLV) +#define IRQ_DSI1 (IRQ_ARMCTRL_START + INTERRUPT_DSI1) +#define IRQ_PWA0 (IRQ_ARMCTRL_START + INTERRUPT_PWA0) +#define IRQ_PWA1 (IRQ_ARMCTRL_START + INTERRUPT_PWA1) +#define IRQ_CPR (IRQ_ARMCTRL_START + INTERRUPT_CPR) +#define IRQ_SMI (IRQ_ARMCTRL_START + INTERRUPT_SMI) +#define IRQ_GPIO0 (IRQ_ARMCTRL_START + INTERRUPT_GPIO0) +#define IRQ_GPIO1 (IRQ_ARMCTRL_START + INTERRUPT_GPIO1) +#define IRQ_GPIO2 (IRQ_ARMCTRL_START + INTERRUPT_GPIO2) +#define IRQ_GPIO3 (IRQ_ARMCTRL_START + INTERRUPT_GPIO3) +#define IRQ_I2C (IRQ_ARMCTRL_START + INTERRUPT_I2C) +#define IRQ_SPI (IRQ_ARMCTRL_START + INTERRUPT_SPI) +#define IRQ_I2SPCM (IRQ_ARMCTRL_START + INTERRUPT_I2SPCM) +#define IRQ_SDIO (IRQ_ARMCTRL_START + INTERRUPT_SDIO) +#define IRQ_UART (IRQ_ARMCTRL_START + INTERRUPT_UART) +#define IRQ_SLIMBUS (IRQ_ARMCTRL_START + INTERRUPT_SLIMBUS) +#define IRQ_VEC (IRQ_ARMCTRL_START + INTERRUPT_VEC) +#define IRQ_CPG (IRQ_ARMCTRL_START + INTERRUPT_CPG) +#define IRQ_RNG (IRQ_ARMCTRL_START + INTERRUPT_RNG) +#define IRQ_ARASANSDIO (IRQ_ARMCTRL_START + INTERRUPT_ARASANSDIO) +#define IRQ_AVSPMON (IRQ_ARMCTRL_START + INTERRUPT_AVSPMON) + +#define IRQ_ARM_TIMER (IRQ_ARMCTRL_START + INTERRUPT_ARM_TIMER) +#define IRQ_ARM_MAILBOX (IRQ_ARMCTRL_START + INTERRUPT_ARM_MAILBOX) +#define IRQ_ARM_DOORBELL_0 (IRQ_ARMCTRL_START + INTERRUPT_ARM_DOORBELL_0) +#define IRQ_ARM_DOORBELL_1 (IRQ_ARMCTRL_START + INTERRUPT_ARM_DOORBELL_1) +#define IRQ_VPU0_HALTED (IRQ_ARMCTRL_START + INTERRUPT_VPU0_HALTED) +#define IRQ_VPU1_HALTED (IRQ_ARMCTRL_START + INTERRUPT_VPU1_HALTED) +#define IRQ_ILLEGAL_TYPE0 (IRQ_ARMCTRL_START + INTERRUPT_ILLEGAL_TYPE0) +#define IRQ_ILLEGAL_TYPE1 (IRQ_ARMCTRL_START + INTERRUPT_ILLEGAL_TYPE1) +#define IRQ_PENDING1 (IRQ_ARMCTRL_START + INTERRUPT_PENDING1) +#define IRQ_PENDING2 (IRQ_ARMCTRL_START + INTERRUPT_PENDING2) + +/* + * FIQ interrupts definitions are the same as the INT definitions. + */ +#define FIQ_TIMER0 INT_TIMER0 +#define FIQ_TIMER1 INT_TIMER1 +#define FIQ_TIMER2 INT_TIMER2 +#define FIQ_TIMER3 INT_TIMER3 +#define FIQ_CODEC0 INT_CODEC0 +#define FIQ_CODEC1 INT_CODEC1 +#define FIQ_CODEC2 INT_CODEC2 +#define FIQ_JPEG INT_JPEG +#define FIQ_ISP INT_ISP +#define FIQ_USB INT_USB +#define FIQ_3D INT_3D +#define FIQ_TRANSPOSER INT_TRANSPOSER +#define FIQ_MULTICORESYNC0 INT_MULTICORESYNC0 +#define FIQ_MULTICORESYNC1 INT_MULTICORESYNC1 +#define FIQ_MULTICORESYNC2 INT_MULTICORESYNC2 +#define FIQ_MULTICORESYNC3 INT_MULTICORESYNC3 +#define FIQ_DMA0 INT_DMA0 +#define FIQ_DMA1 INT_DMA1 +#define FIQ_DMA2 INT_DMA2 +#define FIQ_DMA3 INT_DMA3 +#define FIQ_DMA4 INT_DMA4 +#define FIQ_DMA5 INT_DMA5 +#define FIQ_DMA6 INT_DMA6 +#define FIQ_DMA7 INT_DMA7 +#define FIQ_DMA8 INT_DMA8 +#define FIQ_DMA9 INT_DMA9 +#define FIQ_DMA10 INT_DMA10 +#define FIQ_DMA11 INT_DMA11 +#define FIQ_DMA12 INT_DMA12 +#define FIQ_AUX INT_AUX +#define FIQ_ARM INT_ARM +#define FIQ_VPUDMA INT_VPUDMA +#define FIQ_HOSTPORT INT_HOSTPORT +#define FIQ_VIDEOSCALER INT_VIDEOSCALER +#define FIQ_CCP2TX INT_CCP2TX +#define FIQ_SDC INT_SDC +#define FIQ_DSI0 INT_DSI0 +#define FIQ_AVE INT_AVE +#define FIQ_CAM0 INT_CAM0 +#define FIQ_CAM1 INT_CAM1 +#define FIQ_HDMI0 INT_HDMI0 +#define FIQ_HDMI1 INT_HDMI1 +#define FIQ_PIXELVALVE1 INT_PIXELVALVE1 +#define FIQ_I2CSPISLV INT_I2CSPISLV +#define FIQ_DSI1 INT_DSI1 +#define FIQ_PWA0 INT_PWA0 +#define FIQ_PWA1 INT_PWA1 +#define FIQ_CPR INT_CPR +#define FIQ_SMI INT_SMI +#define FIQ_GPIO0 INT_GPIO0 +#define FIQ_GPIO1 INT_GPIO1 +#define FIQ_GPIO2 INT_GPIO2 +#define FIQ_GPIO3 INT_GPIO3 +#define FIQ_I2C INT_I2C +#define FIQ_SPI INT_SPI +#define FIQ_I2SPCM INT_I2SPCM +#define FIQ_SDIO INT_SDIO +#define FIQ_UART INT_UART +#define FIQ_SLIMBUS INT_SLIMBUS +#define FIQ_VEC INT_VEC +#define FIQ_CPG INT_CPG +#define FIQ_RNG INT_RNG +#define FIQ_ARASANSDIO INT_ARASANSDIO +#define FIQ_AVSPMON INT_AVSPMON + +#define FIQ_ARM_TIMER INT_ARM_TIMER +#define FIQ_ARM_MAILBOX INT_ARM_MAILBOX +#define FIQ_ARM_DOORBELL_0 INT_ARM_DOORBELL_0 +#define FIQ_ARM_DOORBELL_1 INT_ARM_DOORBELL_1 +#define FIQ_VPU0_HALTED INT_VPU0_HALTED +#define FIQ_VPU1_HALTED INT_VPU1_HALTED +#define FIQ_ILLEGAL_TYPE0 INT_ILLEGAL_TYPE0 +#define FIQ_ILLEGAL_TYPE1 INT_ILLEGAL_TYPE1 +#define FIQ_PENDING1 INT_PENDING1 +#define FIQ_PENDING2 INT_PENDING2 + +#define HARD_IRQS (64 + 21) +#define GPIO_IRQ_START HARD_IRQS + +#define GPIO_IRQS 32*5 + +#define NR_IRQS HARD_IRQS+GPIO_IRQS + + +#endif /* _BCM2708_IRQS_H_ */ diff --git a/arch/arm/mach-bcm2708/include/mach/memory.h b/arch/arm/mach-bcm2708/include/mach/memory.h new file mode 100644 index 0000000..521540d --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/memory.h @@ -0,0 +1,57 @@ +/* + * arch/arm/mach-bcm2708/include/mach/memory.h + * + * Copyright (C) 2010 Broadcom + * + * 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 __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +/* Memory overview: + + [ARMcore] <--virtual addr--> + [ARMmmu] <--physical addr--> + [GERTmap] <--bus add--> + [VCperiph] + +*/ + +/* + * Physical DRAM offset. + */ +#define PLAT_PHYS_OFFSET UL(0x00000000) +#define VC_ARMMEM_OFFSET UL(0x00000000) /* offset in VC of ARM memory */ + +#ifdef CONFIG_BCM2708_NOL2CACHE + #define _REAL_BUS_OFFSET UL(0xC0000000) /* don't use L1 or L2 caches */ +#else + #define _REAL_BUS_OFFSET UL(0x40000000) /* use L2 cache */ +#endif + +/* We're using the memory at 64M in the VideoCore for Linux - this adjustment + * will provide the offset into this area as well as setting the bits that + * stop the L1 and L2 cache from being used + * + * WARNING: this only works because the ARM is given memory at a fixed location + * (ARMMEM_OFFSET) + */ +#define BUS_OFFSET (VC_ARMMEM_OFFSET + _REAL_BUS_OFFSET) +#define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET)) +#define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET)) +#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - PLAT_PHYS_OFFSET)) +#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - PLAT_PHYS_OFFSET)) + +#endif diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h new file mode 100644 index 0000000..110ce07 --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/platform.h @@ -0,0 +1,220 @@ +/* + * arch/arm/mach-bcm2708/include/mach/platform.h + * + * Copyright (C) 2010 Broadcom + * + * 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 _BCM2708_PLATFORM_H +#define _BCM2708_PLATFORM_H + + +/* macros to get at IO space when running virtually */ +#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) + +#define __io_address(n) IOMEM(IO_ADDRESS(n)) + + +/* + * SDRAM + */ +#define BCM2708_SDRAM_BASE 0x00000000 + +/* + * Logic expansion modules + * + */ + + +/* ------------------------------------------------------------------------ + * BCM2708 ARMCTRL Registers + * ------------------------------------------------------------------------ + */ + +#define HW_REGISTER_RW(addr) (addr) +#define HW_REGISTER_RO(addr) (addr) + +#include "arm_control.h" +#undef ARM_BASE + +/* + * Definitions and addresses for the ARM CONTROL logic + * This file is manually generated. + */ + +#define BCM2708_PERI_BASE 0x20000000 +#define ST_BASE (BCM2708_PERI_BASE + 0x3000) /* System Timer */ +#define DMA_BASE (BCM2708_PERI_BASE + 0x7000) /* DMA controller */ +#define ARM_BASE (BCM2708_PERI_BASE + 0xB000) /* BCM2708 ARM control block */ +#define PM_BASE (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */ +#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */ +#define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */ +#define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */ +#define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */ +#define EMMC_BASE (BCM2708_PERI_BASE + 0x300000) /* eMMC interface */ +#define SMI_BASE (BCM2708_PERI_BASE + 0x600000) /* SMI */ +#define USB_BASE (BCM2708_PERI_BASE + 0x980000) /* DTC_OTG USB controller */ +#define MCORE_BASE (BCM2708_PERI_BASE + 0x0000) /* Fake frame buffer device (actually the multicore sync block*/ + +#define ARMCTRL_BASE (ARM_BASE + 0x000) +#define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */ +#define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */ +#define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */ + + +/* + * Interrupt assignments + */ + +#define ARM_IRQ1_BASE 0 +#define INTERRUPT_TIMER0 (ARM_IRQ1_BASE + 0) +#define INTERRUPT_TIMER1 (ARM_IRQ1_BASE + 1) +#define INTERRUPT_TIMER2 (ARM_IRQ1_BASE + 2) +#define INTERRUPT_TIMER3 (ARM_IRQ1_BASE + 3) +#define INTERRUPT_CODEC0 (ARM_IRQ1_BASE + 4) +#define INTERRUPT_CODEC1 (ARM_IRQ1_BASE + 5) +#define INTERRUPT_CODEC2 (ARM_IRQ1_BASE + 6) +#define INTERRUPT_VC_JPEG (ARM_IRQ1_BASE + 7) +#define INTERRUPT_ISP (ARM_IRQ1_BASE + 8) +#define INTERRUPT_VC_USB (ARM_IRQ1_BASE + 9) +#define INTERRUPT_VC_3D (ARM_IRQ1_BASE + 10) +#define INTERRUPT_TRANSPOSER (ARM_IRQ1_BASE + 11) +#define INTERRUPT_MULTICORESYNC0 (ARM_IRQ1_BASE + 12) +#define INTERRUPT_MULTICORESYNC1 (ARM_IRQ1_BASE + 13) +#define INTERRUPT_MULTICORESYNC2 (ARM_IRQ1_BASE + 14) +#define INTERRUPT_MULTICORESYNC3 (ARM_IRQ1_BASE + 15) +#define INTERRUPT_DMA0 (ARM_IRQ1_BASE + 16) +#define INTERRUPT_DMA1 (ARM_IRQ1_BASE + 17) +#define INTERRUPT_VC_DMA2 (ARM_IRQ1_BASE + 18) +#define INTERRUPT_VC_DMA3 (ARM_IRQ1_BASE + 19) +#define INTERRUPT_DMA4 (ARM_IRQ1_BASE + 20) +#define INTERRUPT_DMA5 (ARM_IRQ1_BASE + 21) +#define INTERRUPT_DMA6 (ARM_IRQ1_BASE + 22) +#define INTERRUPT_DMA7 (ARM_IRQ1_BASE + 23) +#define INTERRUPT_DMA8 (ARM_IRQ1_BASE + 24) +#define INTERRUPT_DMA9 (ARM_IRQ1_BASE + 25) +#define INTERRUPT_DMA10 (ARM_IRQ1_BASE + 26) +#define INTERRUPT_DMA11 (ARM_IRQ1_BASE + 27) +#define INTERRUPT_DMA12 (ARM_IRQ1_BASE + 28) +#define INTERRUPT_AUX (ARM_IRQ1_BASE + 29) +#define INTERRUPT_ARM (ARM_IRQ1_BASE + 30) +#define INTERRUPT_VPUDMA (ARM_IRQ1_BASE + 31) + +#define ARM_IRQ2_BASE 32 +#define INTERRUPT_HOSTPORT (ARM_IRQ2_BASE + 0) +#define INTERRUPT_VIDEOSCALER (ARM_IRQ2_BASE + 1) +#define INTERRUPT_CCP2TX (ARM_IRQ2_BASE + 2) +#define INTERRUPT_SDC (ARM_IRQ2_BASE + 3) +#define INTERRUPT_DSI0 (ARM_IRQ2_BASE + 4) +#define INTERRUPT_AVE (ARM_IRQ2_BASE + 5) +#define INTERRUPT_CAM0 (ARM_IRQ2_BASE + 6) +#define INTERRUPT_CAM1 (ARM_IRQ2_BASE + 7) +#define INTERRUPT_HDMI0 (ARM_IRQ2_BASE + 8) +#define INTERRUPT_HDMI1 (ARM_IRQ2_BASE + 9) +#define INTERRUPT_PIXELVALVE1 (ARM_IRQ2_BASE + 10) +#define INTERRUPT_I2CSPISLV (ARM_IRQ2_BASE + 11) +#define INTERRUPT_DSI1 (ARM_IRQ2_BASE + 12) +#define INTERRUPT_PWA0 (ARM_IRQ2_BASE + 13) +#define INTERRUPT_PWA1 (ARM_IRQ2_BASE + 14) +#define INTERRUPT_CPR (ARM_IRQ2_BASE + 15) +#define INTERRUPT_SMI (ARM_IRQ2_BASE + 16) +#define INTERRUPT_GPIO0 (ARM_IRQ2_BASE + 17) +#define INTERRUPT_GPIO1 (ARM_IRQ2_BASE + 18) +#define INTERRUPT_GPIO2 (ARM_IRQ2_BASE + 19) +#define INTERRUPT_GPIO3 (ARM_IRQ2_BASE + 20) +#define INTERRUPT_VC_I2C (ARM_IRQ2_BASE + 21) +#define INTERRUPT_VC_SPI (ARM_IRQ2_BASE + 22) +#define INTERRUPT_VC_I2SPCM (ARM_IRQ2_BASE + 23) +#define INTERRUPT_VC_SDIO (ARM_IRQ2_BASE + 24) +#define INTERRUPT_VC_UART (ARM_IRQ2_BASE + 25) +#define INTERRUPT_SLIMBUS (ARM_IRQ2_BASE + 26) +#define INTERRUPT_VEC (ARM_IRQ2_BASE + 27) +#define INTERRUPT_CPG (ARM_IRQ2_BASE + 28) +#define INTERRUPT_RNG (ARM_IRQ2_BASE + 29) +#define INTERRUPT_VC_ARASANSDIO (ARM_IRQ2_BASE + 30) +#define INTERRUPT_AVSPMON (ARM_IRQ2_BASE + 31) + +#define ARM_IRQ0_BASE 64 +#define INTERRUPT_ARM_TIMER (ARM_IRQ0_BASE + 0) +#define INTERRUPT_ARM_MAILBOX (ARM_IRQ0_BASE + 1) +#define INTERRUPT_ARM_DOORBELL_0 (ARM_IRQ0_BASE + 2) +#define INTERRUPT_ARM_DOORBELL_1 (ARM_IRQ0_BASE + 3) +#define INTERRUPT_VPU0_HALTED (ARM_IRQ0_BASE + 4) +#define INTERRUPT_VPU1_HALTED (ARM_IRQ0_BASE + 5) +#define INTERRUPT_ILLEGAL_TYPE0 (ARM_IRQ0_BASE + 6) +#define INTERRUPT_ILLEGAL_TYPE1 (ARM_IRQ0_BASE + 7) +#define INTERRUPT_PENDING1 (ARM_IRQ0_BASE + 8) +#define INTERRUPT_PENDING2 (ARM_IRQ0_BASE + 9) +#define INTERRUPT_JPEG (ARM_IRQ0_BASE + 10) +#define INTERRUPT_USB (ARM_IRQ0_BASE + 11) +#define INTERRUPT_3D (ARM_IRQ0_BASE + 12) +#define INTERRUPT_DMA2 (ARM_IRQ0_BASE + 13) +#define INTERRUPT_DMA3 (ARM_IRQ0_BASE + 14) +#define INTERRUPT_I2C (ARM_IRQ0_BASE + 15) +#define INTERRUPT_SPI (ARM_IRQ0_BASE + 16) +#define INTERRUPT_I2SPCM (ARM_IRQ0_BASE + 17) +#define INTERRUPT_SDIO (ARM_IRQ0_BASE + 18) +#define INTERRUPT_UART (ARM_IRQ0_BASE + 19) +#define INTERRUPT_ARASANSDIO (ARM_IRQ0_BASE + 20) + +#define MAXIRQNUM (32 + 32 + 20) +#define MAXFIQNUM (32 + 32 + 20) + +#define MAX_TIMER 2 +#define MAX_PERIOD 699050 +#define TICKS_PER_uSEC 1 + +/* + * These are useconds NOT ticks. + * + */ +#define mSEC_1 1000 +#define mSEC_5 (mSEC_1 * 5) +#define mSEC_10 (mSEC_1 * 10) +#define mSEC_25 (mSEC_1 * 25) +#define SEC_1 (mSEC_1 * 1000) + +/* + * Watchdog + */ +#define PM_RSTC (PM_BASE+0x1c) +#define PM_RSTS (PM_BASE+0x20) +#define PM_WDOG (PM_BASE+0x24) + +#define PM_WDOG_RESET 0000000000 +#define PM_PASSWORD 0x5a000000 +#define PM_WDOG_TIME_SET 0x000fffff +#define PM_RSTC_WRCFG_CLR 0xffffffcf +#define PM_RSTC_WRCFG_SET 0x00000030 +#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 +#define PM_RSTC_RESET 0x00000102 + +#define PM_RSTS_HADPOR_SET 0x00001000 +#define PM_RSTS_HADSRH_SET 0x00000400 +#define PM_RSTS_HADSRF_SET 0x00000200 +#define PM_RSTS_HADSRQ_SET 0x00000100 +#define PM_RSTS_HADWRH_SET 0x00000040 +#define PM_RSTS_HADWRF_SET 0x00000020 +#define PM_RSTS_HADWRQ_SET 0x00000010 +#define PM_RSTS_HADDRH_SET 0x00000004 +#define PM_RSTS_HADDRF_SET 0x00000002 +#define PM_RSTS_HADDRQ_SET 0x00000001 + +#define UART0_CLOCK 3000000 + +#endif + +/* END */ diff --git a/arch/arm/mach-bcm2708/include/mach/power.h b/arch/arm/mach-bcm2708/include/mach/power.h new file mode 100644 index 0000000..52b3b02 --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/power.h @@ -0,0 +1,26 @@ +/* + * linux/arch/arm/mach-bcm2708/power.h + * + * Copyright (C) 2010 Broadcom + * + * 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 device provides a shared mechanism for controlling the power to + * VideoCore subsystems. + */ + +#ifndef _MACH_BCM2708_POWER_H +#define _MACH_BCM2708_POWER_H + +#include +#include + +typedef unsigned int BCM_POWER_HANDLE_T; + +extern int bcm_power_open(BCM_POWER_HANDLE_T *handle); +extern int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request); +extern int bcm_power_close(BCM_POWER_HANDLE_T handle); + +#endif diff --git a/arch/arm/mach-bcm2708/include/mach/system.h b/arch/arm/mach-bcm2708/include/mach/system.h new file mode 100644 index 0000000..2d0b821 --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/system.h @@ -0,0 +1,38 @@ +/* + * arch/arm/mach-bcm2708/include/mach/system.h + * + * Copyright (C) 2010 Broadcom + * Copyright (C) 2003 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +#include +#include +#include + +static inline void arch_idle(void) +{ + /* + * This should do all the clock switching + * and wait for interrupt tricks + */ + cpu_do_idle(); +} + +#endif diff --git a/arch/arm/mach-bcm2708/include/mach/timex.h b/arch/arm/mach-bcm2708/include/mach/timex.h new file mode 100644 index 0000000..64a660c --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/timex.h @@ -0,0 +1,23 @@ +/* + * arch/arm/mach-bcm2708/include/mach/timex.h + * + * BCM2708 sysem clock frequency + * + * Copyright (C) 2010 Broadcom + * + * 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 + */ + +#define CLOCK_TICK_RATE (1000000) diff --git a/arch/arm/mach-bcm2708/include/mach/uncompress.h b/arch/arm/mach-bcm2708/include/mach/uncompress.h new file mode 100644 index 0000000..6ff8f94 --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/uncompress.h @@ -0,0 +1,85 @@ +/* + * arch/arm/mach-bcn2708/include/mach/uncompress.h + * + * Copyright (C) 2010 Broadcom + * Copyright (C) 2003 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#define UART_BAUD 115200 + +#define BCM2708_UART_DR __io(UART0_BASE + UART01x_DR) +#define BCM2708_UART_FR __io(UART0_BASE + UART01x_FR) +#define BCM2708_UART_IBRD __io(UART0_BASE + UART011_IBRD) +#define BCM2708_UART_FBRD __io(UART0_BASE + UART011_FBRD) +#define BCM2708_UART_LCRH __io(UART0_BASE + UART011_LCRH) +#define BCM2708_UART_CR __io(UART0_BASE + UART011_CR) + +/* + * This does not append a newline + */ +static inline void putc(int c) +{ + while (__raw_readl(BCM2708_UART_FR) & UART01x_FR_TXFF) + barrier(); + + __raw_writel(c, BCM2708_UART_DR); +} + +static inline void flush(void) +{ + int fr; + + do { + fr = __raw_readl(BCM2708_UART_FR); + barrier(); + } while ((fr & (UART011_FR_TXFE | UART01x_FR_BUSY)) != UART011_FR_TXFE); +} + +static inline void arch_decomp_setup(void) +{ + int temp, div, rem, frac; + + temp = 16 * UART_BAUD; + div = UART0_CLOCK / temp; + rem = UART0_CLOCK % temp; + temp = (8 * rem) / UART_BAUD; + frac = (temp >> 1) + (temp & 1); + + /* Make sure the UART is disabled before we start */ + __raw_writel(0, BCM2708_UART_CR); + + /* Set the baud rate */ + __raw_writel(div, BCM2708_UART_IBRD); + __raw_writel(frac, BCM2708_UART_FBRD); + + /* Set the UART to 8n1, FIFO enabled */ + __raw_writel(UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN, BCM2708_UART_LCRH); + + /* Enable the UART */ + __raw_writel(UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE, + BCM2708_UART_CR); +} + +/* + * nothing to do + */ +#define arch_decomp_wdog() + diff --git a/arch/arm/mach-bcm2708/include/mach/vc_mem.h b/arch/arm/mach-bcm2708/include/mach/vc_mem.h new file mode 100644 index 0000000..d29125b --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/vc_mem.h @@ -0,0 +1,36 @@ +/***************************************************************************** +* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#if !defined( VC_MEM_H ) +#define VC_MEM_H + +#include + +#define VC_MEM_IOC_MAGIC 'v' + +#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long ) +#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int ) +#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int ) +#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int ) + +#if defined( __KERNEL__ ) +#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF + +extern unsigned long mm_vc_mem_phys_addr; +extern unsigned int mm_vc_mem_size; +extern int vc_mem_get_current_size( void ); +#endif + +#endif /* VC_MEM_H */ + diff --git a/arch/arm/mach-bcm2708/include/mach/vcio.h b/arch/arm/mach-bcm2708/include/mach/vcio.h new file mode 100644 index 0000000..b522ba9 --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/vcio.h @@ -0,0 +1,141 @@ +/* + * arch/arm/mach-bcm2708/include/mach/vcio.h + * + * Copyright (C) 2010 Broadcom + * + * 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 _MACH_BCM2708_VCIO_H +#define _MACH_BCM2708_VCIO_H + +/* Routines to handle I/O via the VideoCore "ARM control" registers + * (semaphores, doorbells, mailboxes) + */ + +#define BCM_VCIO_DRIVER_NAME "bcm2708_vcio" + +/* Constants shared with the ARM identifying separate mailbox channels */ +#define MBOX_CHAN_POWER 0 /* for use by the power management interface */ +#define MBOX_CHAN_FB 1 /* for use by the frame buffer */ +#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */ +#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */ +#define MBOX_CHAN_COUNT 9 + +/* Mailbox property tags */ +enum { + VCMSG_PROPERTY_END = 0x00000000, + VCMSG_GET_FIRMWARE_REVISION = 0x00000001, + VCMSG_GET_BOARD_MODEL = 0x00010001, + VCMSG_GET_BOARD_REVISION = 0x00020002, + VCMSG_GET_BOARD_MAC_ADDRESS = 0x00020003, + VCMSG_GET_BOARD_SERIAL = 0x00020004, + VCMSG_GET_ARM_MEMORY = 0x00020005, + VCMSG_GET_VC_MEMORY = 0x00020006, + VCMSG_GET_CLOCKS = 0x00020007, + VCMSG_GET_COMMAND_LINE = 0x00050001, + VCMSG_GET_DMA_CHANNELS = 0x00060001, + VCMSG_GET_POWER_STATE = 0x00020001, + VCMSG_GET_TIMING = 0x00020002, + VCMSG_SET_POWER_STATE = 0x00028001, + VCMSG_GET_CLOCK_STATE = 0x00030001, + VCMSG_SET_CLOCK_STATE = 0x00038001, + VCMSG_GET_CLOCK_RATE = 0x00030002, + VCMSG_SET_CLOCK_RATE = 0x00038002, + VCMSG_GET_VOLTAGE = 0x00030003, + VCMSG_SET_VOLTAGE = 0x00038003, + VCMSG_GET_MAX_CLOCK = 0x00030004, + VCMSG_GET_MAX_VOLTAGE = 0x00030005, + VCMSG_GET_TEMPERATURE = 0x00030006, + VCMSG_GET_MIN_CLOCK = 0x00030007, + VCMSG_GET_MIN_VOLTAGE = 0x00030008, + VCMSG_GET_TURBO = 0x00030009, + VCMSG_SET_TURBO = 0x00038009, + VCMSG_SET_ALLOCATE_BUFFER = 0x00040001, + VCMSG_SET_RELEASE_BUFFER = 0x00048001, + VCMSG_SET_BLANK_SCREEN = 0x00040002, + VCMSG_TST_BLANK_SCREEN = 0x00044002, + VCMSG_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, + VCMSG_TST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, + VCMSG_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, + VCMSG_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, + VCMSG_TST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, + VCMSG_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, + VCMSG_GET_DEPTH = 0x00040005, + VCMSG_TST_DEPTH = 0x00044005, + VCMSG_SET_DEPTH = 0x00048005, + VCMSG_GET_PIXEL_ORDER = 0x00040006, + VCMSG_TST_PIXEL_ORDER = 0x00044006, + VCMSG_SET_PIXEL_ORDER = 0x00048006, + VCMSG_GET_ALPHA_MODE = 0x00040007, + VCMSG_TST_ALPHA_MODE = 0x00044007, + VCMSG_SET_ALPHA_MODE = 0x00048007, + VCMSG_GET_PITCH = 0x00040008, + VCMSG_TST_PITCH = 0x00044008, + VCMSG_SET_PITCH = 0x00048008, + VCMSG_GET_VIRTUAL_OFFSET = 0x00040009, + VCMSG_TST_VIRTUAL_OFFSET = 0x00044009, + VCMSG_SET_VIRTUAL_OFFSET = 0x00048009, + VCMSG_GET_OVERSCAN = 0x0004000a, + VCMSG_TST_OVERSCAN = 0x0004400a, + VCMSG_SET_OVERSCAN = 0x0004800a, + VCMSG_GET_PALETTE = 0x0004000b, + VCMSG_TST_PALETTE = 0x0004400b, + VCMSG_SET_PALETTE = 0x0004800b, + VCMSG_GET_LAYER = 0x0004000c, + VCMSG_TST_LAYER = 0x0004400c, + VCMSG_SET_LAYER = 0x0004800c, + VCMSG_GET_TRANSFORM = 0x0004000d, + VCMSG_TST_TRANSFORM = 0x0004400d, + VCMSG_SET_TRANSFORM = 0x0004800d, +}; + +extern int /*rc*/ bcm_mailbox_read(unsigned chan, uint32_t *data28); +extern int /*rc*/ bcm_mailbox_write(unsigned chan, uint32_t data28); +extern int /*rc*/ bcm_mailbox_property(void *data, int size); + +#include + +/* + * The major device number. We can't rely on dynamic + * registration any more, because ioctls need to know + * it. + */ +#define MAJOR_NUM 100 + +/* + * Set the message of the device driver + */ +#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) +/* + * _IOWR means that we're creating an ioctl command + * number for passing information from a user process + * to the kernel module and from the kernel module to user process + * + * The first arguments, MAJOR_NUM, is the major device + * number we're using. + * + * The second argument is the number of the command + * (there could be several with different meanings). + * + * The third argument is the type we want to get from + * the process to the kernel. + */ + +/* + * The name of the device file + */ +#define DEVICE_FILE_NAME "char_dev" + +#endif diff --git a/arch/arm/mach-bcm2708/include/mach/vmalloc.h b/arch/arm/mach-bcm2708/include/mach/vmalloc.h new file mode 100644 index 0000000..502c617 --- /dev/null +++ b/arch/arm/mach-bcm2708/include/mach/vmalloc.h @@ -0,0 +1,20 @@ +/* + * arch/arm/mach-bcm2708/include/mach/vmalloc.h + * + * Copyright (C) 2010 Broadcom + * + * 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 + */ +#define VMALLOC_END (0xe8000000) diff --git a/arch/arm/mach-bcm2708/power.c b/arch/arm/mach-bcm2708/power.c new file mode 100644 index 0000000..256bf1a --- /dev/null +++ b/arch/arm/mach-bcm2708/power.c @@ -0,0 +1,194 @@ +/* + * linux/arch/arm/mach-bcm2708/power.c + * + * Copyright (C) 2010 Broadcom + * + * 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 device provides a shared mechanism for controlling the power to + * VideoCore subsystems. + */ + +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "bcm2708_power" + +#define BCM_POWER_MAXCLIENTS 4 +#define BCM_POWER_NOCLIENT (1<<31) + +/* Some drivers expect there devices to be permanently powered */ +#define BCM_POWER_ALWAYS_ON (BCM_POWER_USB) + +#if 1 +#define DPRINTK printk +#else +#define DPRINTK if (0) printk +#endif + +struct state_struct { + uint32_t global_request; + uint32_t client_request[BCM_POWER_MAXCLIENTS]; + struct semaphore client_mutex; + struct semaphore mutex; +} g_state; + +int bcm_power_open(BCM_POWER_HANDLE_T *handle) +{ + BCM_POWER_HANDLE_T i; + int ret = -EBUSY; + + down(&g_state.client_mutex); + + for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { + if (g_state.client_request[i] == BCM_POWER_NOCLIENT) { + g_state.client_request[i] = BCM_POWER_NONE; + *handle = i; + ret = 0; + break; + } + } + + up(&g_state.client_mutex); + + DPRINTK("bcm_power_open() -> %d\n", *handle); + + return ret; +} +EXPORT_SYMBOL_GPL(bcm_power_open); + +int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request) +{ + int rc = 0; + + DPRINTK("bcm_power_request(%d, %x)\n", handle, request); + + if ((handle < BCM_POWER_MAXCLIENTS) && + (g_state.client_request[handle] != BCM_POWER_NOCLIENT)) { + if (down_interruptible(&g_state.mutex) != 0) { + DPRINTK("bcm_power_request -> interrupted\n"); + return -EINTR; + } + + if (request != g_state.client_request[handle]) { + uint32_t others_request = 0; + uint32_t global_request; + BCM_POWER_HANDLE_T i; + + for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) { + if (i != handle) + others_request |= + g_state.client_request[i]; + } + others_request &= ~BCM_POWER_NOCLIENT; + + global_request = request | others_request; + if (global_request != g_state.global_request) { + uint32_t actual; + + /* Send a request to VideoCore */ + bcm_mailbox_write(MBOX_CHAN_POWER, + global_request << 4); + + /* Wait for a response during power-up */ + if (global_request & ~g_state.global_request) { + rc = bcm_mailbox_read(MBOX_CHAN_POWER, + &actual); + DPRINTK + ("bcm_mailbox_read -> %08x, %d\n", + actual, rc); + actual >>= 4; + } else { + rc = 0; + actual = global_request; + } + + if (rc == 0) { + if (actual != global_request) { + printk(KERN_ERR + "%s: prev global %x, new global %x, actual %x, request %x, others_request %x\n", + __func__, + g_state.global_request, + global_request, actual, request, others_request); + /* A failure */ + BUG_ON((others_request & actual) + != others_request); + request &= actual; + rc = -EIO; + } + + g_state.global_request = actual; + g_state.client_request[handle] = + request; + } + } + } + up(&g_state.mutex); + } else { + rc = -EINVAL; + } + DPRINTK("bcm_power_request -> %d\n", rc); + return rc; +} +EXPORT_SYMBOL_GPL(bcm_power_request); + +int bcm_power_close(BCM_POWER_HANDLE_T handle) +{ + int rc; + + DPRINTK("bcm_power_close(%d)\n", handle); + + rc = bcm_power_request(handle, BCM_POWER_NONE); + if (rc == 0) + g_state.client_request[handle] = BCM_POWER_NOCLIENT; + + return rc; +} +EXPORT_SYMBOL_GPL(bcm_power_close); + +static int __init bcm_power_init(void) +{ +#if defined(BCM_POWER_ALWAYS_ON) + BCM_POWER_HANDLE_T always_on_handle; +#endif + int rc = 0; + int i; + + printk(KERN_INFO "bcm_power: Broadcom power driver\n"); + bcm_mailbox_write(MBOX_CHAN_POWER, 0); + + for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) + g_state.client_request[i] = BCM_POWER_NOCLIENT; + + sema_init(&g_state.client_mutex, 1); + sema_init(&g_state.mutex, 1); + + g_state.global_request = 0; + +#if defined(BCM_POWER_ALWAYS_ON) + if (BCM_POWER_ALWAYS_ON) { + bcm_power_open(&always_on_handle); + bcm_power_request(always_on_handle, BCM_POWER_ALWAYS_ON); + } +#endif + + return rc; +} + +static void __exit bcm_power_exit(void) +{ + bcm_mailbox_write(MBOX_CHAN_POWER, 0); +} + +arch_initcall(bcm_power_init); /* Initialize early */ +module_exit(bcm_power_exit); + +MODULE_AUTHOR("Phil Elwell"); +MODULE_DESCRIPTION("Interface to BCM2708 power management"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-bcm2708/vc_mem.c b/arch/arm/mach-bcm2708/vc_mem.c new file mode 100644 index 0000000..aeae4d5 --- /dev/null +++ b/arch/arm/mach-bcm2708/vc_mem.c @@ -0,0 +1,462 @@ +/***************************************************************************** +* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2, available at +* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a +* license other than the GPL, without Broadcom's express prior written +* consent. +*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_ARCH_KONA +#include +#elif CONFIG_ARCH_BCM2708 +#else +#include +#endif + +#include "mach/vc_mem.h" +#include + +#define DRIVER_NAME "vc-mem" + +// Uncomment to enable debug logging +// #define ENABLE_DBG + +#if defined(ENABLE_DBG) +#define LOG_DBG( fmt, ... ) printk( KERN_INFO fmt "\n", ##__VA_ARGS__ ) +#else +#define LOG_DBG( fmt, ... ) +#endif +#define LOG_ERR( fmt, ... ) printk( KERN_ERR fmt "\n", ##__VA_ARGS__ ) + +// Device (/dev) related variables +static dev_t vc_mem_devnum = 0; +static struct class *vc_mem_class = NULL; +static struct cdev vc_mem_cdev; +static int vc_mem_inited = 0; + +// Proc entry +static struct proc_dir_entry *vc_mem_proc_entry; + +/* + * Videocore memory addresses and size + * + * Drivers that wish to know the videocore memory addresses and sizes should + * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in + * headers. This allows the other drivers to not be tied down to a a certain + * address/size at compile time. + * + * In the future, the goal is to have the videocore memory virtual address and + * size be calculated at boot time rather than at compile time. The decision of + * where the videocore memory resides and its size would be in the hands of the + * bootloader (and/or kernel). When that happens, the values of these variables + * would be calculated and assigned in the init function. + */ +// in the 2835 VC in mapped above ARM, but ARM has full access to VC space +unsigned long mm_vc_mem_phys_addr = 0x00000000; +unsigned int mm_vc_mem_size = 0; +unsigned int mm_vc_mem_base = 0; + +EXPORT_SYMBOL(mm_vc_mem_phys_addr); +EXPORT_SYMBOL(mm_vc_mem_size); +EXPORT_SYMBOL(mm_vc_mem_base); + +static uint phys_addr = 0; +static uint mem_size = 0; +static uint mem_base = 0; + + +/**************************************************************************** +* +* vc_mem_open +* +***************************************************************************/ + +static int +vc_mem_open(struct inode *inode, struct file *file) +{ + (void) inode; + (void) file; + + LOG_DBG("%s: called file = 0x%p", __func__, file); + + return 0; +} + +/**************************************************************************** +* +* vc_mem_release +* +***************************************************************************/ + +static int +vc_mem_release(struct inode *inode, struct file *file) +{ + (void) inode; + (void) file; + + LOG_DBG("%s: called file = 0x%p", __func__, file); + + return 0; +} + +/**************************************************************************** +* +* vc_mem_get_size +* +***************************************************************************/ + +static void +vc_mem_get_size(void) +{ +} + +/**************************************************************************** +* +* vc_mem_get_base +* +***************************************************************************/ + +static void +vc_mem_get_base(void) +{ +} + +/**************************************************************************** +* +* vc_mem_get_current_size +* +***************************************************************************/ + +int +vc_mem_get_current_size(void) +{ + return mm_vc_mem_size; +} + +EXPORT_SYMBOL_GPL(vc_mem_get_current_size); + +/**************************************************************************** +* +* vc_mem_ioctl +* +***************************************************************************/ + +static long +vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int rc = 0; + + (void) cmd; + (void) arg; + + LOG_DBG("%s: called file = 0x%p", __func__, file); + + switch (cmd) { + case VC_MEM_IOC_MEM_PHYS_ADDR: + { + LOG_DBG("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p", + __func__, (void *) mm_vc_mem_phys_addr); + + if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, + sizeof (mm_vc_mem_phys_addr)) != 0) { + rc = -EFAULT; + } + break; + } + case VC_MEM_IOC_MEM_SIZE: + { + // Get the videocore memory size first + vc_mem_get_size(); + + LOG_DBG("%s: VC_MEM_IOC_MEM_SIZE=%u", __func__, + mm_vc_mem_size); + + if (copy_to_user((void *) arg, &mm_vc_mem_size, + sizeof (mm_vc_mem_size)) != 0) { + rc = -EFAULT; + } + break; + } + case VC_MEM_IOC_MEM_BASE: + { + // Get the videocore memory base + vc_mem_get_base(); + + LOG_DBG("%s: VC_MEM_IOC_MEM_BASE=%u", __func__, + mm_vc_mem_base); + + if (copy_to_user((void *) arg, &mm_vc_mem_base, + sizeof (mm_vc_mem_base)) != 0) { + rc = -EFAULT; + } + break; + } + case VC_MEM_IOC_MEM_LOAD: + { + // Get the videocore memory base + vc_mem_get_base(); + + LOG_DBG("%s: VC_MEM_IOC_MEM_LOAD=%u", __func__, + mm_vc_mem_base); + + if (copy_to_user((void *) arg, &mm_vc_mem_base, + sizeof (mm_vc_mem_base)) != 0) { + rc = -EFAULT; + } + break; + } + default: + { + return -ENOTTY; + } + } + LOG_DBG("%s: file = 0x%p returning %d", __func__, file, rc); + + return rc; +} + +/**************************************************************************** +* +* vc_mem_mmap +* +***************************************************************************/ + +static int +vc_mem_mmap(struct file *filp, struct vm_area_struct *vma) +{ + int rc = 0; + unsigned long length = vma->vm_end - vma->vm_start; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + + LOG_DBG("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx", + __func__, (long) vma->vm_start, (long) vma->vm_end, + (long) vma->vm_pgoff); + + if (offset + length > mm_vc_mem_size) { + LOG_ERR("%s: length %ld is too big", __func__, length); + return -EINVAL; + } + // Do not cache the memory map + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + rc = remap_pfn_range(vma, vma->vm_start, + (mm_vc_mem_phys_addr >> PAGE_SHIFT) + + vma->vm_pgoff, length, vma->vm_page_prot); + if (rc != 0) { + LOG_ERR("%s: remap_pfn_range failed (rc=%d)", __func__, rc); + } + + return rc; +} + +/**************************************************************************** +* +* File Operations for the driver. +* +***************************************************************************/ + +static const struct file_operations vc_mem_fops = { + .owner = THIS_MODULE, + .open = vc_mem_open, + .release = vc_mem_release, + .unlocked_ioctl = vc_mem_ioctl, + .mmap = vc_mem_mmap, +}; + +/**************************************************************************** +* +* vc_mem_proc_read +* +***************************************************************************/ + +static int +vc_mem_proc_read(char *buf, char **start, off_t offset, int count, int *eof, + void *data) +{ + char *p = buf; + + (void) start; + (void) count; + (void) data; + + if (offset > 0) { + *eof = 1; + return 0; + } + // Get the videocore memory size first + vc_mem_get_size(); + + p += sprintf(p, "Videocore memory:\n"); + if (mm_vc_mem_phys_addr != 0) + p += sprintf(p, " Physical address: 0x%p\n", + (void *) mm_vc_mem_phys_addr); + else + p += sprintf(p, " Physical address: 0x00000000\n"); + p += sprintf(p, " Length (bytes): %u\n", mm_vc_mem_size); + + *eof = 1; + return p - buf; +} + +/**************************************************************************** +* +* vc_mem_proc_write +* +***************************************************************************/ + +static int +vc_mem_proc_write(struct file *file, const char __user * buffer, + unsigned long count, void *data) +{ + int rc = -EFAULT; + char input_str[10]; + + memset(input_str, 0, sizeof (input_str)); + + if (count > sizeof (input_str)) { + LOG_ERR("%s: input string length too long", __func__); + goto out; + } + + if (copy_from_user(input_str, buffer, count - 1)) { + LOG_ERR("%s: failed to get input string", __func__); + goto out; + } + + if (strncmp(input_str, "connect", strlen("connect")) == 0) { + // Get the videocore memory size from the videocore + vc_mem_get_size(); + } + + out: + return rc; +} + +/**************************************************************************** +* +* vc_mem_init +* +***************************************************************************/ + +static int __init +vc_mem_init(void) +{ + int rc = -EFAULT; + struct device *dev; + + LOG_DBG("%s: called", __func__); + + mm_vc_mem_phys_addr = phys_addr; + mm_vc_mem_size = mem_size; + mm_vc_mem_base = mem_base; + + vc_mem_get_size(); + + printk("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", + mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); + + if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { + LOG_ERR("%s: alloc_chrdev_region failed (rc=%d)", __func__, rc); + goto out_err; + } + + cdev_init(&vc_mem_cdev, &vc_mem_fops); + if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { + LOG_ERR("%s: cdev_add failed (rc=%d)", __func__, rc); + goto out_unregister; + } + + vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); + if (IS_ERR(vc_mem_class)) { + rc = PTR_ERR(vc_mem_class); + LOG_ERR("%s: class_create failed (rc=%d)", __func__, rc); + goto out_cdev_del; + } + + dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL, + DRIVER_NAME); + if (IS_ERR(dev)) { + rc = PTR_ERR(dev); + LOG_ERR("%s: device_create failed (rc=%d)", __func__, rc); + goto out_class_destroy; + } + +#if 0 + vc_mem_proc_entry = create_proc_entry(DRIVER_NAME, 0444, NULL); + if (vc_mem_proc_entry == NULL) { + rc = -EFAULT; + LOG_ERR("%s: create_proc_entry failed", __func__); + goto out_device_destroy; + } + vc_mem_proc_entry->read_proc = vc_mem_proc_read; + vc_mem_proc_entry->write_proc = vc_mem_proc_write; +#endif + + vc_mem_inited = 1; + return 0; + + out_device_destroy: + device_destroy(vc_mem_class, vc_mem_devnum); + + out_class_destroy: + class_destroy(vc_mem_class); + vc_mem_class = NULL; + + out_cdev_del: + cdev_del(&vc_mem_cdev); + + out_unregister: + unregister_chrdev_region(vc_mem_devnum, 1); + + out_err: + return -1; +} + +/**************************************************************************** +* +* vc_mem_exit +* +***************************************************************************/ + +static void __exit +vc_mem_exit(void) +{ + LOG_DBG("%s: called", __func__); + + if (vc_mem_inited) { +#if 0 + remove_proc_entry(vc_mem_proc_entry->name, NULL); +#endif + device_destroy(vc_mem_class, vc_mem_devnum); + class_destroy(vc_mem_class); + cdev_del(&vc_mem_cdev); + unregister_chrdev_region(vc_mem_devnum, 1); + } +} + +module_init(vc_mem_init); +module_exit(vc_mem_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Broadcom Corporation"); + +module_param(phys_addr, uint, 0644); +module_param(mem_size, uint, 0644); +module_param(mem_base, uint, 0644); + diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c new file mode 100644 index 0000000..599eb63 --- /dev/null +++ b/arch/arm/mach-bcm2708/vcio.c @@ -0,0 +1,474 @@ +/* + * linux/arch/arm/mach-bcm2708/vcio.c + * + * Copyright (C) 2010 Broadcom + * + * 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 device provides a shared mechanism for writing to the mailboxes, + * semaphores, doorbells etc. that are shared between the ARM and the + * VideoCore processor + */ + +#if defined(CONFIG_SERIAL_BCM_MBOX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + + +#define DRIVER_NAME BCM_VCIO_DRIVER_NAME + +/* ---------------------------------------------------------------------- + * Mailbox + * -------------------------------------------------------------------- */ + +/* offsets from a mail box base address */ +#define MAIL_WRT 0x00 /* write - and next 4 words */ +#define MAIL_RD 0x00 /* read - and next 4 words */ +#define MAIL_POL 0x10 /* read without popping the fifo */ +#define MAIL_SND 0x14 /* sender ID (bottom two bits) */ +#define MAIL_STA 0x18 /* status */ +#define MAIL_CNF 0x1C /* configuration */ + +#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) +#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) +#define MBOX_CHAN(msg) ((msg) & 0xf) +#define MBOX_DATA28(msg) ((msg) & ~0xf) +#define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) + +#define MBOX_MAGIC 0xd0d0c0de + +struct vc_mailbox { + struct device *dev; /* parent device */ + void __iomem *status; + void __iomem *config; + void __iomem *read; + void __iomem *write; + uint32_t msg[MBOX_CHAN_COUNT]; + struct semaphore sema[MBOX_CHAN_COUNT]; + uint32_t magic; +}; + +static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, + uint32_t addr_mbox) +{ + int i; + + mbox_out->dev = dev; + mbox_out->status = __io_address(addr_mbox + MAIL_STA); + mbox_out->config = __io_address(addr_mbox + MAIL_CNF); + mbox_out->read = __io_address(addr_mbox + MAIL_RD); + /* Write to the other mailbox */ + mbox_out->write = + __io_address((addr_mbox ^ ARM_0_MAIL0_WRT ^ ARM_0_MAIL1_WRT) + + MAIL_WRT); + + for (i = 0; i < MBOX_CHAN_COUNT; i++) { + mbox_out->msg[i] = 0; + sema_init(&mbox_out->sema[i], 0); + } + + /* Enable the interrupt on data reception */ + writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->config); + + mbox_out->magic = MBOX_MAGIC; +} + +static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) +{ + int rc; + + if (mbox->magic != MBOX_MAGIC) + rc = -EINVAL; + else { + /* wait for the mailbox FIFO to have some space in it */ + while (0 != (readl(mbox->status) & ARM_MS_FULL)) + cpu_relax(); + + writel(MBOX_MSG(chan, data28), mbox->write); + rc = 0; + } + return rc; +} + +static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) +{ + int rc; + + if (mbox->magic != MBOX_MAGIC) + rc = -EINVAL; + else { + down(&mbox->sema[chan]); + *data28 = MBOX_DATA28(mbox->msg[chan]); + mbox->msg[chan] = 0; + rc = 0; + } + return rc; +} + +static irqreturn_t mbox_irq(int irq, void *dev_id) +{ + /* wait for the mailbox FIFO to have some data in it */ + struct vc_mailbox *mbox = (struct vc_mailbox *) dev_id; + int status = readl(mbox->status); + int ret = IRQ_NONE; + + while (!(status & ARM_MS_EMPTY)) { + uint32_t msg = readl(mbox->read); + int chan = MBOX_CHAN(msg); + if (chan < MBOX_CHAN_COUNT) { + if (mbox->msg[chan]) { + /* Overflow */ + printk(KERN_ERR DRIVER_NAME + ": mbox chan %d overflow - drop %08x\n", + chan, msg); + } else { + mbox->msg[chan] = (msg | 0xf); + up(&mbox->sema[chan]); + } + } else { + printk(KERN_ERR DRIVER_NAME + ": invalid channel selector (msg %08x)\n", msg); + } + ret = IRQ_HANDLED; + status = readl(mbox->status); + } + return ret; +} + +static struct irqaction mbox_irqaction = { + .name = "ARM Mailbox IRQ", + .flags = IRQF_DISABLED | IRQF_IRQPOLL, + .handler = mbox_irq, +}; + +/* ---------------------------------------------------------------------- + * Mailbox Methods + * -------------------------------------------------------------------- */ + +static struct device *mbox_dev; /* we assume there's only one! */ + +static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) +{ + int rc; + + struct vc_mailbox *mailbox = dev_get_drvdata(dev); + device_lock(dev); + rc = mbox_write(mailbox, chan, data28); + device_unlock(dev); + + return rc; +} + +static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) +{ + int rc; + + struct vc_mailbox *mailbox = dev_get_drvdata(dev); + device_lock(dev); + rc = mbox_read(mailbox, chan, data28); + device_unlock(dev); + + return rc; +} + +extern int bcm_mailbox_write(unsigned chan, uint32_t data28) +{ + if (mbox_dev) + return dev_mbox_write(mbox_dev, chan, data28); + else + return -ENODEV; +} +EXPORT_SYMBOL_GPL(bcm_mailbox_write); + +extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) +{ + if (mbox_dev) + return dev_mbox_read(mbox_dev, chan, data28); + else + return -ENODEV; +} +EXPORT_SYMBOL_GPL(bcm_mailbox_read); + +static void dev_mbox_register(const char *dev_name, struct device *dev) +{ + mbox_dev = dev; +} + +static int mbox_copy_from_user(void *dst, const void *src, int size) +{ + if ( (uint32_t)src < TASK_SIZE) + { + return copy_from_user(dst, src, size); + } + else + { + memcpy( dst, src, size ); + return 0; + } +} + +static int mbox_copy_to_user(void *dst, const void *src, int size) +{ + if ( (uint32_t)dst < TASK_SIZE) + { + return copy_to_user(dst, src, size); + } + else + { + memcpy( dst, src, size ); + return 0; + } +} + +static DEFINE_MUTEX(mailbox_lock); +extern int bcm_mailbox_property(void *data, int size) +{ + uint32_t success; + dma_addr_t mem_bus; /* the memory address accessed from videocore */ + void *mem_kern; /* the memory address accessed from driver */ + int s = 0; + + mutex_lock(&mailbox_lock); + /* allocate some memory for the messages communicating with GPU */ + mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, GFP_ATOMIC); + if (mem_kern) { + /* create the message */ + mbox_copy_from_user(mem_kern, data, size); + + /* send the message */ + wmb(); + s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus); + if (s == 0) { + s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success); + } + if (s == 0) { + /* copy the response */ + rmb(); + mbox_copy_to_user(data, mem_kern, size); + } + dma_free_coherent(NULL, PAGE_ALIGN(size), mem_kern, mem_bus); + } else { + s = -ENOMEM; + } + if (s != 0) + printk(KERN_ERR DRIVER_NAME ": %s failed (%d)\n", __func__, s); + + mutex_unlock(&mailbox_lock); + return s; +} +EXPORT_SYMBOL_GPL(bcm_mailbox_property); + +/* ---------------------------------------------------------------------- + * Platform Device for Mailbox + * -------------------------------------------------------------------- */ + +/* + * Is the device open right now? Used to prevent + * concurent access into the same device + */ +static int Device_Open = 0; + +/* + * This is called whenever a process attempts to open the device file + */ +static int device_open(struct inode *inode, struct file *file) +{ + /* + * We don't want to talk to two processes at the same time + */ + if (Device_Open) + return -EBUSY; + + Device_Open++; + /* + * Initialize the message + */ + try_module_get(THIS_MODULE); + return 0; +} + +static int device_release(struct inode *inode, struct file *file) +{ + /* + * We're now ready for our next caller + */ + Device_Open--; + + module_put(THIS_MODULE); + return 0; +} + +/* + * This function is called whenever a process tries to do an ioctl on our + * device file. We get two extra parameters (additional to the inode and file + * structures, which all device functions get): the number of the ioctl called + * and the parameter given to the ioctl function. + * + * If the ioctl is write or read/write (meaning output is returned to the + * calling process), the ioctl call returns the output of this function. + * + */ +static long device_ioctl(struct file *file, /* see include/linux/fs.h */ + unsigned int ioctl_num, /* number and param for ioctl */ + unsigned long ioctl_param) +{ + unsigned size; + /* + * Switch according to the ioctl called + */ + switch (ioctl_num) { + case IOCTL_MBOX_PROPERTY: + /* + * Receive a pointer to a message (in user space) and set that + * to be the device's message. Get the parameter given to + * ioctl by the process. + */ + mbox_copy_from_user(&size, (void *)ioctl_param, sizeof size); + return bcm_mailbox_property((void *)ioctl_param, size); + break; + default: + printk(KERN_ERR DRIVER_NAME "unknown ioctl: %d\n", ioctl_num); + return -EINVAL; + } + + return 0; +} + +/* Module Declarations */ + +/* + * This structure will hold the functions to be called + * when a process does something to the device we + * created. Since a pointer to this structure is kept in + * the devices table, it can't be local to + * init_module. NULL is for unimplemented functios. + */ +struct file_operations fops = { + .unlocked_ioctl = device_ioctl, + .open = device_open, + .release = device_release, /* a.k.a. close */ +}; + +static int bcm_vcio_probe(struct platform_device *pdev) +{ + int ret = 0; + struct vc_mailbox *mailbox; + + mailbox = kzalloc(sizeof(*mailbox), GFP_KERNEL); + if (NULL == mailbox) { + printk(KERN_ERR DRIVER_NAME ": failed to allocate " + "mailbox memory\n"); + ret = -ENOMEM; + } else { + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " + "resource\n"); + ret = -ENODEV; + kfree(mailbox); + } else { + /* should be based on the registers from res really */ + mbox_init(mailbox, &pdev->dev, ARM_0_MAIL0_RD); + + platform_set_drvdata(pdev, mailbox); + dev_mbox_register(DRIVER_NAME, &pdev->dev); + + mbox_irqaction.dev_id = mailbox; + setup_irq(IRQ_ARM_MAILBOX, &mbox_irqaction); + printk(KERN_INFO DRIVER_NAME ": mailbox at %p\n", + __io_address(ARM_0_MAIL0_RD)); + } + } + + if (ret == 0) { + /* + * Register the character device + */ + ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops); + + /* + * Negative values signify an error + */ + if (ret < 0) { + printk(KERN_ERR DRIVER_NAME + "Failed registering the character device %d\n", ret); + return ret; + } + } + return ret; +} + +static int bcm_vcio_remove(struct platform_device *pdev) +{ + struct vc_mailbox *mailbox = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + kfree(mailbox); + + return 0; +} + +static struct platform_driver bcm_mbox_driver = { + .probe = bcm_vcio_probe, + .remove = bcm_vcio_remove, + + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init bcm_mbox_init(void) +{ + int ret; + + printk(KERN_INFO "mailbox: Broadcom VideoCore Mailbox driver\n"); + + ret = platform_driver_register(&bcm_mbox_driver); + if (ret != 0) { + printk(KERN_ERR DRIVER_NAME ": failed to register " + "on platform\n"); + } + + return ret; +} + +static void __exit bcm_mbox_exit(void) +{ + platform_driver_unregister(&bcm_mbox_driver); +} + +arch_initcall(bcm_mbox_init); /* Initialize early */ +module_exit(bcm_mbox_exit); + +MODULE_AUTHOR("Gray Girling"); +MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:bcm-mbox"); diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index c21082d..6ae2668 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -358,7 +358,7 @@ config CPU_PJ4B # ARMv6 config CPU_V6 - bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX + bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || MACH_BCM2708 select CPU_32v6 select CPU_ABRT_EV6 select CPU_CACHE_V6 diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index d073528..223fc69 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -73,10 +73,19 @@ ENDPROC(cpu_v6_reset) * * IRQs are already disabled. */ + +/* See jira SW-5991 for details of this workaround */ ENTRY(cpu_v6_do_idle) - mov r1, #0 - mcr p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode - mcr p15, 0, r1, c7, c0, 4 @ wait for interrupt + .align 5 + mov r1, #2 +1: subs r1, #1 + nop + mcreq p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode + mcreq p15, 0, r1, c7, c0, 4 @ wait for interrupt + nop + nop + nop + bne 1b mov pc, lr ENTRY(cpu_v6_dcache_clean_area) diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index a10297d..c9ddd87 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -522,6 +522,7 @@ torbreck MACH_TORBRECK TORBRECK 3090 prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103 paz00 MACH_PAZ00 PAZ00 3128 acmenetusfoxg20 MACH_ACMENETUSFOXG20 ACMENETUSFOXG20 3129 +bcm2708 MACH_BCM2708 BCM2708 3138 ag5evm MACH_AG5EVM AG5EVM 3189 ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206 wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207 diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 9ab8f8d..74e7543 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -249,6 +249,27 @@ config MMC_SDHCI_S3C_DMA YMMV. +config MMC_SDHCI_BCM2708 + tristate "SDHCI support on BCM2708" + depends on MMC_SDHCI && MACH_BCM2708 + select MMC_SDHCI_IO_ACCESSORS + help + This selects the Secure Digital Host Controller Interface (SDHCI) + often referrered to as the eMMC block. + + If you have a controller with this interface, say Y or M here. + + If unsure, say N. + +config MMC_SDHCI_BCM2708_DMA + bool "DMA support on BCM2708 Arasan controller" + depends on MMC_SDHCI_BCM2708 + help + Enable DMA support on the Arasan SDHCI controller in Broadcom 2708 + based chips. + + If unsure, say N. + config MMC_SDHCI_BCM2835 tristate "SDHCI platform support for the BCM2835 SD/MMC Controller" depends on ARCH_BCM2835 diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index cd32280..6a7b985 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o +obj-$(CONFIG_MMC_SDHCI_BCM2708) += sdhci-bcm2708.o obj-$(CONFIG_MMC_WBSD) += wbsd.o obj-$(CONFIG_MMC_AU1X) += au1xmmc.o obj-$(CONFIG_MMC_OMAP) += omap.o diff --git a/drivers/mmc/host/sdhci-bcm2708.c b/drivers/mmc/host/sdhci-bcm2708.c new file mode 100644 index 0000000..e79723d --- /dev/null +++ b/drivers/mmc/host/sdhci-bcm2708.c @@ -0,0 +1,1425 @@ +/* + * sdhci-bcm2708.c Support for SDHCI device on BCM2708 + * Copyright (c) 2010 Broadcom + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supports: + * SDHCI platform device - Arasan SD controller in BCM2708 + * + * Inspired by sdhci-pci.c, by Pierre Ossman + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "sdhci.h" + +/*****************************************************************************\ + * * + * Configuration * + * * +\*****************************************************************************/ + +#define DRIVER_NAME "bcm2708_sdhci" + +/* for the time being insist on DMA mode - PIO seems not to work */ +#ifndef CONFIG_MMC_SDHCI_BCM2708_DMA +#warning Non-DMA (PIO) version of this driver currently unavailable +#endif +#undef CONFIG_MMC_SDHCI_BCM2708_DMA +#define CONFIG_MMC_SDHCI_BCM2708_DMA y + +#define USE_SYNC_AFTER_DMA +#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA +/* #define CHECK_DMA_USE */ +#endif +//#define LOG_REGISTERS + +#define USE_SCHED_TIME +#define USE_SPACED_WRITES_2CLK 1 /* space consecutive register writes */ +#define USE_SOFTWARE_TIMEOUTS 1 /* not hardware timeouts */ +#define SOFTWARE_ERASE_TIMEOUT_SEC 30 + +#define SDHCI_BCM_DMA_CHAN 4 /* this default is normally overriden */ +#define SDHCI_BCM_DMA_WAITS 0 /* delays slowing DMA transfers: 0-31 */ +/* We are worried that SD card DMA use may be blocking the AXI bus for others */ + +/*! TODO: obtain these from the physical address */ +#define DMA_SDHCI_BASE 0x7e300000 /* EMMC register block on Videocore */ +#define DMA_SDHCI_BUFFER (DMA_SDHCI_BASE + SDHCI_BUFFER) + +#define BCM2708_SDHCI_SLEEP_TIMEOUT 1000 /* msecs */ + +/* Mhz clock that the EMMC core is running at. Should match the platform clockman settings */ +#define BCM2708_EMMC_CLOCK_FREQ 80000000 + +/*****************************************************************************\ + * * + * Debug * + * * +\*****************************************************************************/ + + + +#define DBG(f, x...) \ + pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x) +// printk(KERN_INFO DRIVER_NAME " [%s()]: " f, __func__,## x)//GRAYG + + +/*****************************************************************************\ + * * + * High Precision Time * + * * +\*****************************************************************************/ + +#ifdef USE_SCHED_TIME + +#include + +typedef unsigned long hptime_t; + +#define FMT_HPT "lu" + +static inline hptime_t hptime(void) +{ + return frc_clock_ticks32(); +} + +#define HPTIME_CLK_NS 1000ul + +#else + +typedef unsigned long hptime_t; + +#define FMT_HPT "lu" + +static inline hptime_t hptime(void) +{ + return jiffies; +} + +#define HPTIME_CLK_NS (1000000000ul/HZ) + +#endif + +static inline unsigned long int since_ns(hptime_t t) +{ + return (unsigned long)((hptime() - t) * HPTIME_CLK_NS); +} + +#if 0 +static void hptime_test(void) +{ + hptime_t now; + hptime_t later; + + now = hptime(); + msleep(10); + later = hptime(); + + printk(KERN_INFO DRIVER_NAME": 10ms = %"FMT_HPT" clks " + "(from %"FMT_HPT" to %"FMT_HPT") = %luns\n", + later-now, now, later, + (unsigned long)(HPTIME_CLK_NS * (later - now))); + + now = hptime(); + msleep(1000); + later = hptime(); + + printk(KERN_INFO DRIVER_NAME": 1s = %"FMT_HPT" clks " + "(from %"FMT_HPT" to %"FMT_HPT") = %luns\n", + later-now, now, later, + (unsigned long)(HPTIME_CLK_NS * (later - now))); +} +#endif + +/*****************************************************************************\ + * * + * SDHCI core callbacks * + * * +\*****************************************************************************/ + + +#ifdef CHECK_DMA_USE +/*#define CHECK_DMA_REG_USE*/ +#endif + +#ifdef CHECK_DMA_REG_USE +/* we don't expect anything to be using these registers during a + DMA (except the IRQ status) - so check */ +static void check_dma_reg_use(struct sdhci_host *host, int reg); +#else +#define check_dma_reg_use(host, reg) +#endif + + +static inline u32 sdhci_bcm2708_raw_readl(struct sdhci_host *host, int reg) +{ + return readl(host->ioaddr + reg); +} + +u32 sdhci_bcm2708_readl(struct sdhci_host *host, int reg) +{ + u32 l = sdhci_bcm2708_raw_readl(host, reg); + +#ifdef LOG_REGISTERS + printk(KERN_ERR "%s: readl from 0x%02x, value 0x%08x\n", + mmc_hostname(host->mmc), reg, l); +#endif + check_dma_reg_use(host, reg); + + return l; +} + +u16 sdhci_bcm2708_readw(struct sdhci_host *host, int reg) +{ + u32 l = sdhci_bcm2708_raw_readl(host, reg & ~3); + u32 w = l >> (reg << 3 & 0x18) & 0xffff; + +#ifdef LOG_REGISTERS + printk(KERN_ERR "%s: readw from 0x%02x, value 0x%04x\n", + mmc_hostname(host->mmc), reg, w); +#endif + check_dma_reg_use(host, reg); + + return (u16)w; +} + +u8 sdhci_bcm2708_readb(struct sdhci_host *host, int reg) +{ + u32 l = sdhci_bcm2708_raw_readl(host, reg & ~3); + u32 b = l >> (reg << 3 & 0x18) & 0xff; + +#ifdef LOG_REGISTERS + printk(KERN_ERR "%s: readb from 0x%02x, value 0x%02x\n", + mmc_hostname(host->mmc), reg, b); +#endif + check_dma_reg_use(host, reg); + + return (u8)b; +} + + +static void sdhci_bcm2708_raw_writel(struct sdhci_host *host, u32 val, int reg) +{ + u32 ier; + +#if USE_SPACED_WRITES_2CLK + static bool timeout_disabled = false; + unsigned int ns_2clk = 0; + + /* The Arasan has a bugette whereby it may lose the content of + * successive writes to registers that are within two SD-card clock + * cycles of each other (a clock domain crossing problem). + * It seems, however, that the data register does not have this problem. + * (Which is just as well - otherwise we'd have to nobble the DMA engine + * too) + */ + if (reg != SDHCI_BUFFER && host->clock != 0) { + /* host->clock is the clock freq in Hz */ + static hptime_t last_write_hpt; + hptime_t now = hptime(); + ns_2clk = 2000000000/host->clock; + + if (now == last_write_hpt || now == last_write_hpt+1) { + /* we can't guarantee any significant time has + * passed - we'll have to wait anyway ! */ + udelay((ns_2clk+1000-1)/1000); + } else + { + /* we must have waited at least this many ns: */ + unsigned int ns_wait = HPTIME_CLK_NS * + (last_write_hpt - now - 1); + if (ns_wait < ns_2clk) + udelay((ns_2clk-ns_wait+500)/1000); + } + last_write_hpt = now; + } +#if USE_SOFTWARE_TIMEOUTS + /* The Arasan is clocked for timeouts using the SD clock which is too + * fast for ERASE commands and causes issues. So we disable timeouts + * for ERASE */ + if (host->cmd != NULL && host->cmd->opcode == MMC_ERASE && + reg == (SDHCI_COMMAND & ~3)) { + mod_timer(&host->timer, + jiffies + SOFTWARE_ERASE_TIMEOUT_SEC * HZ); + ier = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE); + ier &= ~SDHCI_INT_DATA_TIMEOUT; + writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE); + timeout_disabled = true; + udelay((ns_2clk+1000-1)/1000); + } else if (timeout_disabled) { + ier = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE); + ier |= SDHCI_INT_DATA_TIMEOUT; + writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE); + timeout_disabled = false; + udelay((ns_2clk+1000-1)/1000); + } +#endif + writel(val, host->ioaddr + reg); +#else + void __iomem * regaddr = host->ioaddr + reg; + + writel(val, regaddr); + + if (reg != SDHCI_BUFFER && reg != SDHCI_INT_STATUS && host->clock != 0) + { + int timeout = 100000; + while (val != readl(regaddr) && --timeout > 0) + continue; + + if (timeout <= 0) + printk(KERN_ERR "%s: writing 0x%X to reg 0x%X " + "always gives 0x%X\n", + mmc_hostname(host->mmc), + val, reg, readl(regaddr)); + BUG_ON(timeout <= 0); + } +#endif +} + + +void sdhci_bcm2708_writel(struct sdhci_host *host, u32 val, int reg) +{ +#ifdef LOG_REGISTERS + printk(KERN_ERR "%s: writel to 0x%02x, value 0x%08x\n", + mmc_hostname(host->mmc), reg, val); +#endif + check_dma_reg_use(host, reg); + + sdhci_bcm2708_raw_writel(host, val, reg); +} + +void sdhci_bcm2708_writew(struct sdhci_host *host, u16 val, int reg) +{ + static u32 shadow = 0; + + u32 p = reg == SDHCI_COMMAND ? shadow : + sdhci_bcm2708_raw_readl(host, reg & ~3); + u32 s = reg << 3 & 0x18; + u32 l = val << s; + u32 m = 0xffff << s; + +#ifdef LOG_REGISTERS + printk(KERN_ERR "%s: writew to 0x%02x, value 0x%04x\n", + mmc_hostname(host->mmc), reg, val); +#endif + + if (reg == SDHCI_TRANSFER_MODE) + shadow = (p & ~m) | l; + else { + check_dma_reg_use(host, reg); + sdhci_bcm2708_raw_writel(host, (p & ~m) | l, reg & ~3); + } +} + +void sdhci_bcm2708_writeb(struct sdhci_host *host, u8 val, int reg) +{ + u32 p = sdhci_bcm2708_raw_readl(host, reg & ~3); + u32 s = reg << 3 & 0x18; + u32 l = val << s; + u32 m = 0xff << s; + +#ifdef LOG_REGISTERS + printk(KERN_ERR "%s: writeb to 0x%02x, value 0x%02x\n", + mmc_hostname(host->mmc), reg, val); +#endif + + check_dma_reg_use(host, reg); + sdhci_bcm2708_raw_writel(host, (p & ~m) | l, reg & ~3); +} + +static unsigned int sdhci_bcm2708_get_max_clock(struct sdhci_host *host) +{ + return 20000000; // this value is in Hz (20MHz) +} + +static unsigned int sdhci_bcm2708_get_timeout_clock(struct sdhci_host *host) +{ + if(host->clock) + return (host->clock / 1000); // this value is in kHz (100MHz) + else + return (sdhci_bcm2708_get_max_clock(host) / 1000); +} + +static void sdhci_bcm2708_set_clock(struct sdhci_host *host, unsigned int clock) +{ + int div = 0; + u16 clk = 0; + unsigned long timeout; + + if (clock == host->clock) + return; + + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + + if (clock == 0) + goto out; + + if (BCM2708_EMMC_CLOCK_FREQ <= clock) + div = 1; + else { + for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) { + if ((BCM2708_EMMC_CLOCK_FREQ / div) <= clock) + break; + } + } + + DBG( "desired SD clock: %d, actual: %d\n", + clock, BCM2708_EMMC_CLOCK_FREQ / div); + + clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; + clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) + << SDHCI_DIVIDER_HI_SHIFT; + clk |= SDHCI_CLOCK_INT_EN; + + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); + + timeout = 20; + while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) + & SDHCI_CLOCK_INT_STABLE)) { + if (timeout == 0) { + printk(KERN_ERR "%s: Internal clock never " + "stabilised.\n", mmc_hostname(host->mmc)); + return; + } + timeout--; + mdelay(1); + } + + clk |= SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); +out: + host->clock = clock; + } + +/*****************************************************************************\ + * * + * DMA Operation * + * * +\*****************************************************************************/ + +struct sdhci_bcm2708_priv { + int dma_chan; + int dma_irq; + void __iomem *dma_chan_base; + struct bcm2708_dma_cb *cb_base; /* DMA control blocks */ + dma_addr_t cb_handle; + /* tracking scatter gather progress */ + unsigned sg_ix; /* scatter gather list index */ + unsigned sg_done; /* bytes in current sg_ix done */ +#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA + unsigned char dma_wanted; /* DMA transfer requested */ + unsigned char dma_waits; /* wait states in DMAs */ +#ifdef CHECK_DMA_USE + unsigned char dmas_pending; /* no of unfinished DMAs */ + hptime_t when_started; + hptime_t when_reset; + hptime_t when_stopped; +#endif +#endif + /* signalling the end of a transfer */ + void (*complete)(struct sdhci_host *); +}; + +#define SDHCI_HOST_PRIV(host) \ + (struct sdhci_bcm2708_priv *)((struct sdhci_host *)(host)+1) + + + +#ifdef CHECK_DMA_REG_USE +static void check_dma_reg_use(struct sdhci_host *host, int reg) +{ + struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); + if (host_priv->dma_wanted && reg != SDHCI_INT_STATUS) { + printk(KERN_INFO"%s: accessing register 0x%x during DMA\n", + mmc_hostname(host->mmc), reg); + } +} +#endif + + + +#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA + +static void sdhci_clear_set_irqgen(struct sdhci_host *host, u32 clear, u32 set) +{ + u32 ier; + + ier = sdhci_bcm2708_raw_readl(host, SDHCI_SIGNAL_ENABLE); + ier &= ~clear; + ier |= set; + /* change which requests generate IRQs - makes no difference to + the content of SDHCI_INT_STATUS, or the need to acknowledge IRQs */ + sdhci_bcm2708_raw_writel(host, ier, SDHCI_SIGNAL_ENABLE); +} + +static void sdhci_signal_irqs(struct sdhci_host *host, u32 irqs) +{ + sdhci_clear_set_irqgen(host, 0, irqs); +} + +static void sdhci_unsignal_irqs(struct sdhci_host *host, u32 irqs) +{ + sdhci_clear_set_irqgen(host, irqs, 0); +} + + + +static void schci_bcm2708_cb_read(struct sdhci_bcm2708_priv *host, + int ix, + dma_addr_t dma_addr, unsigned len, + int /*bool*/ is_last) +{ + struct bcm2708_dma_cb *cb = &host->cb_base[ix]; + unsigned char dmawaits = host->dma_waits; + + cb->info = BCM2708_DMA_PER_MAP(BCM2708_DMA_DREQ_EMMC) | + BCM2708_DMA_WAITS(dmawaits) | + BCM2708_DMA_S_DREQ | + BCM2708_DMA_D_WIDTH | + BCM2708_DMA_D_INC; + cb->src = DMA_SDHCI_BUFFER; /* DATA register DMA address */ + cb->dst = dma_addr; + cb->length = len; + cb->stride = 0; + + if (is_last) { + cb->info |= BCM2708_DMA_INT_EN | + BCM2708_DMA_WAIT_RESP; + cb->next = 0; + } else + cb->next = host->cb_handle + + (ix+1)*sizeof(struct bcm2708_dma_cb); + + cb->pad[0] = 0; + cb->pad[1] = 0; +} + +static void schci_bcm2708_cb_write(struct sdhci_bcm2708_priv *host, + int ix, + dma_addr_t dma_addr, unsigned len, + int /*bool*/ is_last) +{ + struct bcm2708_dma_cb *cb = &host->cb_base[ix]; + unsigned char dmawaits = host->dma_waits; + + /* We can make arbitrarily large writes as long as we specify DREQ to + pace the delivery of bytes to the Arasan hardware */ + cb->info = BCM2708_DMA_PER_MAP(BCM2708_DMA_DREQ_EMMC) | + BCM2708_DMA_WAITS(dmawaits) | + BCM2708_DMA_D_DREQ | + BCM2708_DMA_S_WIDTH | + BCM2708_DMA_S_INC; + cb->src = dma_addr; + cb->dst = DMA_SDHCI_BUFFER; /* DATA register DMA address */ + cb->length = len; + cb->stride = 0; + + if (is_last) { + cb->info |= BCM2708_DMA_INT_EN | + BCM2708_DMA_WAIT_RESP; + cb->next = 0; + } else + cb->next = host->cb_handle + + (ix+1)*sizeof(struct bcm2708_dma_cb); + + cb->pad[0] = 0; + cb->pad[1] = 0; +} + + +static void schci_bcm2708_dma_go(struct sdhci_host *host) +{ + struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); + void __iomem *dma_chan_base = host_priv->dma_chan_base; + + BUG_ON(host_priv->dma_wanted); +#ifdef CHECK_DMA_USE + if (host_priv->dma_wanted) + printk(KERN_ERR "%s: DMA already in progress - " + "now %"FMT_HPT", last started %lu " + "reset %lu stopped %lu\n", + mmc_hostname(host->mmc), + hptime(), since_ns(host_priv->when_started), + since_ns(host_priv->when_reset), + since_ns(host_priv->when_stopped)); + else if (host_priv->dmas_pending > 0) + printk(KERN_INFO "%s: note - new DMA when %d reset DMAs " + "already in progress - " + "now %"FMT_HPT", started %lu reset %lu stopped %lu\n", + mmc_hostname(host->mmc), + host_priv->dmas_pending, + hptime(), since_ns(host_priv->when_started), + since_ns(host_priv->when_reset), + since_ns(host_priv->when_stopped)); + host_priv->dmas_pending += 1; + host_priv->when_started = hptime(); +#endif + host_priv->dma_wanted = 1; + DBG("PDMA go - base %p handle %08X\n", dma_chan_base, + host_priv->cb_handle); + bcm_dma_start(dma_chan_base, host_priv->cb_handle); +} + + +static void +sdhci_platdma_read(struct sdhci_host *host, dma_addr_t dma_addr, size_t len) +{ + struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); + + DBG("PDMA to read %d bytes\n", len); + host_priv->sg_done += len; + schci_bcm2708_cb_read(host_priv, 0, dma_addr, len, 1/*TRUE*/); + schci_bcm2708_dma_go(host); +} + + +static void +sdhci_platdma_write(struct sdhci_host *host, dma_addr_t dma_addr, size_t len) +{ + struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); + + DBG("PDMA to write %d bytes\n", len); + //BUG_ON(0 != (len & 0x1ff)); + + host_priv->sg_done += len; + schci_bcm2708_cb_write(host_priv, 0, dma_addr, len, 1/*TRUE*/); + schci_bcm2708_dma_go(host); +} + +/*! space is avaiable to receive into or data is available to write + Platform DMA exported function +*/ +void +sdhci_bcm2708_platdma_avail(struct sdhci_host *host, unsigned int *ref_intmask, + void(*completion_callback)(struct sdhci_host *host)) +{ + struct mmc_data *data = host->data; + struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); + int sg_ix; + size_t bytes; + dma_addr_t addr; + + BUG_ON(NULL == data); + BUG_ON(0 == data->blksz); + + host_priv->complete = completion_callback; + + sg_ix = host_priv->sg_ix; + BUG_ON(sg_ix >= data->sg_len); + + /* we can DMA blocks larger than blksz - it may hang the DMA + channel but we are its only user */ + bytes = sg_dma_len(&data->sg[sg_ix]) - host_priv->sg_done; + addr = sg_dma_address(&data->sg[sg_ix]) + host_priv->sg_done; + + if (bytes > 0) { + /* We're going to poll for read/write available state until + we finish this DMA + */ + + if (data->flags & MMC_DATA_READ) { + if (*ref_intmask & SDHCI_INT_DATA_AVAIL) { + sdhci_unsignal_irqs(host, SDHCI_INT_DATA_AVAIL | + SDHCI_INT_SPACE_AVAIL); + sdhci_platdma_read(host, addr, bytes); + } + } else { + if (*ref_intmask & SDHCI_INT_SPACE_AVAIL) { + sdhci_unsignal_irqs(host, SDHCI_INT_DATA_AVAIL | + SDHCI_INT_SPACE_AVAIL); + sdhci_platdma_write(host, addr, bytes); + } + } + } + /* else: + we have run out of bytes that need transferring (e.g. we may be in + the middle of the last DMA transfer), or + it is also possible that we've been called when another IRQ is + signalled, even though we've turned off signalling of our own IRQ */ + + *ref_intmask &= ~SDHCI_INT_DATA_END; + /* don't let the main sdhci driver act on this .. we'll deal with it + when we respond to the DMA - if one is currently in progress */ +} + +/* is it possible to DMA the given mmc_data structure? + Platform DMA exported function +*/ +int /*bool*/ +sdhci_bcm2708_platdma_dmaable(struct sdhci_host *host, struct mmc_data *data) +{ + struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); + int ok = bcm_sg_suitable_for_dma(data->sg, data->sg_len); + + if (!ok) + DBG("Reverting to PIO - bad cache alignment\n"); + + else { + host_priv->sg_ix = 0; /* first SG index */ + host_priv->sg_done = 0; /* no bytes done */ + } + + return ok; +} + +#include //GRAYG +/*! the current SD transacton has been abandonned + We need to tidy up if we were in the middle of a DMA + Platform DMA exported function +*/ +void +sdhci_bcm2708_platdma_reset(struct sdhci_host *host, struct mmc_data *data) +{ + struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); + unsigned long flags; + + BUG_ON(NULL == host); + + spin_lock_irqsave(&host->lock, flags); + + if (host_priv->dma_wanted) { + if (NULL == data) { + printk(KERN_ERR "%s: ongoing DMA reset - no data!\n", + mmc_hostname(host->mmc)); + BUG_ON(NULL == data); + } else { + struct scatterlist *sg; + int sg_len; + int sg_todo; + int rc; + unsigned long cs; + + sg = data->sg; + sg_len = data->sg_len; + sg_todo = sg_dma_len(&sg[host_priv->sg_ix]); + + cs = readl(host_priv->dma_chan_base + BCM2708_DMA_CS); + + if (!(BCM2708_DMA_ACTIVE & cs)) + printk(KERN_INFO "%s: missed completion of " + "cmd %d DMA (%d/%d [%d]/[%d]) - " + "ignoring it\n", + mmc_hostname(host->mmc), + host->last_cmdop, + host_priv->sg_done, sg_todo, + host_priv->sg_ix+1, sg_len); + else + printk(KERN_INFO "%s: resetting ongoing cmd %d" + "DMA before %d/%d [%d]/[%d] complete\n", + mmc_hostname(host->mmc), + host->last_cmdop, + host_priv->sg_done, sg_todo, + host_priv->sg_ix+1, sg_len); +#ifdef CHECK_DMA_USE + printk(KERN_INFO "%s: now %"FMT_HPT" started %lu " + "last reset %lu last stopped %lu\n", + mmc_hostname(host->mmc), + hptime(), since_ns(host_priv->when_started), + since_ns(host_priv->when_reset), + since_ns(host_priv->when_stopped)); + { unsigned long info, debug; + void __iomem *base; + unsigned long pend0, pend1, pend2; + + base = host_priv->dma_chan_base; + cs = readl(base + BCM2708_DMA_CS); + info = readl(base + BCM2708_DMA_INFO); + debug = readl(base + BCM2708_DMA_DEBUG); + printk(KERN_INFO "%s: DMA%d CS=%08lX TI=%08lX " + "DEBUG=%08lX\n", + mmc_hostname(host->mmc), + host_priv->dma_chan, + cs, info, debug); + pend0 = readl(__io_address(ARM_IRQ_PEND0)); + pend1 = readl(__io_address(ARM_IRQ_PEND1)); + pend2 = readl(__io_address(ARM_IRQ_PEND2)); + + printk(KERN_INFO "%s: PEND0=%08lX " + "PEND1=%08lX PEND2=%08lX\n", + mmc_hostname(host->mmc), + pend0, pend1, pend2); + + //gintsts = readl(__io_address(GINTSTS)); + //gintmsk = readl(__io_address(GINTMSK)); + //printk(KERN_INFO "%s: USB GINTSTS=%08lX" + // "GINTMSK=%08lX\n", + // mmc_hostname(host->mmc), gintsts, gintmsk); + } +#endif + rc = bcm_dma_abort(host_priv->dma_chan_base); + BUG_ON(rc != 0); + } + host_priv->dma_wanted = 0; +#ifdef CHECK_DMA_USE + host_priv->when_reset = hptime(); +#endif + } + + spin_unlock_irqrestore(&host->lock, flags); +} + + +static void sdhci_bcm2708_dma_complete_irq(struct sdhci_host *host, + u32 dma_cs) +{ + struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); + struct mmc_data *data; + struct scatterlist *sg; + int sg_len; + int sg_ix; + int sg_todo; + unsigned long flags; + + BUG_ON(NULL == host); + + spin_lock_irqsave(&host->lock, flags); + data = host->data; + +#ifdef CHECK_DMA_USE + if (host_priv->dmas_pending <= 0) + DBG("on completion no DMA in progress - " + "now %"FMT_HPT" started %lu reset %lu stopped %lu\n", + hptime(), since_ns(host_priv->when_started), + since_ns(host_priv->when_reset), + since_ns(host_priv->when_stopped)); + else if (host_priv->dmas_pending > 1) + DBG("still %d DMA in progress after completion - " + "now %"FMT_HPT" started %lu reset %lu stopped %lu\n", + host_priv->dmas_pending - 1, + hptime(), since_ns(host_priv->when_started), + since_ns(host_priv->when_reset), + since_ns(host_priv->when_stopped)); + BUG_ON(host_priv->dmas_pending <= 0); + host_priv->dmas_pending -= 1; + host_priv->when_stopped = hptime(); +#endif + host_priv->dma_wanted = 0; + + if (NULL == data) { + DBG("PDMA unused completion - status 0x%X\n", dma_cs); + spin_unlock_irqrestore(&host->lock, flags); + return; + } + sg = data->sg; + sg_len = data->sg_len; + sg_todo = sg_dma_len(&sg[host_priv->sg_ix]); + + DBG("PDMA complete %d/%d [%d]/[%d]..\n", + host_priv->sg_done, sg_todo, + host_priv->sg_ix+1, sg_len); + + BUG_ON(host_priv->sg_done > sg_todo); + + if (host_priv->sg_done >= sg_todo) { + host_priv->sg_ix++; + host_priv->sg_done = 0; + } + + sg_ix = host_priv->sg_ix; + if (sg_ix < sg_len) { + u32 irq_mask; + /* Set off next DMA if we've got the capacity */ + + if (data->flags & MMC_DATA_READ) + irq_mask = SDHCI_INT_DATA_AVAIL; + else + irq_mask = SDHCI_INT_SPACE_AVAIL; + + /* We have to use the interrupt status register on the BCM2708 + rather than the SDHCI_PRESENT_STATE register because latency + in the glue logic means that the information retrieved from + the latter is not always up-to-date w.r.t the DMA engine - + it may not indicate that a read or a write is ready yet */ + if (sdhci_bcm2708_raw_readl(host, SDHCI_INT_STATUS) & + irq_mask) { + size_t bytes = sg_dma_len(&sg[sg_ix]) - + host_priv->sg_done; + dma_addr_t addr = sg_dma_address(&data->sg[sg_ix]) + + host_priv->sg_done; + + /* acknowledge interrupt */ + sdhci_bcm2708_raw_writel(host, irq_mask, + SDHCI_INT_STATUS); + + BUG_ON(0 == bytes); + + if (data->flags & MMC_DATA_READ) + sdhci_platdma_read(host, addr, bytes); + else + sdhci_platdma_write(host, addr, bytes); + } else { + DBG("PDMA - wait avail\n"); + /* may generate an IRQ if already present */ + sdhci_signal_irqs(host, SDHCI_INT_DATA_AVAIL | + SDHCI_INT_SPACE_AVAIL); + } + } else { +#ifdef USE_SYNC_AFTER_DMA + /* On the Arasan controller the stop command (which will be + scheduled after this completes) does not seem to work + properly if we allow it to be issued when we are + transferring data to/from the SD card. + We get CRC and DEND errors unless we wait for + the SD controller to finish reading/writing to the card. */ + u32 state_mask; + int timeout=1000000; + hptime_t now = hptime(); + + DBG("PDMA over - sync card\n"); + if (data->flags & MMC_DATA_READ) + state_mask = SDHCI_DOING_READ; + else + state_mask = SDHCI_DOING_WRITE; + + while (0 != (sdhci_bcm2708_raw_readl(host, + SDHCI_PRESENT_STATE) & + state_mask) && --timeout > 0) + continue; + + if (1000000-timeout > 4000) /*ave. is about 3250*/ + DBG("%s: note - long %s sync %luns - " + "%d its.\n", + mmc_hostname(host->mmc), + data->flags & MMC_DATA_READ? "read": "write", + since_ns(now), 1000000-timeout); + if (timeout <= 0) + printk(KERN_ERR"%s: final %s to SD card still " + "running\n", + mmc_hostname(host->mmc), + data->flags & MMC_DATA_READ? "read": "write"); +#endif + if (host_priv->complete) { + (*host_priv->complete)(host); + DBG("PDMA %s complete\n", + data->flags & MMC_DATA_READ?"read":"write"); + sdhci_signal_irqs(host, SDHCI_INT_DATA_AVAIL | + SDHCI_INT_SPACE_AVAIL); + } + } + spin_unlock_irqrestore(&host->lock, flags); +} + +static irqreturn_t sdhci_bcm2708_dma_irq(int irq, void *dev_id) +{ + irqreturn_t result = IRQ_NONE; + struct sdhci_host *host = dev_id; + struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); + u32 dma_cs; /* control and status register */ + unsigned long flags; + + BUG_ON(NULL == dev_id); + BUG_ON(NULL == host_priv->dma_chan_base); + + spin_lock_irqsave(&host->lock, flags); + + dma_cs = readl(host_priv->dma_chan_base + BCM2708_DMA_CS); + + if (dma_cs & BCM2708_DMA_ERR) { + unsigned long debug; + debug = readl(host_priv->dma_chan_base + + BCM2708_DMA_DEBUG); + printk(KERN_ERR "%s: DMA error - CS %lX DEBUG %lX\n", + mmc_hostname(host->mmc), (unsigned long)dma_cs, + (unsigned long)debug); + /* reset error */ + writel(debug, host_priv->dma_chan_base + + BCM2708_DMA_DEBUG); + } + if (dma_cs & BCM2708_DMA_INT) { + /* acknowledge interrupt */ + writel(BCM2708_DMA_INT, + host_priv->dma_chan_base + BCM2708_DMA_CS); + + dsb(); /* ARM data synchronization (push) operation */ + + if (!host_priv->dma_wanted) { + /* ignore this interrupt - it was reset */ + printk(KERN_INFO "%s: DMA IRQ %X ignored - " + "results were reset\n", + mmc_hostname(host->mmc), dma_cs); +#ifdef CHECK_DMA_USE + printk(KERN_INFO "%s: now %"FMT_HPT + " started %lu reset %lu stopped %lu\n", + mmc_hostname(host->mmc), hptime(), + since_ns(host_priv->when_started), + since_ns(host_priv->when_reset), + since_ns(host_priv->when_stopped)); + host_priv->dmas_pending--; +#endif + } else + sdhci_bcm2708_dma_complete_irq(host, dma_cs); + + result = IRQ_HANDLED; + } + + spin_unlock_irqrestore(&host->lock, flags); + + return result; +} +#endif /* CONFIG_MMC_SDHCI_BCM2708_DMA */ + + +/***************************************************************************** \ + * * + * Device Attributes * + * * +\*****************************************************************************/ + + +/** + * Show the DMA-using status + */ +static ssize_t attr_dma_show(struct device *_dev, + struct device_attribute *attr, char *buf) +{ + struct sdhci_host *host = (struct sdhci_host *)dev_get_drvdata(_dev); + + if (host) { + int use_dma = (host->flags & SDHCI_USE_PLATDMA? 1:0); + return sprintf(buf, "%d\n", use_dma); + } else + return -EINVAL; +} + +/** + * Set the DMA-using status + */ +static ssize_t attr_dma_store(struct device *_dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sdhci_host *host = (struct sdhci_host *)dev_get_drvdata(_dev); + + if (host) { +#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA + int on = simple_strtol(buf, NULL, 0); + if (on) { + host->flags |= SDHCI_USE_PLATDMA; + printk(KERN_INFO "%s: DMA enabled\n", + mmc_hostname(host->mmc)); + } else { + host->flags &= ~(SDHCI_USE_PLATDMA | SDHCI_REQ_USE_DMA); + printk(KERN_INFO "%s: DMA disabled\n", + mmc_hostname(host->mmc)); + } +#endif + return count; + } else + return -EINVAL; +} + +static DEVICE_ATTR(use_dma, S_IRUGO | S_IWUGO, attr_dma_show, attr_dma_store); + + +/** + * Show the DMA wait states used + */ +static ssize_t attr_dmawait_show(struct device *_dev, + struct device_attribute *attr, char *buf) +{ + struct sdhci_host *host = (struct sdhci_host *)dev_get_drvdata(_dev); + + if (host) { + struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); + int dmawait = host_priv->dma_waits; + return sprintf(buf, "%d\n", dmawait); + } else + return -EINVAL; +} + +/** + * Set the DMA wait state used + */ +static ssize_t attr_dmawait_store(struct device *_dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sdhci_host *host = (struct sdhci_host *)dev_get_drvdata(_dev); + + if (host) { +#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA + struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); + int dma_waits = simple_strtol(buf, NULL, 0); + if (dma_waits >= 0 && dma_waits < 32) + host_priv->dma_waits = dma_waits; + else + printk(KERN_ERR "%s: illegal dma_waits value - %d", + mmc_hostname(host->mmc), dma_waits); +#endif + return count; + } else + return -EINVAL; +} + +static DEVICE_ATTR(dma_wait, S_IRUGO | S_IWUGO, + attr_dmawait_show, attr_dmawait_store); + + +/** + * Show the DMA-using status + */ +static ssize_t attr_status_show(struct device *_dev, + struct device_attribute *attr, char *buf) +{ + struct sdhci_host *host = (struct sdhci_host *)dev_get_drvdata(_dev); + + if (host) { + struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); + return sprintf(buf, + "present: yes\n" + "power: %s\n" + "clock: %u Hz\n" +#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA + "dma: %s (%d waits)\n", +#else + "dma: unconfigured\n", +#endif + "always on", + host->clock +#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA + , (host->flags & SDHCI_USE_PLATDMA)? "on": "off" + , host_priv->dma_waits +#endif + ); + } else + return -EINVAL; +} + +static DEVICE_ATTR(status, S_IRUGO, attr_status_show, NULL); + +/***************************************************************************** \ + * * + * Power Management * + * * +\*****************************************************************************/ + + +#ifdef CONFIG_PM +static int sdhci_bcm2708_suspend(struct platform_device *dev, pm_message_t state) +{ + struct sdhci_host *host = (struct sdhci_host *) + platform_get_drvdata(dev); + int ret = 0; + + if (host->mmc) { + ret = mmc_suspend_host(host->mmc); + } + + return ret; +} + +static int sdhci_bcm2708_resume(struct platform_device *dev) +{ + struct sdhci_host *host = (struct sdhci_host *) + platform_get_drvdata(dev); + int ret = 0; + + if (host->mmc) { + ret = mmc_resume_host(host->mmc); + } + + return ret; +} +#endif + + +/*****************************************************************************\ + * * + * Device quirk functions. Implemented as local ops because the flags * + * field is out of space with newer kernels. This implementation can be * + * back ported to older kernels as well. * +\****************************************************************************/ +static unsigned int sdhci_bcm2708_quirk_extra_ints(struct sdhci_host *host) +{ + return 1; +} + +static unsigned int sdhci_bcm2708_quirk_spurious_crc(struct sdhci_host *host) +{ + return 1; +} + +static unsigned int sdhci_bcm2708_quirk_voltage_broken(struct sdhci_host *host) +{ + return 1; +} + +static unsigned int sdhci_bcm2708_uhs_broken(struct sdhci_host *host) +{ + return 1; +} + +/***************************************************************************** \ + * * + * Device ops * + * * +\*****************************************************************************/ + +static struct sdhci_ops sdhci_bcm2708_ops = { +#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS + .read_l = sdhci_bcm2708_readl, + .read_w = sdhci_bcm2708_readw, + .read_b = sdhci_bcm2708_readb, + .write_l = sdhci_bcm2708_writel, + .write_w = sdhci_bcm2708_writew, + .write_b = sdhci_bcm2708_writeb, +#else +#error The BCM2708 SDHCI driver needs CONFIG_MMC_SDHCI_IO_ACCESSORS to be set +#endif + //.enable_dma = NULL, + .set_clock = sdhci_bcm2708_set_clock, + .get_max_clock = sdhci_bcm2708_get_max_clock, + //.get_min_clock = NULL, + .get_timeout_clock = sdhci_bcm2708_get_timeout_clock, + +#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA + // Platform DMA operations + .pdma_able = sdhci_bcm2708_platdma_dmaable, + .pdma_avail = sdhci_bcm2708_platdma_avail, + .pdma_reset = sdhci_bcm2708_platdma_reset, +#endif + .extra_ints = sdhci_bcm2708_quirk_extra_ints, + .spurious_crc_acmd51 = sdhci_bcm2708_quirk_spurious_crc, + .voltage_broken = sdhci_bcm2708_quirk_voltage_broken, + .uhs_broken = sdhci_bcm2708_uhs_broken, +}; + +/*****************************************************************************\ + * * + * Device probing/removal * + * * +\*****************************************************************************/ + +static int sdhci_bcm2708_probe(struct platform_device *pdev) +{ + struct sdhci_host *host; + struct resource *iomem; + struct sdhci_bcm2708_priv *host_priv; + int ret; + + BUG_ON(pdev == NULL); + + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!iomem) { + ret = -ENOMEM; + goto err; + } + + if (resource_size(iomem) != 0x100) + dev_err(&pdev->dev, "Invalid iomem size. You may " + "experience problems.\n"); + + if (pdev->dev.parent) + host = sdhci_alloc_host(pdev->dev.parent, + sizeof(struct sdhci_bcm2708_priv)); + else + host = sdhci_alloc_host(&pdev->dev, + sizeof(struct sdhci_bcm2708_priv)); + + if (IS_ERR(host)) { + ret = PTR_ERR(host); + goto err; + } + + host->hw_name = "BCM2708_Arasan"; + host->ops = &sdhci_bcm2708_ops; + host->irq = platform_get_irq(pdev, 0); + + host->quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION | + SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | + SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | + SDHCI_QUIRK_NONSTANDARD_CLOCK; +#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA + host->flags = SDHCI_USE_PLATDMA; +#endif + + if (!request_mem_region(iomem->start, resource_size(iomem), + mmc_hostname(host->mmc))) { + dev_err(&pdev->dev, "cannot request region\n"); + ret = -EBUSY; + goto err_request; + } + + host->ioaddr = ioremap(iomem->start, resource_size(iomem)); + if (!host->ioaddr) { + dev_err(&pdev->dev, "failed to remap registers\n"); + ret = -ENOMEM; + goto err_remap; + } + + host_priv = SDHCI_HOST_PRIV(host); + +#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA + host_priv->dma_wanted = 0; +#ifdef CHECK_DMA_USE + host_priv->dmas_pending = 0; + host_priv->when_started = 0; + host_priv->when_reset = 0; + host_priv->when_stopped = 0; +#endif + host_priv->sg_ix = 0; + host_priv->sg_done = 0; + host_priv->complete = NULL; + host_priv->dma_waits = SDHCI_BCM_DMA_WAITS; + + host_priv->cb_base = dma_alloc_writecombine(&pdev->dev, SZ_4K, + &host_priv->cb_handle, + GFP_KERNEL); + if (!host_priv->cb_base) { + dev_err(&pdev->dev, "cannot allocate DMA CBs\n"); + ret = -ENOMEM; + goto err_alloc_cb; + } + + ret = bcm_dma_chan_alloc(BCM_DMA_FEATURE_FAST, + &host_priv->dma_chan_base, + &host_priv->dma_irq); + if (ret < 0) { + dev_err(&pdev->dev, "couldn't allocate a DMA channel\n"); + goto err_add_dma; + } + host_priv->dma_chan = ret; + + ret = request_irq(host_priv->dma_irq, sdhci_bcm2708_dma_irq, + IRQF_SHARED, DRIVER_NAME " (dma)", host); + if (ret) { + dev_err(&pdev->dev, "cannot set DMA IRQ\n"); + goto err_add_dma_irq; + } + DBG("DMA CBs %p handle %08X DMA%d %p DMA IRQ %d\n", + host_priv->cb_base, (unsigned)host_priv->cb_handle, + host_priv->dma_chan, host_priv->dma_chan_base, + host_priv->dma_irq); + + host->mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; +#endif + + ret = sdhci_add_host(host); + if (ret) + goto err_add_host; + + platform_set_drvdata(pdev, host); + ret = device_create_file(&pdev->dev, &dev_attr_use_dma); + ret = device_create_file(&pdev->dev, &dev_attr_dma_wait); + ret = device_create_file(&pdev->dev, &dev_attr_status); + + printk(KERN_INFO "%s: BCM2708 SDHC host at 0x%08llx DMA %d IRQ %d\n", + mmc_hostname(host->mmc), (unsigned long long)iomem->start, + host_priv->dma_chan, host_priv->dma_irq); + + return 0; + +err_add_host: +#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA + free_irq(host_priv->dma_irq, host); +err_add_dma_irq: + bcm_dma_chan_free(host_priv->dma_chan); +err_add_dma: + dma_free_writecombine(&pdev->dev, SZ_4K, host_priv->cb_base, + host_priv->cb_handle); +err_alloc_cb: +#endif + iounmap(host->ioaddr); +err_remap: + release_mem_region(iomem->start, resource_size(iomem)); +err_request: + sdhci_free_host(host); +err: + dev_err(&pdev->dev, "probe failed, err %d\n", ret); + return ret; +} + +static int sdhci_bcm2708_remove(struct platform_device *pdev) +{ + struct sdhci_host *host = platform_get_drvdata(pdev); + struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); + int dead; + u32 scratch; + + dead = 0; + scratch = sdhci_bcm2708_readl(host, SDHCI_INT_STATUS); + if (scratch == (u32)-1) + dead = 1; + + device_remove_file(&pdev->dev, &dev_attr_status); + device_remove_file(&pdev->dev, &dev_attr_dma_wait); + device_remove_file(&pdev->dev, &dev_attr_use_dma); + +#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA + free_irq(host_priv->dma_irq, host); + dma_free_writecombine(&pdev->dev, SZ_4K, host_priv->cb_base, + host_priv->cb_handle); +#endif + sdhci_remove_host(host, dead); + iounmap(host->ioaddr); + release_mem_region(iomem->start, resource_size(iomem)); + sdhci_free_host(host); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver sdhci_bcm2708_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, + .probe = sdhci_bcm2708_probe, + .remove = sdhci_bcm2708_remove, + +#ifdef CONFIG_PM + .suspend = sdhci_bcm2708_suspend, + .resume = sdhci_bcm2708_resume, +#endif + +}; + +/*****************************************************************************\ + * * + * Driver init/exit * + * * +\*****************************************************************************/ + +static int __init sdhci_drv_init(void) +{ + return platform_driver_register(&sdhci_bcm2708_driver); +} + +static void __exit sdhci_drv_exit(void) +{ + platform_driver_unregister(&sdhci_bcm2708_driver); +} + +module_init(sdhci_drv_init); +module_exit(sdhci_drv_exit); + +MODULE_DESCRIPTION("Secure Digital Host Controller Interface platform driver"); +MODULE_AUTHOR("Broadcom "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:"DRIVER_NAME); + diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 2ea429c..179e83e 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "sdhci.h" @@ -315,7 +316,7 @@ static void sdhci_read_block_pio(struct sdhci_host *host) u32 uninitialized_var(scratch); u8 *buf; - DBG("PIO reading\n"); + DBG("PIO reading %db\n", host->data->blksz); blksize = host->data->blksz; chunk = 0; @@ -360,7 +361,7 @@ static void sdhci_write_block_pio(struct sdhci_host *host) u32 scratch; u8 *buf; - DBG("PIO writing\n"); + DBG("PIO writing %db\n", host->data->blksz); blksize = host->data->blksz; chunk = 0; @@ -399,19 +400,28 @@ static void sdhci_write_block_pio(struct sdhci_host *host) local_irq_restore(flags); } -static void sdhci_transfer_pio(struct sdhci_host *host) +static void sdhci_transfer_pio(struct sdhci_host *host, u32 intstate) { u32 mask; + u32 state = 0; + u32 intmask; + int available; BUG_ON(!host->data); if (host->blocks == 0) return; - if (host->data->flags & MMC_DATA_READ) + if (host->data->flags & MMC_DATA_READ) { mask = SDHCI_DATA_AVAILABLE; - else + intmask = SDHCI_INT_DATA_AVAIL; + } else { mask = SDHCI_SPACE_AVAILABLE; + intmask = SDHCI_INT_SPACE_AVAIL; + } + + /* initially we can see whether we can procede using intstate */ + available = (intstate & intmask); /* * Some controllers (JMicron JMB38x) mess up the buffer bits @@ -422,7 +432,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host) (host->data->blocks == 1)) mask = ~0; - while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { + while (available) { if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY) udelay(100); @@ -434,9 +444,11 @@ static void sdhci_transfer_pio(struct sdhci_host *host) host->blocks--; if (host->blocks == 0) break; + state = sdhci_readl(host, SDHCI_PRESENT_STATE); + available = state & mask; } - DBG("PIO transfer complete.\n"); + DBG("PIO transfer complete - %d blocks left.\n", host->blocks); } static char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags) @@ -709,7 +721,9 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host) u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL; u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; - if (host->flags & SDHCI_REQ_USE_DMA) + /* platform DMA will begin on receipt of PIO irqs */ + if ((host->flags & SDHCI_REQ_USE_DMA) && + !(host->flags & SDHCI_USE_PLATDMA)) sdhci_clear_set_irqs(host, pio_irqs, dma_irqs); else sdhci_clear_set_irqs(host, dma_irqs, pio_irqs); @@ -741,44 +755,25 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) host->data_early = 0; host->data->bytes_xfered = 0; - if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) + if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA | SDHCI_USE_PLATDMA)) host->flags |= SDHCI_REQ_USE_DMA; /* * FIXME: This doesn't account for merging when mapping the * scatterlist. */ - if (host->flags & SDHCI_REQ_USE_DMA) { - int broken, i; - struct scatterlist *sg; - - broken = 0; - if (host->flags & SDHCI_USE_ADMA) { - if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) - broken = 1; - } else { - if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) - broken = 1; - } - - if (unlikely(broken)) { - for_each_sg(data->sg, sg, data->sg_len, i) { - if (sg->length & 0x3) { - DBG("Reverting to PIO because of " - "transfer size (%d)\n", - sg->length); - host->flags &= ~SDHCI_REQ_USE_DMA; - break; - } - } - } - } /* * The assumption here being that alignment is the same after * translation to device address space. */ - if (host->flags & SDHCI_REQ_USE_DMA) { + if ((host->flags & (SDHCI_REQ_USE_DMA | SDHCI_USE_PLATDMA)) == + (SDHCI_REQ_USE_DMA | SDHCI_USE_PLATDMA)) { + + if (! sdhci_platdma_dmaable(host, data)) + host->flags &= ~SDHCI_REQ_USE_DMA; + + } else if (host->flags & SDHCI_REQ_USE_DMA) { int broken, i; struct scatterlist *sg; @@ -837,7 +832,8 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) */ WARN_ON(1); host->flags &= ~SDHCI_REQ_USE_DMA; - } else { + } else + if (!(host->flags & SDHCI_USE_PLATDMA)) { WARN_ON(sg_cnt != 1); sdhci_writel(host, sg_dma_address(data->sg), SDHCI_DMA_ADDRESS); @@ -853,11 +849,13 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) if (host->version >= SDHCI_SPEC_200) { ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); ctrl &= ~SDHCI_CTRL_DMA_MASK; + if (! (host->flags & SDHCI_USE_PLATDMA)) { if ((host->flags & SDHCI_REQ_USE_DMA) && (host->flags & SDHCI_USE_ADMA)) ctrl |= SDHCI_CTRL_ADMA32; else ctrl |= SDHCI_CTRL_SDMA; + } sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); } @@ -909,7 +907,8 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, if (data->flags & MMC_DATA_READ) mode |= SDHCI_TRNS_READ; - if (host->flags & SDHCI_REQ_USE_DMA) + if ((host->flags & SDHCI_REQ_USE_DMA) && + !(host->flags & SDHCI_USE_PLATDMA)) mode |= SDHCI_TRNS_DMA; sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); @@ -925,13 +924,16 @@ static void sdhci_finish_data(struct sdhci_host *host) host->data = NULL; if (host->flags & SDHCI_REQ_USE_DMA) { - if (host->flags & SDHCI_USE_ADMA) - sdhci_adma_table_post(host, data); - else { + /* we may have to abandon an ongoing platform DMA */ + if (host->flags & SDHCI_USE_PLATDMA) + sdhci_platdma_reset(host, data); + + if (host->flags & (SDHCI_USE_PLATDMA | SDHCI_USE_SDMA)) { dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, (data->flags & MMC_DATA_READ) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); - } + } else if (host->flags & SDHCI_USE_ADMA) + sdhci_adma_table_post(host, data); } /* @@ -984,6 +986,12 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY)) mask |= SDHCI_DATA_INHIBIT; + if(host->ops->missing_status && (cmd->opcode == MMC_SEND_STATUS)) { + timeout = 5000; // Really obscenely large delay to send the status, due to bug in controller + // which might cause the STATUS command to get stuck when a data operation is in flow + mask |= SDHCI_DATA_INHIBIT; + } + /* We shouldn't wait for data inihibit for stop commands, even though they might use busy signaling */ if (host->mrq->data && (cmd == host->mrq->data->stop)) @@ -1001,10 +1009,16 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) timeout--; mdelay(1); } + DBG("send cmd %d - wait 0x%X irq 0x%x\n", cmd->opcode, mask, + sdhci_readl(host, SDHCI_INT_STATUS)); mod_timer(&host->timer, jiffies + 10 * HZ); host->cmd = cmd; + if (host->last_cmdop == MMC_APP_CMD) + host->last_cmdop = -cmd->opcode; + else + host->last_cmdop = cmd->opcode; sdhci_prepare_data(host, cmd); @@ -1470,7 +1484,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) else ctrl &= ~SDHCI_CTRL_HISPD; - if (host->version >= SDHCI_SPEC_300) { + if (host->version >= SDHCI_SPEC_300 && !(host->ops->uhs_broken)) { u16 clk, ctrl_2; /* In case of UHS-I modes, set High Speed Enable */ @@ -2164,7 +2178,7 @@ static void sdhci_timeout_timer(unsigned long data) if (host->mrq) { pr_err("%s: Timeout waiting for hardware " - "interrupt.\n", mmc_hostname(host->mmc)); + "interrupt - cmd%d.\n", mmc_hostname(host->mmc), host->last_cmdop); sdhci_dumpregs(host); if (host->data) { @@ -2209,10 +2223,13 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) BUG_ON(intmask == 0); if (!host->cmd) { + if (!(host->ops->extra_ints)) { pr_err("%s: Got command interrupt 0x%08x even " "though no command operation was in progress.\n", mmc_hostname(host->mmc), (unsigned)intmask); sdhci_dumpregs(host); + } else + DBG("cmd irq 0x%08x cmd complete\n", (unsigned)intmask); return; } @@ -2282,6 +2299,19 @@ static void sdhci_show_adma_error(struct sdhci_host *host) static void sdhci_show_adma_error(struct sdhci_host *host) { } #endif +static void sdhci_data_end(struct sdhci_host *host) +{ + if (host->cmd) { + /* + * Data managed to finish before the + * command completed. Make sure we do + * things in the proper order. + */ + host->data_early = 1; + } else + sdhci_finish_data(host); +} + static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) { u32 command; @@ -2311,23 +2341,39 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) } } + if (!(host->ops->extra_ints)) { pr_err("%s: Got data interrupt 0x%08x even " "though no data operation was in progress.\n", mmc_hostname(host->mmc), (unsigned)intmask); sdhci_dumpregs(host); + } else + DBG("data irq 0x%08x but no data\n", (unsigned)intmask); return; } if (intmask & SDHCI_INT_DATA_TIMEOUT) host->data->error = -ETIMEDOUT; - else if (intmask & SDHCI_INT_DATA_END_BIT) + else if (intmask & SDHCI_INT_DATA_END_BIT) { + DBG("end error in cmd %d\n", host->last_cmdop); + if (host->ops->spurious_crc_acmd51 && + host->last_cmdop == -SD_APP_SEND_SCR) { + DBG("ignoring spurious data_end_bit error\n"); + intmask = SDHCI_INT_DATA_AVAIL|SDHCI_INT_DATA_END; + } else host->data->error = -EILSEQ; - else if ((intmask & SDHCI_INT_DATA_CRC) && + } else if ((intmask & SDHCI_INT_DATA_CRC) && SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) - != MMC_BUS_TEST_R) + != MMC_BUS_TEST_R) { + DBG("crc error in cmd %d\n", host->last_cmdop); + if (host->ops->spurious_crc_acmd51 && + host->last_cmdop == -SD_APP_SEND_SCR) { + DBG("ignoring spurious data_crc_bit error\n"); + intmask = SDHCI_INT_DATA_AVAIL|SDHCI_INT_DATA_END; + } else { host->data->error = -EILSEQ; - else if (intmask & SDHCI_INT_ADMA_ERROR) { + } + } else if (intmask & SDHCI_INT_ADMA_ERROR) { pr_err("%s: ADMA error\n", mmc_hostname(host->mmc)); sdhci_show_adma_error(host); host->data->error = -EIO; @@ -2335,11 +2381,18 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) host->ops->adma_workaround(host, intmask); } - if (host->data->error) + if (host->data->error) { + DBG("finish request early on error %d\n", host->data->error); sdhci_finish_data(host); - else { - if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) - sdhci_transfer_pio(host); + } else { + if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) { + if (host->flags & SDHCI_REQ_USE_DMA) { + /* possible only in PLATDMA mode */ + sdhci_platdma_avail(host, &intmask, + &sdhci_data_end); + } else + sdhci_transfer_pio(host, intmask); + } /* * We currently don't do anything fancy with DMA @@ -2368,18 +2421,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS); } - if (intmask & SDHCI_INT_DATA_END) { - if (host->cmd) { - /* - * Data managed to finish before the - * command completed. Make sure we do - * things in the proper order. - */ - host->data_early = 1; - } else { - sdhci_finish_data(host); - } - } + if (intmask & SDHCI_INT_DATA_END) + sdhci_data_end(host); } } @@ -2435,6 +2478,22 @@ again: tasklet_schedule(&host->card_tasklet); } + if (intmask & SDHCI_INT_ERROR_MASK & ~SDHCI_INT_ERROR) + DBG("controller reports error 0x%x -" + "%s%s%s%s%s%s%s%s%s%s", + intmask, + intmask & SDHCI_INT_TIMEOUT? " timeout": "", + intmask & SDHCI_INT_CRC ? " crc": "", + intmask & SDHCI_INT_END_BIT? " endbit": "", + intmask & SDHCI_INT_INDEX? " index": "", + intmask & SDHCI_INT_DATA_TIMEOUT? " data_timeout": "", + intmask & SDHCI_INT_DATA_CRC? " data_crc": "", + intmask & SDHCI_INT_DATA_END_BIT? " data_endbit": "", + intmask & SDHCI_INT_BUS_POWER? " buspower": "", + intmask & SDHCI_INT_ACMD12ERR? " acmd12": "", + intmask & SDHCI_INT_ADMA_ERROR? " adma": "" + ); + if (intmask & SDHCI_INT_CMD_MASK) { sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, SDHCI_INT_STATUS); @@ -2449,7 +2508,13 @@ again: intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); - intmask &= ~SDHCI_INT_ERROR; + if (intmask & SDHCI_INT_ERROR_MASK) { + /* collect any uncovered errors */ + sdhci_writel(host, intmask & SDHCI_INT_ERROR_MASK, + SDHCI_INT_STATUS); + } + + intmask &= ~SDHCI_INT_ERROR_MASK; if (intmask & SDHCI_INT_BUS_POWER) { pr_err("%s: Card is consuming too much power!\n", @@ -2569,7 +2634,8 @@ int sdhci_resume_host(struct sdhci_host *host) { int ret; - if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { + if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA | + SDHCI_USE_PLATDMA)) { if (host->ops->enable_dma) host->ops->enable_dma(host); } @@ -2785,14 +2851,16 @@ int sdhci_add_host(struct sdhci_host *host) host->flags &= ~SDHCI_USE_ADMA; } - if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { + if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA | + SDHCI_USE_PLATDMA)) { if (host->ops->enable_dma) { if (host->ops->enable_dma(host)) { pr_warning("%s: No suitable DMA " "available. Falling back to PIO.\n", mmc_hostname(mmc)); host->flags &= - ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA); + ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA | + SDHCI_USE_PLATDMA); } } } @@ -3080,6 +3148,12 @@ int sdhci_add_host(struct sdhci_host *host) SDHCI_MAX_CURRENT_MULTIPLIER; } + if(host->ops->voltage_broken) { + ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34; + // Cannot support UHS modes if we are stuck at 3.3V; + mmc->caps &= ~(MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_DDR50); + } + mmc->ocr_avail = ocr_avail; mmc->ocr_avail_sdio = ocr_avail; if (host->ocr_avail_sdio) @@ -3210,6 +3284,7 @@ int sdhci_add_host(struct sdhci_host *host) pr_info("%s: SDHCI controller on %s [%s] using %s\n", mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), + (host->flags & SDHCI_USE_PLATDMA) ? "platform's DMA" : (host->flags & SDHCI_USE_ADMA) ? "ADMA" : (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO"); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 379e09d..f90574e 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -289,6 +289,20 @@ struct sdhci_ops { void (*platform_reset_enter)(struct sdhci_host *host, u8 mask); void (*platform_reset_exit)(struct sdhci_host *host, u8 mask); int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs); + + int (*pdma_able)(struct sdhci_host *host, + struct mmc_data *data); + void (*pdma_avail)(struct sdhci_host *host, + unsigned int *ref_intmask, + void(*complete)(struct sdhci_host *)); + void (*pdma_reset)(struct sdhci_host *host, + struct mmc_data *data); + unsigned int (*extra_ints)(struct sdhci_host *host); + unsigned int (*spurious_crc_acmd51)(struct sdhci_host *host); + unsigned int (*voltage_broken)(struct sdhci_host *host); + unsigned int (*uhs_broken)(struct sdhci_host *host); + unsigned int (*missing_status)(struct sdhci_host *host); + void (*hw_reset)(struct sdhci_host *host); void (*platform_suspend)(struct sdhci_host *host); void (*platform_resume)(struct sdhci_host *host); @@ -399,6 +413,29 @@ extern int sdhci_resume_host(struct sdhci_host *host); extern void sdhci_enable_irq_wakeups(struct sdhci_host *host); #endif +static inline int /*bool*/ +sdhci_platdma_dmaable(struct sdhci_host *host, struct mmc_data *data) +{ + if (host->ops->pdma_able) + return host->ops->pdma_able(host, data); + else + return 1; +} +static inline void +sdhci_platdma_avail(struct sdhci_host *host, unsigned int *ref_intmask, + void(*completion_callback)(struct sdhci_host *)) +{ + if (host->ops->pdma_avail) + host->ops->pdma_avail(host, ref_intmask, completion_callback); +} + +static inline void +sdhci_platdma_reset(struct sdhci_host *host, struct mmc_data *data) +{ + if (host->ops->pdma_reset) + host->ops->pdma_reset(host, data); +} + #ifdef CONFIG_PM_RUNTIME extern int sdhci_runtime_suspend_host(struct sdhci_host *host); extern int sdhci_runtime_resume_host(struct sdhci_host *host); diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index b838ffc..f3a39c1 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -128,6 +128,7 @@ struct sdhci_host { #define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ #define SDHCI_HS200_NEEDS_TUNING (1<<10) /* HS200 needs tuning */ #define SDHCI_USING_RETUNING_TIMER (1<<11) /* Host is using a retuning timer for the card */ +#define SDHCI_USE_PLATDMA (1<<12) /* Host uses 3rd party DMA */ unsigned int version; /* SDHCI spec. version */ @@ -142,6 +143,7 @@ struct sdhci_host { struct mmc_request *mrq; /* Current request */ struct mmc_command *cmd; /* Current command */ + int last_cmdop; /* Opcode of last cmd sent */ struct mmc_data *data; /* Current data request */ unsigned int data_early:1; /* Data finished before cmd */ -- 1.9.1