mirror of
https://git.yoctoproject.org/meta-ti
synced 2026-01-12 09:30:21 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88867c1d96 | ||
|
|
a1e2573369 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,6 +0,0 @@
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.swp
|
||||
*.orig
|
||||
*.rej
|
||||
*~
|
||||
30
README
30
README
@@ -1,4 +1,30 @@
|
||||
Collection of layers for the OE-core universe
|
||||
The official OpenEmbedded/Yocto BSP layer for Texas Instruments platforms.
|
||||
|
||||
Please see the respective READMEs in the layer subdirectories
|
||||
It is hosted on http://git.yoctoproject.org/cgit/cgit.cgi/meta-ti/ with the
|
||||
source repository at git://git.yoctoproject.org/meta-ti
|
||||
|
||||
|
||||
This layer depends on:
|
||||
|
||||
URI: git://git.openembedded.org/openembedded-core
|
||||
layers: meta
|
||||
branch: master
|
||||
|
||||
|
||||
When not depending on meta-openembedded and not using systemd, you may need to
|
||||
mask few miscellaneous recipes requiring systemd, by adding this to local.conf:
|
||||
|
||||
BBMASK = "meta-ti/recipes-misc"
|
||||
|
||||
|
||||
The base BSP part of meta-ti should work with different OpenEmbedded/Yocto
|
||||
distributions and layer stacks, such as:
|
||||
distro-less (only with OE-Core), with Yocto/Poky, with Angstrom or Arago.
|
||||
|
||||
Please follow the recommended setup procedures of your OE distribution.
|
||||
|
||||
|
||||
Send pull requests, patches, comments or questions to meta-ti@yoctoproject.org
|
||||
|
||||
Maintainers: Denys Dmytriyenko <denys@ti.com>
|
||||
Koen Kooi <koen@dominion.thruhere.net>
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"APPEND-1" : {
|
||||
"skip_vars" : [ "ALTERNATIVE", "FILES", "INSANE_SKIP", "RDEPENDS", "RRECOMMENDS" ]
|
||||
},
|
||||
"APPEND-2" : {
|
||||
"skip_vars" : [ "KERNEL_LOCALVERSION", "PR", "PV" ],
|
||||
"file_regex" : {
|
||||
"meta-ti-bsp\\/recipes-graphics\\/mesa\\/mesa-pvr_\\S+\\.bb" : {
|
||||
"skip_vars": [ "GALLIUMDRIVERS", "VULKAN_DRIVERS" ]
|
||||
},
|
||||
"meta-ti-bsp\\/recipes-graphics\\/mesa\\/mesa-pvr\\.inc" : {
|
||||
"skip_vars": [ "TOOLS", "TOOLS_DEPS", "GALLIUMDRIVERS", "VULKAN_DRIVERS" ]
|
||||
}
|
||||
}
|
||||
},
|
||||
"GUARD-1" : {
|
||||
"skip_files" : [
|
||||
"meta-ti-bsp/recipes-core/udev/eudev_%.bbappend",
|
||||
"meta-ti-bsp/recipes-devtools/binutils/binutils-cross-canadian_%.bbappend",
|
||||
"meta-ti-bsp/recipes-security/optee/optee-%.bbappend"
|
||||
]
|
||||
},
|
||||
"GUARD-2" : {
|
||||
"skip_vars" : [ "k3" , "ti-soc" ]
|
||||
},
|
||||
"SUMMARY-1" : {
|
||||
"skip_files" : [
|
||||
"meta-ti-extras/recipes-ti/ipc/ti-ipc-rtos_git.bb"
|
||||
]
|
||||
}
|
||||
}
|
||||
156
classes/sdcard_image.bbclass
Normal file
156
classes/sdcard_image.bbclass
Normal file
@@ -0,0 +1,156 @@
|
||||
inherit image
|
||||
|
||||
# Add the fstypes we need
|
||||
IMAGE_FSTYPES_append = " tar.bz2 sdimg"
|
||||
|
||||
# Ensure required utilities are present
|
||||
IMAGE_DEPENDS_sdimg = "genext2fs-native e2fsprogs-native"
|
||||
|
||||
# Change this to match your host distro
|
||||
LOSETUP ?= "/sbin/losetup"
|
||||
|
||||
# Since these need to go in /etc/fstab we can hardcode them
|
||||
# Since the vars are weakly assigned, you can override them from your local.conf
|
||||
LOOPDEV ?= "/dev/loop1"
|
||||
LOOPDEV_BOOT ?= "/dev/loop2"
|
||||
LOOPDEV_FS ?= "/dev/loop3"
|
||||
|
||||
# Default to 4GiB images
|
||||
SDIMG_SIZE ?= "444"
|
||||
|
||||
# FS type for rootfs
|
||||
ROOTFSTYPE ?= "ext4"
|
||||
|
||||
BOOTPARTNAME_beaglebone = "BEAGLE_BONE"
|
||||
BOOTPARTNAME ?= "${MACHINE}"
|
||||
|
||||
IMAGEDATESTAMP = "${@time.strftime('%Y.%m.%d',time.gmtime())}"
|
||||
|
||||
# Files and/or directories to be copied into the vfat partition
|
||||
FATPAYLOAD ?= ""
|
||||
|
||||
IMAGE_CMD_sdimg () {
|
||||
SDIMG=${WORKDIR}/sd.img
|
||||
|
||||
# sanity check fstab entry for boot partition mounting
|
||||
if [ "x$(cat /etc/fstab | grep ${LOOPDEV_BOOT} | grep ${WORKDIR}/tmp-mnt-boot | grep user || true)" = "x" ]; then
|
||||
echo "/etc/fstab entries need to be created with the user flag for the loop devices like:"
|
||||
echo "${LOOPDEV_BOOT} ${WORKDIR}/tmp-mnt-boot vfat user 0 0"
|
||||
false
|
||||
fi
|
||||
|
||||
# cleanup loops
|
||||
for loop in ${LOOPDEV} ${LOOPDEV_BOOT} ${LOOPDEV_FS} ; do
|
||||
${LOSETUP} -d $loop || true
|
||||
done
|
||||
|
||||
# If an SD image is already present, reuse and reformat it
|
||||
if [ ! -e ${SDIMG} ] ; then
|
||||
dd if=/dev/zero of=${SDIMG} bs=$(echo '255 * 63 * 512' | bc) count=${SDIMG_SIZE}
|
||||
fi
|
||||
|
||||
${LOSETUP} ${LOOPDEV} ${SDIMG}
|
||||
|
||||
# Create partition table
|
||||
dd if=/dev/zero of=${LOOPDEV} bs=1024 count=1024
|
||||
SIZE=$(/sbin/fdisk -l ${LOOPDEV} | grep Disk | grep bytes | awk '{print $5}')
|
||||
CYLINDERS=$(echo $SIZE/255/63/512 | bc)
|
||||
{
|
||||
echo ,9,0x0C,*
|
||||
echo ,,,-
|
||||
} | /sbin/sfdisk -D -H 255 -S 63 -C ${CYLINDERS} ${LOOPDEV}
|
||||
|
||||
# Prepare loop devices for boot and filesystem partitions
|
||||
BOOT_OFFSET=32256
|
||||
FS_OFFSET_SECT=$(/sbin/fdisk -l -u ${LOOPDEV} 2>&1 | grep Linux | perl -p -i -e "s/\s+/ /"|cut -d " " -f 2)
|
||||
FS_OFFSET=$(echo "$FS_OFFSET_SECT * 512" | bc)
|
||||
FS_SIZE_BLOCKS=$(/sbin/fdisk -l -u ${LOOPDEV} 2>&1 | grep Linux | perl -p -i -e "s/\s+/ /g" \
|
||||
|cut -d " " -f 4 | cut -d "+" -f 1)
|
||||
|
||||
LOOPDEV_BLOCKS=$(/sbin/fdisk -l -u ${LOOPDEV} 2>&1 | grep FAT | perl -p -i -e "s/\s+/ /g"|cut -d " " -f 5)
|
||||
LOOPDEV_BYTES=$(echo "$LOOPDEV_BLOCKS * 1024" | bc)
|
||||
|
||||
${LOSETUP} -d ${LOOPDEV}
|
||||
|
||||
${LOSETUP} ${LOOPDEV_BOOT} ${SDIMG} -o ${BOOT_OFFSET}
|
||||
|
||||
/sbin/mkfs.vfat ${LOOPDEV_BOOT} -n ${BOOTPARTNAME} $LOOPDEV_BLOCKS
|
||||
|
||||
# Prepare filesystem partition
|
||||
# Copy ubi used by flashing scripts
|
||||
if [ -e ${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.rootfs.ubi ] ; then
|
||||
echo "Copying UBIFS image to file system"
|
||||
cp ${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.rootfs.ubi ${IMAGE_ROOTFS}/boot/fs.ubi
|
||||
fi
|
||||
|
||||
# Prepare boot partion. First mount the boot partition, and copy the boot loader and supporting files
|
||||
# from the root filesystem
|
||||
|
||||
mkdir -p ${WORKDIR}/tmp-mnt-boot
|
||||
mount $LOOPDEV_BOOT ${WORKDIR}/tmp-mnt-boot
|
||||
|
||||
echo "Copying bootloaders into the boot partition"
|
||||
if [ -e ${IMAGE_ROOTFS}/boot/MLO ] ; then
|
||||
cp -v ${IMAGE_ROOTFS}/boot/MLO ${WORKDIR}/tmp-mnt-boot
|
||||
else
|
||||
cp -v ${DEPLOY_DIR_IMAGE}/MLO ${WORKDIR}/tmp-mnt-boot
|
||||
fi
|
||||
|
||||
# Check for u-boot SPL
|
||||
if [ -e ${DEPLOY_DIR_IMAGE}/u-boot-${MACHINE}.img ] ; then
|
||||
suffix=img
|
||||
else
|
||||
suffix=bin
|
||||
fi
|
||||
|
||||
cp -v ${IMAGE_ROOTFS}/boot/uEnv.txt ${WORKDIR}/tmp-mnt-boot || true
|
||||
cp -v ${IMAGE_ROOTFS}/boot/user.txt ${WORKDIR}/tmp-mnt-boot || true
|
||||
cp -v ${IMAGE_ROOTFS}/boot/uImage ${WORKDIR}/tmp-mnt-boot || true
|
||||
|
||||
if [ -e ${IMAGE_ROOTFS}/boot/u-boot.$suffix ] ; then
|
||||
cp -v ${IMAGE_ROOTFS}/boot/{u-boot.$suffix} ${WORKDIR}/tmp-mnt-boot || true
|
||||
else
|
||||
cp -v ${DEPLOY_DIR_IMAGE}/u-boot-${MACHINE}.$suffix ${WORKDIR}/tmp-mnt-boot/u-boot.$suffix
|
||||
fi
|
||||
|
||||
if [ -n ${FATPAYLOAD} ] ; then
|
||||
echo "Copying payload into VFAT"
|
||||
for entry in ${FATPAYLOAD} ; do
|
||||
# add the || true to stop aborting on vfat issues like not supporting .~lock files
|
||||
cp -av ${IMAGE_ROOTFS}$entry ${WORKDIR}/tmp-mnt-boot || true
|
||||
done
|
||||
fi
|
||||
|
||||
echo "${IMAGE_NAME}-${IMAGEDATESTAMP}" > ${IMAGE_ROOTFS}/etc/image-version-info
|
||||
|
||||
# Cleanup VFAT mount
|
||||
echo "Cleaning up VFAT mount"
|
||||
umount ${WORKDIR}/tmp-mnt-boot
|
||||
${LOSETUP} -d ${LOOPDEV_BOOT} || true
|
||||
|
||||
# Prepare rootfs parition
|
||||
echo "Creating rootfs loopback"
|
||||
${LOSETUP} ${LOOPDEV_FS} ${SDIMG} -o ${FS_OFFSET}
|
||||
|
||||
FS_NUM_INODES=$(echo $FS_SIZE_BLOCKS / 4 | bc)
|
||||
|
||||
case "${ROOTFSTYPE}" in
|
||||
ext3)
|
||||
genext2fs -z -N $FS_NUM_INODES -b $FS_SIZE_BLOCKS -d ${IMAGE_ROOTFS} ${LOOPDEV_FS}
|
||||
tune2fs -L ${IMAGE_NAME} -j ${LOOPDEV_FS}
|
||||
;;
|
||||
ext4)
|
||||
genext2fs -z -N $FS_NUM_INODES -b $FS_SIZE_BLOCKS -d ${IMAGE_ROOTFS} ${LOOPDEV_FS}
|
||||
tune2fs -L ${IMAGE_NAME} -j -O extents,uninit_bg,dir_index ${LOOPDEV_FS}
|
||||
;;
|
||||
*)
|
||||
echo "Please set ROOTFSTYPE to something supported"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
${LOSETUP} -d ${LOOPDEV_FS} || true
|
||||
|
||||
gzip -c ${WORKDIR}/sd.img > ${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}-${IMAGEDATESTAMP}.img.gz
|
||||
rm -f ${WORKDIR}/sd.img
|
||||
}
|
||||
9
conf/layer.conf
Normal file
9
conf/layer.conf
Normal file
@@ -0,0 +1,9 @@
|
||||
# We have a conf and classes directory, append to BBPATH
|
||||
BBPATH .= ":${LAYERDIR}"
|
||||
|
||||
# We have a recipes directory, add to BBFILES
|
||||
BBFILES += "${LAYERDIR}/recipes*/*/*.bb ${LAYERDIR}/recipes*/*/*.bbappend"
|
||||
|
||||
BBFILE_COLLECTIONS += "meta-ti"
|
||||
BBFILE_PATTERN_meta-ti := "^${LAYERDIR}/"
|
||||
BBFILE_PRIORITY_meta-ti = "10"
|
||||
17
conf/machine/am180x-evm.conf
Normal file
17
conf/machine/am180x-evm.conf
Normal file
@@ -0,0 +1,17 @@
|
||||
#@TYPE: Machine
|
||||
#@NAME: AM180x CPUs on an AM180x EVM board
|
||||
#@DESCRIPTION: Machine configuration for the TI AM180x EVM board
|
||||
|
||||
require conf/machine/include/davinci.inc
|
||||
require conf/machine/include/omapl138.inc
|
||||
|
||||
UBOOT_MACHINE = "da850evm_config"
|
||||
UBOOT_ENTRYPOINT = "0xc0008000"
|
||||
UBOOT_LOADADDRESS = "0xc0008000"
|
||||
|
||||
MACHINE_FEATURES = "kernel26 serial ethernet"
|
||||
|
||||
SERIAL_CONSOLE = "115200 ttyS2"
|
||||
|
||||
PREFERRED_PROVIDER_virtual/kernel = "linux-omapl138-psp"
|
||||
PREFERRED_PROVIDER_virtual/bootloader = "u-boot"
|
||||
@@ -1,15 +1,22 @@
|
||||
#@TYPE: Machine
|
||||
#@NAME: AM335x EVM
|
||||
#@DESCRIPTION: Machine configuration for the TI AM335x EVM
|
||||
TARGET_ARCH = "arm"
|
||||
|
||||
PREFERRED_PROVIDER_virtual/xserver = "xserver-xorg"
|
||||
XSERVER = "xserver-xorg \
|
||||
xf86-input-evdev \
|
||||
xf86-video-fbdev"
|
||||
|
||||
GUI_MACHINE_CLASS = "smallscreen"
|
||||
|
||||
require conf/machine/include/ti33x.inc
|
||||
|
||||
MACHINE_FEATURES += "screen touchscreen"
|
||||
IMAGE_FSTYPES += "ubi tar.bz2"
|
||||
|
||||
IMAGE_FSTYPES += "ubifs ubi"
|
||||
SERIAL_CONSOLE = "115200 ttyO0"
|
||||
|
||||
# Normally AM335 boards use ttyS0, but ICE uses ttyS3, so try both
|
||||
SERIAL_CONSOLES = "115200;ttyS0 115200;ttyS3"
|
||||
PREFERRED_PROVIDER_virtual/kernel = "linux-ti33x-psp"
|
||||
|
||||
# UBI information. Note that this is board and kernel specific. Changes
|
||||
# in your kernel port may require changes in these variables. For more
|
||||
@@ -22,7 +29,7 @@ SERIAL_CONSOLES = "115200;ttyS0 115200;ttyS3"
|
||||
# UBI: logical eraseblock size: 126976 bytes
|
||||
# from ubiattach stdout:
|
||||
# UBI device number 0, total 1988 LEBs
|
||||
MKUBIFS_ARGS ?= "-F -m 2048 -e 126976 -c 16000"
|
||||
MKUBIFS_ARGS = "-F -m 2048 -e 126976 -c 1988"
|
||||
|
||||
# do ubiattach /dev/ubi_ctrl -m 7 -O 2048
|
||||
# from dmesg:
|
||||
@@ -30,4 +37,11 @@ MKUBIFS_ARGS ?= "-F -m 2048 -e 126976 -c 16000"
|
||||
# UBI: physical eraseblock size: 131072 bytes (128 KiB)
|
||||
# UBI: sub-page size: 512
|
||||
# UBI: VID header offset: 2048 (aligned 2048)
|
||||
UBINIZE_ARGS ?= "-m 2048 -p 128KiB -s 512 -O 2048"
|
||||
UBINIZE_ARGS = "-m 2048 -p 128KiB -s 512 -O 2048"
|
||||
|
||||
PREFERRED_PROVIDER_virtual/bootloader = "u-boot"
|
||||
|
||||
UBOOT_ARCH = "arm"
|
||||
UBOOT_MACHINE = "am335x_evm_config"
|
||||
|
||||
MACHINE_FEATURES = "kernel26 apm usbgadget usbhost vfat ext2 screen touchscreen"
|
||||
50
conf/machine/am37x-evm.conf
Normal file
50
conf/machine/am37x-evm.conf
Normal file
@@ -0,0 +1,50 @@
|
||||
#@TYPE: Machine
|
||||
#@NAME: AM37x EVM
|
||||
#@DESCRIPTION: Machine configuration for the TI AM37x EVM
|
||||
|
||||
PREFERRED_PROVIDER_virtual/xserver = "xserver-xorg"
|
||||
XSERVER = "xserver-xorg \
|
||||
xf86-input-evdev \
|
||||
xf86-input-mouse \
|
||||
xf86-input-tslib \
|
||||
xf86-video-omapfb \
|
||||
xf86-input-keyboard"
|
||||
|
||||
GUI_MACHINE_CLASS = "smallscreen"
|
||||
|
||||
require conf/machine/include/omap3.inc
|
||||
|
||||
# Ship all kernel modules
|
||||
|
||||
IMAGE_FSTYPES += "jffs2 tar.bz2"
|
||||
EXTRA_IMAGECMD_jffs2 = "-lnp -e 0x20000 -s 2048"
|
||||
|
||||
SERIAL_CONSOLE = "115200 ttyS0"
|
||||
|
||||
PREFERRED_PROVIDER_virtual/kernel = "linux-omap-psp"
|
||||
|
||||
PREFERRED_PROVIDER_virtual/bootloader = "u-boot"
|
||||
|
||||
UBOOT_ARCH = "arm"
|
||||
UBOOT_MACHINE = "omap3_evm_config"
|
||||
XLOAD_MACHINE = "omap3evm_config"
|
||||
|
||||
MACHINE_FEATURES = "kernel26 apm usbgadget usbhost vfat ext2 screen touchscreen"
|
||||
|
||||
# NOTE: there are NAND and OneNAND versions of this board...
|
||||
|
||||
# do ubiattach /dev/ubi_ctrl -m 4
|
||||
# From dmesg:
|
||||
# UBI: smallest flash I/O unit: 2048
|
||||
# UBI: logical eraseblock size: 129024 bytes
|
||||
# from ubiattach stdout:
|
||||
# UBI device number 0, total 1996 LEBs
|
||||
MKUBIFS_ARGS = "-m 2048 -e 129024 -c 1996"
|
||||
|
||||
# do ubiattach /dev/ubi_ctrl -m 4
|
||||
# from dmesg:
|
||||
# UBI: smallest flash I/O unit: 2048
|
||||
# UBI: physical eraseblock size: 131072 bytes (128 KiB)
|
||||
# UBI: sub-page size: 512
|
||||
UBINIZE_ARGS = "-m 2048 -p 128KiB -s 512"
|
||||
|
||||
51
conf/machine/beagleboard.conf
Normal file
51
conf/machine/beagleboard.conf
Normal file
@@ -0,0 +1,51 @@
|
||||
#@TYPE: Machine
|
||||
#@NAME: Beagleboard machine
|
||||
#@DESCRIPTION: Machine configuration for the http://beagleboard.org/ board
|
||||
|
||||
PREFERRED_PROVIDER_virtual/xserver = "xserver-xorg"
|
||||
XSERVER = "xserver-xorg \
|
||||
xf86-input-evdev \
|
||||
xf86-input-mouse \
|
||||
xf86-video-omapfb \
|
||||
xf86-input-keyboard"
|
||||
|
||||
# Only has DVI connector for external screen
|
||||
GUI_MACHINE_CLASS = "bigscreen"
|
||||
|
||||
require conf/machine/include/omap3.inc
|
||||
|
||||
# SPL build
|
||||
EXTRA_IMAGEDEPENDS = "u-boot"
|
||||
|
||||
PREFERRED_PROVIDER_virtual/kernel = "linux-mainline"
|
||||
|
||||
IMAGE_FSTYPES += "tar.bz2 ubi"
|
||||
EXTRA_IMAGECMD_jffs2 = "-lnp "
|
||||
|
||||
# Guesswork
|
||||
SERIAL_CONSOLE = "115200 ttyO2"
|
||||
|
||||
UBOOT_MACHINE = "omap3_beagle_config"
|
||||
|
||||
# do ubiattach /dev/ubi_ctrl -m 4
|
||||
# From dmesg:
|
||||
# UBI: smallest flash I/O unit: 2048
|
||||
# UBI: logical eraseblock size: 129024 bytes
|
||||
# from ubiattach stdout:
|
||||
# UBI device number 0, total 1996 LEBs
|
||||
#
|
||||
# Beagleboard C5 has 3998 LEBS (490MiB)
|
||||
MKUBIFS_ARGS = "-m 2048 -e 129024 -c 1996"
|
||||
|
||||
# do ubiattach /dev/ubi_ctrl -m 4
|
||||
# from dmesg:
|
||||
# UBI: smallest flash I/O unit: 2048
|
||||
# UBI: physical eraseblock size: 131072 bytes (128 KiB)
|
||||
# UBI: sub-page size: 512
|
||||
UBINIZE_ARGS = "-m 2048 -p 128KiB -s 512"
|
||||
|
||||
# and sdio
|
||||
MACHINE_FEATURES = "kernel26 screen apm usbgadget usbhost vfat alsa"
|
||||
|
||||
# For a modularized kernel we want to drag in networking, sound, rtc etc."
|
||||
MACHINE_EXTRA_RRECOMMENDS = "kernel-module-smsc95xx kernel-module-snd-soc-twl4030 kernel-module-rtc-twl"
|
||||
26
conf/machine/beaglebone.conf
Normal file
26
conf/machine/beaglebone.conf
Normal file
@@ -0,0 +1,26 @@
|
||||
#@TYPE: Machine
|
||||
#@NAME: BeagleBone machine
|
||||
#@DESCRIPTION: Machine configuration for the http://beagleboard.org/bone board
|
||||
|
||||
PREFERRED_PROVIDER_virtual/xserver = "xserver-xorg"
|
||||
XSERVER = "xserver-xorg \
|
||||
xf86-input-evdev \
|
||||
xf86-video-fbdev"
|
||||
|
||||
# Only has DVI connector for external screen
|
||||
GUI_MACHINE_CLASS = "bigscreen"
|
||||
|
||||
require conf/machine/include/ti33x.inc
|
||||
EXTRA_IMAGEDEPENDS = "u-boot"
|
||||
|
||||
PREFERRED_PROVIDER_virtual/kernel = "linux-ti33x-psp"
|
||||
|
||||
IMAGE_FSTYPES += "tar.bz2 "
|
||||
|
||||
# Guesswork
|
||||
SERIAL_CONSOLE = "115200 ttyO0"
|
||||
|
||||
UBOOT_MACHINE = "am335x_evm_config"
|
||||
|
||||
# and sdio
|
||||
MACHINE_FEATURES = "kernel26 screen apm usbgadget usbhost vfat alsa"
|
||||
15
conf/machine/include/omap3.inc
Normal file
15
conf/machine/include/omap3.inc
Normal file
@@ -0,0 +1,15 @@
|
||||
SOC_FAMILY = "omap3"
|
||||
require conf/machine/include/soc-family.inc
|
||||
|
||||
require conf/machine/include/tune-cortexa8.inc
|
||||
PREFERRED_PROVIDER_virtual/kernel = "linux-omap"
|
||||
# Increase this everytime you change something in the kernel
|
||||
MACHINE_KERNEL_PR = "r121"
|
||||
|
||||
KERNEL_IMAGETYPE = "uImage"
|
||||
|
||||
UBOOT_ENTRYPOINT = "0x80008000"
|
||||
UBOOT_LOADADDRESS = "0x80008000"
|
||||
|
||||
EXTRA_IMAGEDEPENDS += "u-boot x-load"
|
||||
|
||||
25
conf/machine/include/omap4.inc
Normal file
25
conf/machine/include/omap4.inc
Normal file
@@ -0,0 +1,25 @@
|
||||
SOC_FAMILY = "omap4"
|
||||
require conf/machine/include/soc-family.inc
|
||||
|
||||
require conf/machine/include/tune-cortexa9.inc
|
||||
|
||||
PREFERRED_PROVIDER_virtual/kernel = "linux-omap4"
|
||||
PREFERRED_PROVIDER_virtual/bootloader = "u-boot"
|
||||
|
||||
PREFERRED_PROVIDER_virtual/xserver = "xserver-xorg"
|
||||
XSERVER = "xserver-xorg \
|
||||
xserver-xorg-extension-dri \
|
||||
xserver-xorg-extension-dri2 \
|
||||
xserver-xorg-extension-glx \
|
||||
xf86-input-evdev \
|
||||
xf86-video-fbdev"
|
||||
|
||||
# Increase this everytime you change something in the kernel
|
||||
MACHINE_KERNEL_PR = "r1"
|
||||
|
||||
KERNEL_IMAGETYPE = "uImage"
|
||||
|
||||
UBOOT_ENTRYPOINT = "0x80008000"
|
||||
UBOOT_LOADADDRESS = "0x80008000"
|
||||
|
||||
EXTRA_IMAGEDEPENDS += "u-boot"
|
||||
2
conf/machine/include/omapl138.inc
Normal file
2
conf/machine/include/omapl138.inc
Normal file
@@ -0,0 +1,2 @@
|
||||
SOC_FAMILY = "omapl138"
|
||||
require conf/machine/include/soc-family.inc
|
||||
14
conf/machine/include/ti33x.inc
Normal file
14
conf/machine/include/ti33x.inc
Normal file
@@ -0,0 +1,14 @@
|
||||
SOC_FAMILY = "ti33x"
|
||||
require conf/machine/include/soc-family.inc
|
||||
|
||||
require conf/machine/include/tune-cortexa8.inc
|
||||
PREFERRED_PROVIDER_virtual/kernel = "linux-ti33x-psp"
|
||||
# Increase this everytime you change something in the kernel
|
||||
MACHINE_KERNEL_PR = "r12"
|
||||
|
||||
KERNEL_IMAGETYPE = "uImage"
|
||||
|
||||
UBOOT_ENTRYPOINT = "0x80008000"
|
||||
UBOOT_LOADADDRESS = "0x80008000"
|
||||
|
||||
EXTRA_IMAGEDEPENDS += "u-boot"
|
||||
52
conf/machine/omap3evm.conf
Normal file
52
conf/machine/omap3evm.conf
Normal file
@@ -0,0 +1,52 @@
|
||||
#@TYPE: Machine
|
||||
#@NAME: OMAP3 EVM
|
||||
#@DESCRIPTION: Machine configuration for the TI OMAP3 EVM
|
||||
TARGET_ARCH = "arm"
|
||||
|
||||
PREFERRED_PROVIDER_virtual/xserver = "xserver-xorg"
|
||||
XSERVER = "xserver-xorg \
|
||||
xf86-input-evdev \
|
||||
xf86-input-mouse \
|
||||
xf86-input-tslib \
|
||||
xf86-video-omapfb \
|
||||
xf86-input-keyboard"
|
||||
|
||||
GUI_MACHINE_CLASS = "smallscreen"
|
||||
|
||||
require conf/machine/include/omap3.inc
|
||||
|
||||
# Ship all kernel modules
|
||||
|
||||
IMAGE_FSTYPES += "jffs2 tar.bz2"
|
||||
EXTRA_IMAGECMD_jffs2 = "-lnp -e 0x20000 -s 2048"
|
||||
|
||||
SERIAL_CONSOLE = "115200 ttyS0"
|
||||
USE_VT = "0"
|
||||
|
||||
PREFERRED_PROVIDER_virtual/kernel = "linux-omap-psp"
|
||||
|
||||
PREFERRED_PROVIDER_virtual/bootloader = "u-boot"
|
||||
|
||||
UBOOT_ARCH = "arm"
|
||||
UBOOT_MACHINE = "omap3_evm_config"
|
||||
XLOAD_MACHINE = "omap3evm_config"
|
||||
|
||||
MACHINE_FEATURES = "kernel26 apm usbgadget usbhost vfat ext2 screen touchscreen"
|
||||
|
||||
# NOTE: there are NAND and OneNAND versions of this board...
|
||||
|
||||
# do ubiattach /dev/ubi_ctrl -m 4
|
||||
# From dmesg:
|
||||
# UBI: smallest flash I/O unit: 2048
|
||||
# UBI: logical eraseblock size: 129024 bytes
|
||||
# from ubiattach stdout:
|
||||
# UBI device number 0, total 1996 LEBs
|
||||
MKUBIFS_ARGS = "-m 2048 -e 129024 -c 1996"
|
||||
|
||||
# do ubiattach /dev/ubi_ctrl -m 4
|
||||
# from dmesg:
|
||||
# UBI: smallest flash I/O unit: 2048
|
||||
# UBI: physical eraseblock size: 131072 bytes (128 KiB)
|
||||
# UBI: sub-page size: 512
|
||||
UBINIZE_ARGS = "-m 2048 -p 128KiB -s 512"
|
||||
|
||||
18
conf/machine/pandaboard.conf
Normal file
18
conf/machine/pandaboard.conf
Normal file
@@ -0,0 +1,18 @@
|
||||
#@TYPE: Machine
|
||||
#@NAME: Pandaboard
|
||||
#@DESCRIPTION: Machine configuration for the OMAP4430 Panda
|
||||
|
||||
require conf/machine/include/omap4.inc
|
||||
|
||||
UBOOT_MACHINE = "omap4_panda_config"
|
||||
|
||||
GUI_MACHINE_CLASS = "bigscreen"
|
||||
|
||||
IMAGE_FSTYPES += "tar.bz2"
|
||||
|
||||
SERIAL_CONSOLE = "115200 ttyO2"
|
||||
|
||||
MACHINE_EXTRA_RRECOMMENDS = " kernel-modules"
|
||||
MACHINE_FEATURES = "kernel26 wifi bluetooth alsa apm ext2 screen touchscreen usbgadget usbhost vfat"
|
||||
|
||||
|
||||
17
extras/README
Normal file
17
extras/README
Normal file
@@ -0,0 +1,17 @@
|
||||
An "extras" (AKA best-effort) layer for meta-ti
|
||||
|
||||
This layer depends on:
|
||||
|
||||
URI: git://git.openembedded.org/openembedded-core
|
||||
layers: meta
|
||||
branch: master
|
||||
|
||||
URI: git://git.yoctoproject.org/meta-ti
|
||||
layers: meta
|
||||
branch: master
|
||||
|
||||
|
||||
Send pull requests, patches, comments or questions to meta-ti@yoctoproject.org
|
||||
|
||||
Maintainers: Denys Dmytriyenko <denys@ti.com>
|
||||
Koen Kooi <koen@dominion.thruhere.net>
|
||||
9
extras/conf/layer.conf
Normal file
9
extras/conf/layer.conf
Normal file
@@ -0,0 +1,9 @@
|
||||
# We have a conf and classes directory, append to BBPATH
|
||||
BBPATH .= ":${LAYERDIR}"
|
||||
|
||||
# We have a recipes directory, add to BBFILES
|
||||
BBFILES += "${LAYERDIR}/recipes*/*/*.bb ${LAYERDIR}/recipes*/*/*.bbappend"
|
||||
|
||||
BBFILE_COLLECTIONS += "meta-ti-extras"
|
||||
BBFILE_PATTERN_meta-ti := "^${LAYERDIR}/"
|
||||
BBFILE_PRIORITY_meta-ti = "10"
|
||||
51
extras/conf/machine/am3517-evm.conf
Normal file
51
extras/conf/machine/am3517-evm.conf
Normal file
@@ -0,0 +1,51 @@
|
||||
#@TYPE: Machine
|
||||
#@NAME: AM3517 EVM
|
||||
#@DESCRIPTION: Machine configuration for the TI Sitara AM3517 EVM
|
||||
|
||||
PREFERRED_PROVIDER_virtual/xserver = "xserver-xorg"
|
||||
XSERVER = "xserver-xorg \
|
||||
xf86-input-evdev \
|
||||
xf86-input-mouse \
|
||||
xf86-input-tslib \
|
||||
xf86-video-omapfb \
|
||||
xf86-input-keyboard"
|
||||
|
||||
GUI_MACHINE_CLASS = "smallscreen"
|
||||
|
||||
require conf/machine/include/omap3.inc
|
||||
|
||||
# Ship all kernel modules
|
||||
|
||||
IMAGE_FSTYPES += "ubi tar.bz2"
|
||||
EXTRA_IMAGECMD_jffs2 = "-lnp -e 0x20000 -s 2048"
|
||||
|
||||
SERIAL_CONSOLE = "115200 ttyS2"
|
||||
USE_VT = "2"
|
||||
|
||||
PREFERRED_PROVIDER_virtual/kernel = "linux-omap-psp"
|
||||
|
||||
PREFERRED_PROVIDER_virtual/bootloader = "u-boot"
|
||||
|
||||
UBOOT_ARCH = "arm"
|
||||
UBOOT_MACHINE = "am3517_evm_config"
|
||||
XLOAD_MACHINE = "am3517evm_config"
|
||||
|
||||
MACHINE_FEATURES = "kernel26 apm usbgadget usbhost vfat ext2 screen touchscreen ethernet"
|
||||
|
||||
# NOTE: there are NAND and OneNAND versions of this board...
|
||||
|
||||
# do ubiattach /dev/ubi_ctrl -m 4
|
||||
# From dmesg:
|
||||
# UBI: smallest flash I/O unit: 2048
|
||||
# UBI: logical eraseblock size: 129024 bytes
|
||||
# from ubiattach stdout:
|
||||
# UBI device number 0, total 1996 LEBs
|
||||
MKUBIFS_ARGS = "-m 2048 -e 129024 -c 1996"
|
||||
|
||||
# do ubiattach /dev/ubi_ctrl -m 4
|
||||
# from dmesg:
|
||||
# UBI: smallest flash I/O unit: 2048
|
||||
# UBI: physical eraseblock size: 131072 bytes (128 KiB)
|
||||
# UBI: sub-page size: 512
|
||||
UBINIZE_ARGS = "-m 2048 -p 128KiB -s 512"
|
||||
|
||||
5
extras/conf/machine/am387x-evm.conf
Normal file
5
extras/conf/machine/am387x-evm.conf
Normal file
@@ -0,0 +1,5 @@
|
||||
#@TYPE: Machine
|
||||
#@NAME: AM389x evm
|
||||
#@DESCRIPTION: Machine configuration for the AM389x evm
|
||||
|
||||
require conf/machine/include/ti814x.inc
|
||||
5
extras/conf/machine/am389x-evm.conf
Normal file
5
extras/conf/machine/am389x-evm.conf
Normal file
@@ -0,0 +1,5 @@
|
||||
#@TYPE: Machine
|
||||
#@NAME: am389x evm
|
||||
#@DESCRIPTION: Machine configuration for the am389x evm
|
||||
|
||||
require conf/machine/include/ti816x.inc
|
||||
5
extras/conf/machine/c6a814x-evm.conf
Normal file
5
extras/conf/machine/c6a814x-evm.conf
Normal file
@@ -0,0 +1,5 @@
|
||||
#@TYPE: Machine
|
||||
#@NAME: c6a814x evm
|
||||
#@DESCRIPTION: Machine configuration for the c6a814x evm
|
||||
|
||||
require conf/machine/include/ti814x.inc
|
||||
5
extras/conf/machine/c6a816x-evm.conf
Normal file
5
extras/conf/machine/c6a816x-evm.conf
Normal file
@@ -0,0 +1,5 @@
|
||||
#@TYPE: Machine
|
||||
#@NAME: c6a816x evm
|
||||
#@DESCRIPTION: Machine configuration for the c6a816x evm
|
||||
|
||||
require conf/machine/include/ti816x.inc
|
||||
5
extras/conf/machine/dm814x-evm.conf
Normal file
5
extras/conf/machine/dm814x-evm.conf
Normal file
@@ -0,0 +1,5 @@
|
||||
#@TYPE: Machine
|
||||
#@NAME: DM814x evm
|
||||
#@DESCRIPTION: Machine configuration for the DM814x evm
|
||||
|
||||
require conf/machine/include/ti814x.inc
|
||||
29
extras/conf/machine/hawkboard.conf
Normal file
29
extras/conf/machine/hawkboard.conf
Normal file
@@ -0,0 +1,29 @@
|
||||
#@TYPE: Machine
|
||||
#@NAME: OMAP-L138 based board
|
||||
#@DESCRIPTION: Machine configuration for the TI Hawkboard
|
||||
|
||||
require conf/machine/include/davinci.inc
|
||||
require conf/machine/include/omapl138.inc
|
||||
|
||||
UBOOT_MACHINE = "da850_omapl138_evm_config"
|
||||
UBOOT_ENTRYPOINT = "0xc0008000"
|
||||
UBOOT_LOADADDRESS = "0xc0008000"
|
||||
|
||||
MACHINE_FEATURES = "kernel26 serial ethernet ide screen"
|
||||
|
||||
# do ubiattach /dev/ubi_ctrl -m 4
|
||||
# From dmesg:
|
||||
# UBI: smallest flash I/O unit: 2048
|
||||
# UBI: logical eraseblock size: 126976 bytes
|
||||
# from ubiattach stdout:
|
||||
# UBI device number 0, total 971 LEBs (123293696 bytes, 117.6 MiB), available 958 LEBs (121643008 bytes, 116.0 MiB), LEB size 126976 bytes (124.0 KiB)
|
||||
MKUBIFS_ARGS = "-m 2048 -e 126976 -c 948"
|
||||
|
||||
# do ubiattach /dev/ubi_ctrl -m 4
|
||||
# from dmesg:
|
||||
# UBI: smallest flash I/O unit: 2048
|
||||
# UBI: physical eraseblock size: 131072 bytes (128 KiB)
|
||||
# UBI: sub-page size: 512
|
||||
UBINIZE_ARGS = "-m 2048 -p 128KiB -s 512"
|
||||
|
||||
SERIAL_CONSOLE = "115200 ttyS2"
|
||||
24
extras/conf/machine/include/davinci.inc
Normal file
24
extras/conf/machine/include/davinci.inc
Normal file
@@ -0,0 +1,24 @@
|
||||
require conf/machine/include/tune-arm926ejs.inc
|
||||
|
||||
# Increase this everytime you change something in the kernel
|
||||
MACHINE_KERNEL_PR = "r51"
|
||||
|
||||
|
||||
KERNEL_IMAGETYPE = "uImage"
|
||||
|
||||
PREFERRED_PROVIDER_virtual/kernel = "linux-davinci"
|
||||
|
||||
PREFERRED_PROVIDER_virtual/bootloader = "u-boot"
|
||||
UBOOT_MACHINE = "davinci_dvevm_config"
|
||||
|
||||
UBOOT_ENTRYPOINT = "0x80008000"
|
||||
UBOOT_LOADADDRESS = "0x80008000"
|
||||
|
||||
EXTRA_IMAGEDEPENDS += "u-boot"
|
||||
|
||||
SERIAL_CONSOLE ?= "115200 ttyS0"
|
||||
EXTRA_IMAGECMD_jffs2 = "--pad --little-endian --eraseblock=0x20000 -n"
|
||||
|
||||
#ROOT_FLASH_SIZE = "29"
|
||||
|
||||
MACHINE_FEATURES = "kernel26 serial ethernet usbhost usbgadget mmc alsa"
|
||||
26
extras/conf/machine/include/ti814x.inc
Normal file
26
extras/conf/machine/include/ti814x.inc
Normal file
@@ -0,0 +1,26 @@
|
||||
SOC_FAMILY = "ti814x"
|
||||
require conf/machine/include/soc-family.inc
|
||||
|
||||
require conf/machine/include/tune-cortexa8.inc
|
||||
|
||||
PREFERRED_PROVIDER_virtual/kernel = "linux-ti81xx-psp"
|
||||
PREFERRED_PROVIDER_virtual/bootloader = "u-boot"
|
||||
|
||||
# Increase this everytime you change something in the kernel
|
||||
MACHINE_KERNEL_PR = "r2"
|
||||
|
||||
KERNEL_IMAGETYPE = "uImage"
|
||||
|
||||
UBOOT_ARCH = "arm"
|
||||
UBOOT_MACHINE = "ti8148_evm_config_nand"
|
||||
UBOOT_ENTRYPOINT = "0x80008000"
|
||||
UBOOT_LOADADDRESS = "0x80008000"
|
||||
|
||||
# Only build u-boot
|
||||
EXTRA_IMAGEDEPENDS += "u-boot"
|
||||
|
||||
# Ship all kernel modules
|
||||
IMAGE_FSTYPES += "jffs2 tar.bz2"
|
||||
EXTRA_IMAGECMD_jffs2 = "-lqn -e 128"
|
||||
SERIAL_CONSOLE = "115200 ttyO0"
|
||||
MACHINE_FEATURES = "kernel26 apm usbgadget usbhost vfat ext2 ethernet"
|
||||
26
extras/conf/machine/include/ti816x.inc
Normal file
26
extras/conf/machine/include/ti816x.inc
Normal file
@@ -0,0 +1,26 @@
|
||||
SOC_FAMILY = "ti816x"
|
||||
require conf/machine/include/soc-family.inc
|
||||
|
||||
require conf/machine/include/tune-cortexa8.inc
|
||||
|
||||
PREFERRED_PROVIDER_virtual/kernel = "linux-ti81xx-psp"
|
||||
PREFERRED_PROVIDER_virtual/bootloader = "u-boot"
|
||||
|
||||
# Increase this everytime you change something in the kernel
|
||||
MACHINE_KERNEL_PR = "r2"
|
||||
|
||||
KERNEL_IMAGETYPE = "uImage"
|
||||
|
||||
UBOOT_ARCH = "arm"
|
||||
UBOOT_MACHINE = "ti8168_evm_config"
|
||||
UBOOT_ENTRYPOINT = "0x80008000"
|
||||
UBOOT_LOADADDRESS = "0x80008000"
|
||||
|
||||
# Only build u-boot
|
||||
EXTRA_IMAGEDEPENDS += "u-boot"
|
||||
|
||||
# Ship all kernel modules
|
||||
IMAGE_FSTYPES += "jffs2 tar.bz2"
|
||||
EXTRA_IMAGECMD_jffs2 = "-lqn -e 128"
|
||||
SERIAL_CONSOLE = "115200 ttyO2"
|
||||
MACHINE_FEATURES = "kernel26 apm usbgadget usbhost vfat ext2 ethernet"
|
||||
49
extras/conf/machine/omap3-touchbook.conf
Normal file
49
extras/conf/machine/omap3-touchbook.conf
Normal file
@@ -0,0 +1,49 @@
|
||||
#@TYPE: Machine
|
||||
#@NAME: Always Innovating touchbook
|
||||
#@DESCRIPTION: Machine configuration for the http://www.alwaysinnovating.com/touchbook/
|
||||
TARGET_ARCH = "arm"
|
||||
|
||||
PREFERRED_PROVIDER_virtual/xserver = "xserver-xorg"
|
||||
XSERVER = "xserver-xorg \
|
||||
xf86-input-evdev \
|
||||
xf86-input-mouse \
|
||||
xf86-input-tslib \
|
||||
xf86-video-fbdev \
|
||||
xf86-video-omapfb \
|
||||
xf86-input-keyboard"
|
||||
|
||||
# Only has DVI connector for external screen
|
||||
GUI_MACHINE_CLASS = "bigscreen"
|
||||
|
||||
require conf/machine/include/omap3.inc
|
||||
|
||||
PREFERRED_PROVIDER_virtual/kernel = "linux-omap-psp"
|
||||
|
||||
IMAGE_FSTYPES += "tar.bz2"
|
||||
EXTRA_IMAGECMD_jffs2 = "-lnp "
|
||||
|
||||
# Guesswork
|
||||
SERIAL_CONSOLE = "115200 ttyS2"
|
||||
|
||||
UBOOT_MACHINE = "omap3_beagle_config"
|
||||
XLOAD_MACHINE = "beagleboard_config"
|
||||
|
||||
# do ubiattach /dev/ubi_ctrl -m 4
|
||||
# From dmesg:
|
||||
# UBI: smallest flash I/O unit: 2048
|
||||
# UBI: logical eraseblock size: 129024 bytes
|
||||
# from ubiattach stdout:
|
||||
# UBI device number 0, total 1996 LEBs
|
||||
MKUBIFS_ARGS = "-m 2048 -e 129024 -c 1996"
|
||||
|
||||
# do ubiattach /dev/ubi_ctrl -m 4
|
||||
# from dmesg:
|
||||
# UBI: smallest flash I/O unit: 2048
|
||||
# UBI: physical eraseblock size: 131072 bytes (128 KiB)
|
||||
# UBI: sub-page size: 512
|
||||
UBINIZE_ARGS = "-m 2048 -p 128KiB -s 512"
|
||||
|
||||
|
||||
|
||||
# and sdio
|
||||
MACHINE_FEATURES = "kernel26 screen apm usbgadget usbhost vfat alsa touchscreen"
|
||||
@@ -0,0 +1,51 @@
|
||||
From 1415ec63689ef39bcb24b5095941ec4cc884035c Mon Sep 17 00:00:00 2001
|
||||
From: Mikael Pettersson <mikpe@it.uu.se>
|
||||
Date: Sun, 15 Aug 2010 10:47:23 +0100
|
||||
Subject: [PATCH 1/2] ARM: 6329/1: wire up sys_accept4() on ARM
|
||||
|
||||
sys_accept4() was added in kernel 2.6.28, but ARM was not updated
|
||||
to include it. The number and types of parameters is such that
|
||||
no ARM-specific processing is needed, so wiring up sys_accept4()
|
||||
just requires defining __NR_accept4 and adding a direct call in
|
||||
the syscall entry table.
|
||||
|
||||
Tested with an EABI 2.6.35 kernel and Ulrich Drepper's original
|
||||
accept4() test program, modified to define __NR_accept4 for ARM.
|
||||
|
||||
Using the updated unistd.h also eliminates a warning then building
|
||||
glibc (2.10.2 and newer) about accept4() being unimplemented.
|
||||
|
||||
Signed-off-by: Mikael Pettersson <mikpe@it.uu.se>
|
||||
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
---
|
||||
arch/arm/include/asm/unistd.h | 1 +
|
||||
arch/arm/kernel/calls.S | 1 +
|
||||
2 files changed, 2 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
|
||||
index dd2bf53..d02cfb6 100644
|
||||
--- a/arch/arm/include/asm/unistd.h
|
||||
+++ b/arch/arm/include/asm/unistd.h
|
||||
@@ -392,6 +392,7 @@
|
||||
#define __NR_rt_tgsigqueueinfo (__NR_SYSCALL_BASE+363)
|
||||
#define __NR_perf_event_open (__NR_SYSCALL_BASE+364)
|
||||
#define __NR_recvmmsg (__NR_SYSCALL_BASE+365)
|
||||
+#define __NR_accept4 (__NR_SYSCALL_BASE+366)
|
||||
|
||||
/*
|
||||
* The following SWIs are ARM private.
|
||||
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
|
||||
index 37ae301..afeb71f 100644
|
||||
--- a/arch/arm/kernel/calls.S
|
||||
+++ b/arch/arm/kernel/calls.S
|
||||
@@ -375,6 +375,7 @@
|
||||
CALL(sys_rt_tgsigqueueinfo)
|
||||
CALL(sys_perf_event_open)
|
||||
/* 365 */ CALL(sys_recvmmsg)
|
||||
+ CALL(sys_accept4)
|
||||
#ifndef syscalls_counted
|
||||
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
|
||||
#define syscalls_counted
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
From b0a773f958b03ba77317f8b762d90d3c00269292 Mon Sep 17 00:00:00 2001
|
||||
From: Roger Monk <r-monk@ti.com>
|
||||
Date: Wed, 25 Aug 2010 16:45:46 +0100
|
||||
Subject: [PATCH] ahci-ti: Fix (currently harmless) typo in SATA PHY configuration
|
||||
|
||||
Signed-off-by: Roger Monk <r-monk@ti.com>
|
||||
---
|
||||
drivers/ata/ahci-ti.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/drivers/ata/ahci-ti.c b/drivers/ata/ahci-ti.c
|
||||
index 9e36c9d..674b216 100644
|
||||
--- a/drivers/ata/ahci-ti.c
|
||||
+++ b/drivers/ata/ahci-ti.c
|
||||
@@ -80,7 +80,7 @@ void ata_plat_init (void __iomem *base)
|
||||
phy_val = PHY_MPY << 0 | PHY_LB << 4 | PHY_LOS << 6 |
|
||||
PHY_RXINVPAIR << 7 | PHY_RXTERM << 8 |
|
||||
PHY_RXCDR << 10 | PHY_RXEQ << 13 |
|
||||
- PHY_RXINVPAIR << 17 | PHY_TXCM << 18 |
|
||||
+ PHY_TXINVPAIR << 17 | PHY_TXCM << 18 |
|
||||
PHY_TXSWING << 19 | PHY_TXDE << 22 |
|
||||
PHY_OVERRIDE << 30 | PHY_ENPLL << 31;
|
||||
|
||||
--
|
||||
1.6.0.4
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
From 787c524fc478068d18eef72f43074b47722e50b0 Mon Sep 17 00:00:00 2001
|
||||
From: Greg KH <gregkh@suse.de>
|
||||
Date: Thu, 5 Aug 2010 13:53:35 -0700
|
||||
Subject: [PATCH] cgroupfs: create /sys/fs/cgroup to mount cgroupfs on
|
||||
|
||||
We really shouldn't be asking userspace to create new root filesystems.
|
||||
So follow along with all of the other in-kernel filesystems, and provide
|
||||
a mount point in sysfs.
|
||||
|
||||
For cgroupfs, this should be in /sys/fs/cgroup/ This change provides
|
||||
that mount point when the cgroup filesystem is registered in the kernel.
|
||||
|
||||
Acked-by: Paul Menage <menage@google.com>
|
||||
Acked-by: Dhaval Giani <dhaval.giani@gmail.com>
|
||||
Cc: Li Zefan <lizf@cn.fujitsu.com>
|
||||
Cc: Lennart Poettering <lennart@poettering.net>
|
||||
Cc: Kay Sievers <kay.sievers@vrfy.org>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
kernel/cgroup.c | 13 ++++++++++++-
|
||||
1 files changed, 12 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
|
||||
index 0249f4b..db21dd8 100644
|
||||
--- a/kernel/cgroup.c
|
||||
+++ b/kernel/cgroup.c
|
||||
@@ -1472,6 +1472,8 @@ static struct file_system_type cgroup_fs_type = {
|
||||
.kill_sb = cgroup_kill_sb,
|
||||
};
|
||||
|
||||
+static struct kobject *cgroup_kobj;
|
||||
+
|
||||
static inline struct cgroup *__d_cgrp(struct dentry *dentry)
|
||||
{
|
||||
return dentry->d_fsdata;
|
||||
@@ -3283,9 +3285,18 @@ int __init cgroup_init(void)
|
||||
hhead = css_set_hash(init_css_set.subsys);
|
||||
hlist_add_head(&init_css_set.hlist, hhead);
|
||||
BUG_ON(!init_root_id(&rootnode));
|
||||
+
|
||||
+ cgroup_kobj = kobject_create_and_add("cgroup", fs_kobj);
|
||||
+ if (!cgroup_kobj) {
|
||||
+ err = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
err = register_filesystem(&cgroup_fs_type);
|
||||
- if (err < 0)
|
||||
+ if (err < 0) {
|
||||
+ kobject_put(cgroup_kobj);
|
||||
goto out;
|
||||
+ }
|
||||
|
||||
proc_create("cgroups", 0, NULL, &proc_cgroupstats_operations);
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
From 37a7868b15be9415abd3f57477afc8be956666e6 Mon Sep 17 00:00:00 2001
|
||||
From: Roger Monk <r-monk@ti.com>
|
||||
Date: Wed, 25 Aug 2010 16:46:28 +0100
|
||||
Subject: [PATCH] ahci-ti: Update SATA PHY configuration - RXCDR --> 4
|
||||
|
||||
* Update SATA PHY configuration for Receiver Clock/Data Recovery
|
||||
* Set to 0x4 = 2nd order, low precision
|
||||
|
||||
Signed-off-by: Roger Monk <r-monk@ti.com>
|
||||
---
|
||||
drivers/ata/ahci-ti.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/drivers/ata/ahci-ti.c b/drivers/ata/ahci-ti.c
|
||||
index 674b216..853d251 100644
|
||||
--- a/drivers/ata/ahci-ti.c
|
||||
+++ b/drivers/ata/ahci-ti.c
|
||||
@@ -55,7 +55,7 @@ void ata_plat_remove(struct ata_host *host);
|
||||
#define PHY_LOS 1 /* bit6 1 */
|
||||
#define PHY_RXINVPAIR 0 /* bit7 1 */
|
||||
#define PHY_RXTERM 0 /* bits9:8 2 */
|
||||
-#define PHY_RXCDR 0 /* bits12:10 3 */
|
||||
+#define PHY_RXCDR 4 /* bits12:10 3 */
|
||||
#define PHY_RXEQ 1 /* bits16:13 4 */
|
||||
#define PHY_TXINVPAIR 0 /* bit17 1 */
|
||||
#define PHY_TXCM 0 /* bit18 1 */
|
||||
--
|
||||
1.6.0.4
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
From 69600e5a42512204bc4eb83a3a459496b049107f Mon Sep 17 00:00:00 2001
|
||||
From: Roger Monk <r-monk@ti.com>
|
||||
Date: Wed, 25 Aug 2010 17:47:16 +0100
|
||||
Subject: [PATCH] board-da850-hawk: Disable NAND SUBPAGE
|
||||
|
||||
* This was causing issues with UBI
|
||||
* Solution/Workaround identified by Caglar Akyuz - now applied locally to board file
|
||||
---
|
||||
arch/arm/mach-davinci/board-da850-hawk.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-davinci/board-da850-hawk.c b/arch/arm/mach-davinci/board-da850-hawk.c
|
||||
index 87ed017..bbfe32a 100644
|
||||
--- a/arch/arm/mach-davinci/board-da850-hawk.c
|
||||
+++ b/arch/arm/mach-davinci/board-da850-hawk.c
|
||||
@@ -118,7 +118,7 @@ static struct davinci_nand_pdata da850_hawk_nandflash_data = {
|
||||
.nr_parts = ARRAY_SIZE(da850_hawk_nandflash_partition),
|
||||
.ecc_mode = NAND_ECC_HW,
|
||||
.ecc_bits = 4,
|
||||
- .options = NAND_USE_FLASH_BBT,
|
||||
+ .options = NAND_USE_FLASH_BBT | NAND_NO_SUBPAGE_WRITE,
|
||||
.timing = &da850_hawk_nandflash_timing,
|
||||
};
|
||||
|
||||
--
|
||||
1.6.0.4
|
||||
|
||||
2630
extras/recipes-kernel/linux/linux-davinci/hawkboard/configs/stock
Normal file
2630
extras/recipes-kernel/linux/linux-davinci/hawkboard/configs/stock
Normal file
File diff suppressed because it is too large
Load Diff
2659
extras/recipes-kernel/linux/linux-davinci/hawkboard/defconfig
Normal file
2659
extras/recipes-kernel/linux/linux-davinci/hawkboard/defconfig
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
||||
From 2ee9f2c655710d9e60a5a9b49871edc316e5363d Mon Sep 17 00:00:00 2001
|
||||
From: Roger Monk <r-monk@ti.com>
|
||||
Date: Wed, 25 Aug 2010 17:29:14 +0100
|
||||
Subject: [PATCH] board-da850-evm: Disable NAND SUBPAGE
|
||||
|
||||
* This was causing issues with UBI
|
||||
* Solution/Workaround identified by Caglar Akyuz - now applied locally to board file
|
||||
|
||||
Signed-off-by: Roger Monk <r-monk@ti.com>
|
||||
---
|
||||
arch/arm/mach-davinci/board-da850-evm.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
|
||||
index cfed439..502b914 100755
|
||||
--- a/arch/arm/mach-davinci/board-da850-evm.c
|
||||
+++ b/arch/arm/mach-davinci/board-da850-evm.c
|
||||
@@ -187,7 +187,7 @@ static struct davinci_nand_pdata da850_evm_nandflash_data = {
|
||||
.nr_parts = ARRAY_SIZE(da850_evm_nandflash_partition),
|
||||
.ecc_mode = NAND_ECC_HW,
|
||||
.ecc_bits = 4,
|
||||
- .options = NAND_USE_FLASH_BBT,
|
||||
+ .options = NAND_USE_FLASH_BBT | NAND_NO_SUBPAGE_WRITE,
|
||||
.timing = &da850_evm_nandflash_timing,
|
||||
};
|
||||
|
||||
--
|
||||
1.6.0.4
|
||||
|
||||
@@ -0,0 +1,334 @@
|
||||
From: Melissa Watkins <m-watkins@ti.com>
|
||||
Date: Wed, 24 Nov 2010 02:59:34 -0600
|
||||
Subject: [PATCH 1/3] uio_pruss1: Core driver addition
|
||||
|
||||
This patch adds the uio_pru driver and updates the uio Makefile
|
||||
and Kconfig files to support this driver. The uio_pru driver provides
|
||||
a framework for handling the PRU in the user space and is responsible
|
||||
for the device setup and the primary interrupt handling.
|
||||
|
||||
Signed-off-by: Amit Chatterjee <amit.chatterjee@ti.com>
|
||||
Signed-off-by: Melissa Watkins <m-watkins@ti.com>
|
||||
---
|
||||
drivers/uio/Kconfig | 10 ++
|
||||
drivers/uio/Makefile | 1 +
|
||||
drivers/uio/uio_pru.c | 279 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 290 insertions(+), 0 deletions(-)
|
||||
create mode 100644 drivers/uio/uio_pru.c
|
||||
|
||||
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
|
||||
index 8aa1955..8ae8280 100644
|
||||
--- a/drivers/uio/Kconfig
|
||||
+++ b/drivers/uio/Kconfig
|
||||
@@ -94,4 +94,14 @@ config UIO_PCI_GENERIC
|
||||
primarily, for virtualization scenarios.
|
||||
If you compile this as a module, it will be called uio_pci_generic.
|
||||
|
||||
+config UIO_PRUSS
|
||||
+ tristate "Texas Instruments PRUSS driver"
|
||||
+ depends on ARCH_DAVINCI_DA850
|
||||
+ default n
|
||||
+ help
|
||||
+ PRUSS driver for OMAPL13X/DA8XX/AM17XX/AM18XX devices
|
||||
+ PRUSS driver requires user space components
|
||||
+ To compile this driver as a module, choose M here: the module
|
||||
+ will be called uio_pruss.
|
||||
+
|
||||
endif
|
||||
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
|
||||
index 73b2e75..e6d8adb 100644
|
||||
--- a/drivers/uio/Makefile
|
||||
+++ b/drivers/uio/Makefile
|
||||
@@ -6,3 +6,4 @@ obj-$(CONFIG_UIO_SMX) += uio_smx.o
|
||||
obj-$(CONFIG_UIO_AEC) += uio_aec.o
|
||||
obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o
|
||||
obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o
|
||||
+obj-$(CONFIG_UIO_PRUSS) += uio_pru.o
|
||||
diff --git a/drivers/uio/uio_pru.c b/drivers/uio/uio_pru.c
|
||||
new file mode 100644
|
||||
index 0000000..82dc35e
|
||||
--- /dev/null
|
||||
+++ b/drivers/uio/uio_pru.c
|
||||
@@ -0,0 +1,279 @@
|
||||
+/*
|
||||
+ * UIO TI Programmable Real-Time Unit (PRU) driver.
|
||||
+ *
|
||||
+ * (C) 2010 Amit Chatterjee <amit.chatterjee@ti.com>
|
||||
+ *
|
||||
+ * Copyright (C) {YEAR} Texas Instruments Incorporated - http://www.ti.com/
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation version 2.
|
||||
+ *
|
||||
+ * This program is distributed .as is. WITHOUT ANY WARRANTY of any
|
||||
+ * kind, whether express or implied; without even the implied warranty
|
||||
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/uio_driver.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/dma-mapping.h>
|
||||
+
|
||||
+#define DRV_NAME "pruss"
|
||||
+#define DRV_VERSION "0.01"
|
||||
+
|
||||
+/*
|
||||
+0x01C30000 - 0x01C301FF Data RAM 0
|
||||
+0x01C30200 - 0x01C31FFF Reserved
|
||||
+0x01C32000 - 0x01C321FF Data RAM 1
|
||||
+0x01C32200 - 0x01C33FFF Reserved
|
||||
+0x01C34000 - 0x01C36FFF INTC Registers
|
||||
+0x01C37000 - 0x01C373FF PRU0 Control Registers
|
||||
+0x01C37400 - 0x01C377FF PRU0 Debug Registers
|
||||
+0x01C37800 - 0x01C37BFF PRU1 Control Registers
|
||||
+0x01C37C00 - 0x01C37FFF PRU1 Debug Registers
|
||||
+0x01C38000 - 0x01C38FFF PRU0 Instruction RAM
|
||||
+0x01C39000 - 0x01C3BFFF Reserved
|
||||
+0x01C3C000 - 0x01C3CFFF PRU1 Instruction RAM
|
||||
+0x01C3D000 - 0x01C3FFFF Reserved
|
||||
+*/
|
||||
+/*
|
||||
+ * 3 PRU_EVTOUT0 PRUSS Interrupt
|
||||
+ * 4 PRU_EVTOUT1 PRUSS Interrupt
|
||||
+ * 5 PRU_EVTOUT2 PRUSS Interrupt
|
||||
+ * 6 PRU_EVTOUT3 PRUSS Interrupt
|
||||
+ * 7 PRU_EVTOUT4 PRUSS Interrupt
|
||||
+ * 8 PRU_EVTOUT5 PRUSS Interrupt
|
||||
+ * 9 PRU_EVTOUT6 PRUSS Interrupt
|
||||
+ * 10 PRU_EVTOUT7 PRUSS Interrupt
|
||||
+*/
|
||||
+
|
||||
+#define PRUSS_INSTANCE (8)
|
||||
+
|
||||
+static struct clk *pruss_clk = NULL, *ecap0_clk = NULL;
|
||||
+static struct uio_info *info[PRUSS_INSTANCE];
|
||||
+static void *ddr_virt_addr;
|
||||
+static dma_addr_t ddr_phy_addr;
|
||||
+
|
||||
+
|
||||
+
|
||||
+static irqreturn_t pruss_handler(int irq, struct uio_info *dev_info)
|
||||
+{
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static int __devinit pruss_probe(struct platform_device *dev)
|
||||
+{
|
||||
+ int ret = -ENODEV;
|
||||
+ int count = 0;
|
||||
+ struct resource *regs_pruram, *regs_l3ram, *regs_ddr;
|
||||
+ char *string;
|
||||
+
|
||||
+ /* Power on PRU in case its not done as part of boot-loader */
|
||||
+ pruss_clk = clk_get(&dev->dev, "pruss");
|
||||
+ if (IS_ERR(pruss_clk)) {
|
||||
+ dev_err(&dev->dev, "no pruss clock available\n");
|
||||
+ ret = PTR_ERR(pruss_clk);
|
||||
+ pruss_clk = NULL;
|
||||
+ return ret;
|
||||
+ } else {
|
||||
+ clk_enable (pruss_clk);
|
||||
+ }
|
||||
+
|
||||
+ ecap0_clk = clk_get(&dev->dev, "ecap0");
|
||||
+ if (IS_ERR(ecap0_clk)) {
|
||||
+ dev_err(&dev->dev, "no ecap0 clock available\n");
|
||||
+ ret = PTR_ERR(ecap0_clk);
|
||||
+ ecap0_clk = NULL;
|
||||
+ return ret;
|
||||
+ } else {
|
||||
+ clk_enable(ecap0_clk);
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+
|
||||
+ for (count = 0; count < PRUSS_INSTANCE; count++) {
|
||||
+ info[count] = (struct uio_info *)kzalloc(sizeof(struct uio_info), GFP_KERNEL);
|
||||
+ if (!info[count])
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ regs_pruram = platform_get_resource(dev, IORESOURCE_MEM, 0);
|
||||
+ if (!regs_pruram) {
|
||||
+ dev_err(&dev->dev, "No memory resource specified\n");
|
||||
+ goto out_free;
|
||||
+ }
|
||||
+
|
||||
+ regs_l3ram = platform_get_resource(dev, IORESOURCE_MEM, 1);
|
||||
+ if (!regs_l3ram) {
|
||||
+ dev_err(&dev->dev, "No memory resource specified\n");
|
||||
+ goto out_free;
|
||||
+ }
|
||||
+
|
||||
+ regs_ddr = platform_get_resource(dev, IORESOURCE_MEM, 2);
|
||||
+ if (!regs_ddr) {
|
||||
+ dev_err(&dev->dev, "No memory resource specified\n");
|
||||
+ goto out_free;
|
||||
+ }
|
||||
+ ddr_virt_addr = dma_alloc_coherent(&dev->dev, regs_ddr->end-regs_ddr->start+1, &ddr_phy_addr, GFP_KERNEL|GFP_DMA);
|
||||
+
|
||||
+
|
||||
+ for (count = 0; count < PRUSS_INSTANCE; count++) {
|
||||
+ info[count]->mem[0].addr = regs_pruram->start;
|
||||
+ if (!info[count]->mem[0].addr) {
|
||||
+ dev_err(&dev->dev, "Invalid memory resource\n");
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ info[count]->mem[0].size = regs_pruram->end - regs_pruram->start + 1;
|
||||
+ info[count]->mem[0].internal_addr = ioremap(regs_pruram->start, info[count]->mem[0].size);
|
||||
+
|
||||
+ if (!info[count]->mem[0].internal_addr) {
|
||||
+ dev_err(&dev->dev, "Can't remap memory address range\n");
|
||||
+ break;
|
||||
+ }
|
||||
+ info[count]->mem[0].memtype = UIO_MEM_PHYS;
|
||||
+
|
||||
+
|
||||
+ info[count]->mem[1].addr = regs_l3ram->start;
|
||||
+ if (!info[count]->mem[1].addr) {
|
||||
+ dev_err(&dev->dev, "Invalid memory resource\n");
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ info[count]->mem[1].size = regs_l3ram->end - regs_l3ram->start + 1;
|
||||
+ info[count]->mem[1].internal_addr = ioremap(regs_l3ram->start, info[count]->mem[1].size);
|
||||
+
|
||||
+ if (!info[count]->mem[1].internal_addr) {
|
||||
+ dev_err(&dev->dev, "Can't remap memory address range\n");
|
||||
+ break;
|
||||
+ }
|
||||
+ info[count]->mem[1].memtype = UIO_MEM_PHYS;
|
||||
+
|
||||
+
|
||||
+ info[count]->mem[2].size = regs_ddr->end - regs_ddr->start + 1;
|
||||
+ if (!(info[count]->mem[2].size-1)) {
|
||||
+ dev_err(&dev->dev, "Invalid memory resource\n");
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ info[count]->mem[2].internal_addr = ddr_virt_addr;
|
||||
+
|
||||
+ if (!info[count]->mem[2].internal_addr) {
|
||||
+ dev_err(&dev->dev, "Can't remap memory address range\n");
|
||||
+ break;
|
||||
+ }
|
||||
+ info[count]->mem[2].addr = ddr_phy_addr;
|
||||
+ info[count]->mem[2].memtype = UIO_MEM_PHYS;
|
||||
+
|
||||
+
|
||||
+ string = kzalloc(20, GFP_KERNEL);
|
||||
+ sprintf(string, "pruss_evt%d", count);
|
||||
+ info[count]->name = string;
|
||||
+ info[count]->version = "0.01";
|
||||
+
|
||||
+ /* Register PRUSS IRQ lines */
|
||||
+ info[count]->irq = IRQ_DA8XX_EVTOUT0+count;
|
||||
+
|
||||
+ info[count]->irq_flags = IRQF_SHARED;
|
||||
+ info[count]->handler = pruss_handler;
|
||||
+
|
||||
+ ret = uio_register_device(&dev->dev, info[count]);
|
||||
+
|
||||
+ if (ret < 0)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ platform_set_drvdata(dev, info);
|
||||
+
|
||||
+ if (ret < 0) {
|
||||
+ if (ddr_virt_addr)
|
||||
+ dma_free_coherent(&dev->dev, regs_ddr->end - regs_ddr->start + 1, ddr_virt_addr, ddr_phy_addr);
|
||||
+ while (count--) {
|
||||
+ uio_unregister_device(info[count]);
|
||||
+ if (info[count]->name)
|
||||
+ kfree(info[count]->name);
|
||||
+ iounmap(info[count]->mem[0].internal_addr);
|
||||
+ }
|
||||
+ } else {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+out_free:
|
||||
+ for (count = 0; count < PRUSS_INSTANCE; count++) {
|
||||
+ if (info[count])
|
||||
+ kfree(info[count]);
|
||||
+ }
|
||||
+
|
||||
+ if (pruss_clk != NULL)
|
||||
+ clk_put(pruss_clk);
|
||||
+ if (ecap0_clk != NULL)
|
||||
+ clk_put(ecap0_clk);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int __devexit pruss_remove(struct platform_device *dev)
|
||||
+{
|
||||
+ int count = 0;
|
||||
+ struct uio_info **info;
|
||||
+
|
||||
+ info = (struct uio_info **)platform_get_drvdata(dev);
|
||||
+
|
||||
+ for (count = 0; count < PRUSS_INSTANCE; count++) {
|
||||
+ uio_unregister_device(info[count]);
|
||||
+ if (info[count]->name)
|
||||
+ kfree(info[count]->name);
|
||||
+
|
||||
+ }
|
||||
+ iounmap(info[0]->mem[0].internal_addr);
|
||||
+ iounmap(info[0]->mem[1].internal_addr);
|
||||
+ if (ddr_virt_addr)
|
||||
+ dma_free_coherent(&dev->dev, info[0]->mem[2].size, info[0]->mem[2].internal_addr, info[0]->mem[2].addr);
|
||||
+
|
||||
+ for (count = 0; count < PRUSS_INSTANCE; count++) {
|
||||
+ if (info[count])
|
||||
+ kfree(info[count]);
|
||||
+ }
|
||||
+
|
||||
+ platform_set_drvdata(dev, NULL);
|
||||
+
|
||||
+ if (pruss_clk != NULL)
|
||||
+ clk_put(pruss_clk);
|
||||
+ if (ecap0_clk != NULL)
|
||||
+ clk_put(ecap0_clk);
|
||||
+
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver pruss_driver = {
|
||||
+ .probe = pruss_probe,
|
||||
+ .remove = __devexit_p(pruss_remove),
|
||||
+ .driver = {
|
||||
+ .name = DRV_NAME,
|
||||
+ .owner = THIS_MODULE,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init pruss_init_module(void)
|
||||
+{
|
||||
+ return platform_driver_register(&pruss_driver);
|
||||
+}
|
||||
+module_init(pruss_init_module);
|
||||
+
|
||||
+static void __exit pruss_exit_module(void)
|
||||
+{
|
||||
+ platform_driver_unregister(&pruss_driver);
|
||||
+}
|
||||
+module_exit(pruss_exit_module);
|
||||
+
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
+MODULE_VERSION(DRV_VERSION);
|
||||
+MODULE_AUTHOR("Amit Chatterjee <amit.chatterjee@ti.com>");
|
||||
--
|
||||
1.7.0.4
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
From: Melissa Watkins <m-watkins@ti.com>
|
||||
Date: Wed, 24 Nov 2010 04:18:07 -0600
|
||||
Subject: [PATCH 2/3] uio_pruss2: Platform changes
|
||||
|
||||
Adding resources supporting the uio_pru driver within the
|
||||
da850 (omapl138) device.
|
||||
|
||||
Signed-off-by: Amit Chatterjee <amit.chatterjee@ti.com>
|
||||
Signed-off-by: Melissa Watkins <m-watkins@ti.com>
|
||||
---
|
||||
arch/arm/configs/da850_omapl138_defconfig | 8 +++-
|
||||
arch/arm/mach-davinci/board-da850-evm.c | 3 +
|
||||
arch/arm/mach-davinci/da850.c | 38 +++++++++++++-
|
||||
arch/arm/mach-davinci/devices-da8xx.c | 75 ++++++++++++++++++++++++++++
|
||||
arch/arm/mach-davinci/include/mach/da8xx.h | 3 +
|
||||
5 files changed, 124 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/configs/da850_omapl138_defconfig b/arch/arm/configs/da850_omapl138_defconfig
|
||||
index b312050..baebec8 100644
|
||||
--- a/arch/arm/configs/da850_omapl138_defconfig
|
||||
+++ b/arch/arm/configs/da850_omapl138_defconfig
|
||||
@@ -1361,6 +1361,7 @@ CONFIG_USB_MUSB_HDRC=y
|
||||
CONFIG_USB_MUSB_SOC=y
|
||||
CONFIG_USB_MUSB_HOST=y
|
||||
# CONFIG_USB_MUSB_PERIPHERAL is not set
|
||||
+# CONFIG_USB_MUSB_DUAL_ROLE is not set
|
||||
# CONFIG_USB_MUSB_OTG is not set
|
||||
CONFIG_USB_MUSB_HDRC_HCD=y
|
||||
# CONFIG_MUSB_PIO_ONLY is not set
|
||||
@@ -1535,7 +1536,12 @@ CONFIG_RTC_INTF_DEV=y
|
||||
CONFIG_RTC_DRV_OMAP=y
|
||||
# CONFIG_DMADEVICES is not set
|
||||
# CONFIG_AUXDISPLAY is not set
|
||||
-# CONFIG_UIO is not set
|
||||
+CONFIG_UIO=y
|
||||
+# CONFIG_UIO_PDRV is not set
|
||||
+# CONFIG_UIO_PDRV_GENIRQ is not set
|
||||
+# CONFIG_UIO_SMX is not set
|
||||
+# CONFIG_UIO_SERCOS3 is not set
|
||||
+CONFIG_UIO_PRUSS=m
|
||||
|
||||
#
|
||||
# TI VLYNQ
|
||||
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
|
||||
index 009e9b5..1687c7c 100755
|
||||
--- a/arch/arm/mach-davinci/board-da850-evm.c
|
||||
+++ b/arch/arm/mach-davinci/board-da850-evm.c
|
||||
@@ -1070,6 +1070,9 @@ static __init void da850_evm_init(void)
|
||||
|
||||
platform_device_register(&da850_gpio_i2c);
|
||||
|
||||
+ /* Register PRUSS device */
|
||||
+ da8xx_register_pruss();
|
||||
+
|
||||
ret = da8xx_register_watchdog();
|
||||
if (ret)
|
||||
pr_warning("da830_evm_init: watchdog registration failed: %d\n",
|
||||
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
|
||||
index 513ae85..8bd1919 100755
|
||||
--- a/arch/arm/mach-davinci/da850.c
|
||||
+++ b/arch/arm/mach-davinci/da850.c
|
||||
@@ -237,6 +237,13 @@ static struct clk tptc2_clk = {
|
||||
.flags = ALWAYS_ENABLED,
|
||||
};
|
||||
|
||||
+static struct clk pruss_clk = {
|
||||
+ .name = "pruss",
|
||||
+ .parent = &pll0_sysclk2,
|
||||
+ .lpsc = DA8XX_LPSC0_DMAX,
|
||||
+ .flags = ALWAYS_ENABLED,
|
||||
+};
|
||||
+
|
||||
static struct clk uart0_clk = {
|
||||
.name = "uart0",
|
||||
.parent = &pll0_sysclk2,
|
||||
@@ -385,13 +392,37 @@ static struct clk usb20_clk = {
|
||||
.gpsc = 1,
|
||||
};
|
||||
|
||||
-
|
||||
static struct clk sata_clk = {
|
||||
.name = "ahci",
|
||||
.parent = &pll0_sysclk2,
|
||||
.lpsc = DA850_LPSC1_SATA,
|
||||
.gpsc = 1,
|
||||
};
|
||||
+
|
||||
+static struct clk ecap0_clk = {
|
||||
+ .name = "ecap0",
|
||||
+ .parent = &pll0_sysclk2,
|
||||
+ .lpsc = DA8XX_LPSC1_ECAP,
|
||||
+ .flags = DA850_CLK_ASYNC3,
|
||||
+ .gpsc = 1,
|
||||
+};
|
||||
+
|
||||
+static struct clk ecap1_clk = {
|
||||
+ .name = "ecap1",
|
||||
+ .parent = &pll0_sysclk2,
|
||||
+ .lpsc = DA8XX_LPSC1_ECAP,
|
||||
+ .flags = DA850_CLK_ASYNC3,
|
||||
+ .gpsc = 1,
|
||||
+};
|
||||
+
|
||||
+static struct clk ecap2_clk = {
|
||||
+ .name = "ecap2",
|
||||
+ .parent = &pll0_sysclk2,
|
||||
+ .lpsc = DA8XX_LPSC1_ECAP,
|
||||
+ .flags = DA850_CLK_ASYNC3,
|
||||
+ .gpsc = 1,
|
||||
+};
|
||||
+
|
||||
static struct clk_lookup da850_clks[] = {
|
||||
CLK(NULL, "ref", &ref_clk),
|
||||
CLK(NULL, "pll0", &pll0_clk),
|
||||
@@ -419,6 +450,7 @@ static struct clk_lookup da850_clks[] = {
|
||||
CLK(NULL, "tptc1", &tptc1_clk),
|
||||
CLK(NULL, "tpcc1", &tpcc1_clk),
|
||||
CLK(NULL, "tptc2", &tptc2_clk),
|
||||
+ CLK(NULL, "pruss", &pruss_clk),
|
||||
CLK(NULL, "uart0", &uart0_clk),
|
||||
CLK(NULL, "uart1", &uart1_clk),
|
||||
CLK(NULL, "uart2", &uart2_clk),
|
||||
@@ -441,7 +473,9 @@ static struct clk_lookup da850_clks[] = {
|
||||
CLK(NULL, "usb11", &usb11_clk),
|
||||
CLK(NULL, "usb20", &usb20_clk),
|
||||
CLK(NULL, "ahci", &sata_clk),
|
||||
-
|
||||
+ CLK(NULL, "ecap0", &ecap0_clk),
|
||||
+ CLK(NULL, "ecap1", &ecap1_clk),
|
||||
+ CLK(NULL, "ecap2", &ecap2_clk),
|
||||
CLK(NULL, NULL, NULL),
|
||||
};
|
||||
|
||||
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
|
||||
index 0842590..94979b3 100755
|
||||
--- a/arch/arm/mach-davinci/devices-da8xx.c
|
||||
+++ b/arch/arm/mach-davinci/devices-da8xx.c
|
||||
@@ -972,6 +972,81 @@ int __init da8xx_register_sata(void)
|
||||
return platform_device_register(&da850_ahci_device);
|
||||
}
|
||||
|
||||
+static struct resource pruss_resources[] = {
|
||||
+ [0] = {
|
||||
+ .start = DA8XX_PRUSS_BASE,
|
||||
+ .end = DA8XX_PRUSS_BASE + SZ_64K - 1,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ [1] = {
|
||||
+ .start = DA8XX_L3RAM_BASE,
|
||||
+ .end = DA8XX_L3RAM_BASE + SZ_128K - 1,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ [2] = {
|
||||
+ .start = 0,
|
||||
+ .end = SZ_256K - 1,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+
|
||||
+ [3] = {
|
||||
+ .start = IRQ_DA8XX_EVTOUT0,
|
||||
+ .end = IRQ_DA8XX_EVTOUT0,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+ [4] = {
|
||||
+ .start = IRQ_DA8XX_EVTOUT1,
|
||||
+ .end = IRQ_DA8XX_EVTOUT1,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+ [5] = {
|
||||
+ .start = IRQ_DA8XX_EVTOUT2,
|
||||
+ .end = IRQ_DA8XX_EVTOUT2,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+ [6] = {
|
||||
+ .start = IRQ_DA8XX_EVTOUT3,
|
||||
+ .end = IRQ_DA8XX_EVTOUT3,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+ [7] = {
|
||||
+ .start = IRQ_DA8XX_EVTOUT4,
|
||||
+ .end = IRQ_DA8XX_EVTOUT4,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+ [8] = {
|
||||
+ .start = IRQ_DA8XX_EVTOUT5,
|
||||
+ .end = IRQ_DA8XX_EVTOUT5,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+ [9] = {
|
||||
+ .start = IRQ_DA8XX_EVTOUT6,
|
||||
+ .end = IRQ_DA8XX_EVTOUT6,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+ [10] = {
|
||||
+ .start = IRQ_DA8XX_EVTOUT7,
|
||||
+ .end = IRQ_DA8XX_EVTOUT7,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct platform_device pruss_device = {
|
||||
+ .name = "pruss",
|
||||
+ .id = 0,
|
||||
+ .num_resources = ARRAY_SIZE(pruss_resources),
|
||||
+ .resource = pruss_resources,
|
||||
+ .dev = {
|
||||
+ .coherent_dma_mask = 0xffffffff,
|
||||
+ }
|
||||
+
|
||||
+};
|
||||
+
|
||||
+int __init da8xx_register_pruss()
|
||||
+{
|
||||
+ return platform_device_register(&pruss_device);
|
||||
+}
|
||||
+
|
||||
#define CFGCHIP2 DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)
|
||||
/*
|
||||
* Configure the USB PHY for DA8xx platforms.
|
||||
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
|
||||
index f76433f..632d7e2 100755
|
||||
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
|
||||
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
|
||||
@@ -75,6 +75,8 @@ extern void __iomem *da8xx_syscfg1_base;
|
||||
#define DA8XX_USB0_BASE 0x01e00000
|
||||
#define DA850_SATA_BASE 0x01E18000
|
||||
#define DA850_SATA_CLK_PWRDN 0x01E2C018
|
||||
+#define DA8XX_PRUSS_BASE 0x01C30000
|
||||
+#define DA8XX_L3RAM_BASE 0x80000000
|
||||
|
||||
#define PINMUX0 0x00
|
||||
#define PINMUX1 0x04
|
||||
@@ -162,6 +164,7 @@ int __init da850_register_vpif_capture(struct vpif_capture_config
|
||||
|
||||
int cppi41_init(void);
|
||||
int da8xx_register_sata(void);
|
||||
+int da8xx_register_pruss(void);
|
||||
|
||||
|
||||
extern struct platform_device da8xx_serial_device;
|
||||
--
|
||||
1.7.0.4
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
From: Melissa Watkins <m-watkins@ti.com>
|
||||
Date: Wed, 24 Nov 2010 04:20:24 -0600
|
||||
Subject: [PATCH 3/3] uio_pruss3: Workarounds put into core code to support our devices
|
||||
|
||||
This patch modifies uio.c to support the uio_pruss driver. The UIO user space module relies on IO memory being mapped to user space. The IO map works fine for all mapped virtual addresses less than 0x80000000. However for the uio_pruss driver, the virtual address is on the higher side, so it fails. The fix added in this patch is mainly to check if the page map returned is correct.
|
||||
|
||||
Signed-off-by: Amit Chatterjee <amit.chatterjee@ti.com>
|
||||
Signed-off-by: Melissa Watkins <m-watkins@ti.com>
|
||||
---
|
||||
drivers/uio/uio.c | 9 +++++++--
|
||||
1 files changed, 7 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
|
||||
index e941367..3241d26 100644
|
||||
--- a/drivers/uio/uio.c
|
||||
+++ b/drivers/uio/uio.c
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/idr.h>
|
||||
-#include <linux/sched.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/uio_driver.h>
|
||||
@@ -615,7 +615,7 @@ static int uio_find_mem_index(struct vm_area_struct *vma)
|
||||
for (mi = 0; mi < MAX_UIO_MAPS; mi++) {
|
||||
if (idev->info->mem[mi].size == 0)
|
||||
return -1;
|
||||
- if (vma->vm_pgoff == mi)
|
||||
+ if ((idev->info->mem[mi].addr) >> PAGE_SHIFT == vma->vm_pgoff)
|
||||
return mi;
|
||||
}
|
||||
return -1;
|
||||
@@ -659,7 +664,7 @@ static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static const struct vm_operations_struct uio_vm_ops = {
|
||||
+static struct vm_operations_struct uio_vm_ops = {
|
||||
.open = uio_vma_open,
|
||||
.close = uio_vma_close,
|
||||
.fault = uio_vma_fault,
|
||||
--
|
||||
1.7.0.4
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1951
extras/recipes-kernel/linux/linux-davinci/omapl138/defconfig
Normal file
1951
extras/recipes-kernel/linux/linux-davinci/omapl138/defconfig
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,160 @@
|
||||
--- /tmp/mach-types 2009-03-17 16:55:42.000000000 +0100
|
||||
+++ git/arch/arm/tools/mach-types 2009-03-17 16:56:28.000000000 +0100
|
||||
@@ -12,7 +12,7 @@
|
||||
#
|
||||
# http://www.arm.linux.org.uk/developer/machines/?action=new
|
||||
#
|
||||
-# Last update: Sun Nov 30 16:39:36 2008
|
||||
+# Last update: Tue Mar 17 15:56:28 2009
|
||||
#
|
||||
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
|
||||
#
|
||||
@@ -1811,7 +1811,7 @@
|
||||
jade MACH_JADE JADE 1821
|
||||
ks8695_softplc MACH_KS8695_SOFTPLC KS8695_SOFTPLC 1822
|
||||
gprisc3 MACH_GPRISC3 GPRISC3 1823
|
||||
-stamp9260 MACH_STAMP9260 STAMP9260 1824
|
||||
+stamp9g20 MACH_STAMP9G20 STAMP9G20 1824
|
||||
smdk6430 MACH_SMDK6430 SMDK6430 1825
|
||||
smdkc100 MACH_SMDKC100 SMDKC100 1826
|
||||
tavorevb MACH_TAVOREVB TAVOREVB 1827
|
||||
@@ -1993,4 +1993,138 @@
|
||||
benzina MACH_BENZINA BENZINA 2003
|
||||
blaze MACH_BLAZE BLAZE 2004
|
||||
linkstation_ls_hgl MACH_LINKSTATION_LS_HGL LINKSTATION_LS_HGL 2005
|
||||
-htcvenus MACH_HTCVENUS HTCVENUS 2006
|
||||
+htckovsky MACH_HTCVENUS HTCVENUS 2006
|
||||
+sony_prs505 MACH_SONY_PRS505 SONY_PRS505 2007
|
||||
+hanlin_v3 MACH_HANLIN_V3 HANLIN_V3 2008
|
||||
+sapphira MACH_SAPPHIRA SAPPHIRA 2009
|
||||
+dack_sda_01 MACH_DACK_SDA_01 DACK_SDA_01 2010
|
||||
+armbox MACH_ARMBOX ARMBOX 2011
|
||||
+harris_rvp MACH_HARRIS_RVP HARRIS_RVP 2012
|
||||
+ribaldo MACH_RIBALDO RIBALDO 2013
|
||||
+agora MACH_AGORA AGORA 2014
|
||||
+omap3_mini MACH_OMAP3_MINI OMAP3_MINI 2015
|
||||
+a9sam6432_b MACH_A9SAM6432_B A9SAM6432_B 2016
|
||||
+usg2410 MACH_USG2410 USG2410 2017
|
||||
+pc72052_i10_revb MACH_PC72052_I10_REVB PC72052_I10_REVB 2018
|
||||
+mx35_exm32 MACH_MX35_EXM32 MX35_EXM32 2019
|
||||
+topas910 MACH_TOPAS910 TOPAS910 2020
|
||||
+hyena MACH_HYENA HYENA 2021
|
||||
+pospax MACH_POSPAX POSPAX 2022
|
||||
+hdl_gx MACH_HDL_GX HDL_GX 2023
|
||||
+ctera_4bay MACH_CTERA_4BAY CTERA_4BAY 2024
|
||||
+ctera_plug_c MACH_CTERA_PLUG_C CTERA_PLUG_C 2025
|
||||
+crwea_plug_i MACH_CRWEA_PLUG_I CRWEA_PLUG_I 2026
|
||||
+egauge2 MACH_EGAUGE2 EGAUGE2 2027
|
||||
+didj MACH_DIDJ DIDJ 2028
|
||||
+m_s3c2443 MACH_MEISTER MEISTER 2029
|
||||
+htcblackstone MACH_HTCBLACKSTONE HTCBLACKSTONE 2030
|
||||
+cpuat9g20 MACH_CPUAT9G20 CPUAT9G20 2031
|
||||
+smdk6440 MACH_SMDK6440 SMDK6440 2032
|
||||
+omap_35xx_mvp MACH_OMAP_35XX_MVP OMAP_35XX_MVP 2033
|
||||
+ctera_plug_i MACH_CTERA_PLUG_I CTERA_PLUG_I 2034
|
||||
+pvg610_100 MACH_PVG610 PVG610 2035
|
||||
+hprw6815 MACH_HPRW6815 HPRW6815 2036
|
||||
+omap3_oswald MACH_OMAP3_OSWALD OMAP3_OSWALD 2037
|
||||
+nas4220b MACH_NAS4220B NAS4220B 2038
|
||||
+htcraphael_cdma MACH_HTCRAPHAEL_CDMA HTCRAPHAEL_CDMA 2039
|
||||
+htcdiamond_cdma MACH_HTCDIAMOND_CDMA HTCDIAMOND_CDMA 2040
|
||||
+scaler MACH_SCALER SCALER 2041
|
||||
+zylonite2 MACH_ZYLONITE2 ZYLONITE2 2042
|
||||
+aspenite MACH_ASPENITE ASPENITE 2043
|
||||
+teton MACH_TETON TETON 2044
|
||||
+ttc_dkb MACH_TTC_DKB TTC_DKB 2045
|
||||
+bishop2 MACH_BISHOP2 BISHOP2 2046
|
||||
+ippv5 MACH_IPPV5 IPPV5 2047
|
||||
+farm926 MACH_FARM926 FARM926 2048
|
||||
+mmccpu MACH_MMCCPU MMCCPU 2049
|
||||
+sgmsfl MACH_SGMSFL SGMSFL 2050
|
||||
+tt8000 MACH_TT8000 TT8000 2051
|
||||
+zrn4300lp MACH_ZRN4300LP ZRN4300LP 2052
|
||||
+mptc MACH_MPTC MPTC 2053
|
||||
+h6051 MACH_H6051 H6051 2054
|
||||
+pvg610_101 MACH_PVG610_101 PVG610_101 2055
|
||||
+stamp9261_pc_evb MACH_STAMP9261_PC_EVB STAMP9261_PC_EVB 2056
|
||||
+pelco_odysseus MACH_PELCO_ODYSSEUS PELCO_ODYSSEUS 2057
|
||||
+tny_a9260 MACH_TNY_A9260 TNY_A9260 2058
|
||||
+tny_a9g20 MACH_TNY_A9G20 TNY_A9G20 2059
|
||||
+aesop_mp2530f MACH_AESOP_MP2530F AESOP_MP2530F 2060
|
||||
+dx900 MACH_DX900 DX900 2061
|
||||
+cpodc2 MACH_CPODC2 CPODC2 2062
|
||||
+tilt_8925 MACH_TILT_8925 TILT_8925 2063
|
||||
+davinci_dm357_evm MACH_DAVINCI_DM357_EVM DAVINCI_DM357_EVM 2064
|
||||
+swordfish MACH_SWORDFISH SWORDFISH 2065
|
||||
+corvus MACH_CORVUS CORVUS 2066
|
||||
+taurus MACH_TAURUS TAURUS 2067
|
||||
+axm MACH_AXM AXM 2068
|
||||
+axc MACH_AXC AXC 2069
|
||||
+baby MACH_BABY BABY 2070
|
||||
+mp200 MACH_MP200 MP200 2071
|
||||
+pcm043 MACH_PCM043 PCM043 2072
|
||||
+hanlin_v3c MACH_HANLIN_V3C HANLIN_V3C 2073
|
||||
+kbk9g20 MACH_KBK9G20 KBK9G20 2074
|
||||
+adsturbog5 MACH_ADSTURBOG5 ADSTURBOG5 2075
|
||||
+avenger_lite1 MACH_AVENGER_LITE1 AVENGER_LITE1 2076
|
||||
+suc82x MACH_SUC SUC 2077
|
||||
+at91sam7s256 MACH_AT91SAM7S256 AT91SAM7S256 2078
|
||||
+mendoza MACH_MENDOZA MENDOZA 2079
|
||||
+kira MACH_KIRA KIRA 2080
|
||||
+mx1hbm MACH_MX1HBM MX1HBM 2081
|
||||
+quatro43xx MACH_QUATRO43XX QUATRO43XX 2082
|
||||
+quatro4230 MACH_QUATRO4230 QUATRO4230 2083
|
||||
+nsb400 MACH_NSB400 NSB400 2084
|
||||
+drp255 MACH_DRP255 DRP255 2085
|
||||
+thoth MACH_THOTH THOTH 2086
|
||||
+firestone MACH_FIRESTONE FIRESTONE 2087
|
||||
+asusp750 MACH_ASUSP750 ASUSP750 2088
|
||||
+ctera_dl MACH_CTERA_DL CTERA_DL 2089
|
||||
+socr MACH_SOCR SOCR 2090
|
||||
+htcoxygen MACH_HTCOXYGEN HTCOXYGEN 2091
|
||||
+heroc MACH_HEROC HEROC 2092
|
||||
+zeno6800 MACH_ZENO6800 ZENO6800 2093
|
||||
+sc2mcs MACH_SC2MCS SC2MCS 2094
|
||||
+gene100 MACH_GENE100 GENE100 2095
|
||||
+as353x MACH_AS353X AS353X 2096
|
||||
+sheevaplug MACH_SHEEVAPLUG SHEEVAPLUG 2097
|
||||
+at91sam9g20 MACH_AT91SAM9G20 AT91SAM9G20 2098
|
||||
+mv88f6192gtw_fe MACH_MV88F6192GTW_FE MV88F6192GTW_FE 2099
|
||||
+cc9200 MACH_CC9200 CC9200 2100
|
||||
+sm9200 MACH_SM9200 SM9200 2101
|
||||
+tp9200 MACH_TP9200 TP9200 2102
|
||||
+snapperdv MACH_SNAPPERDV SNAPPERDV 2103
|
||||
+avengers_lite MACH_AVENGERS_LITE AVENGERS_LITE 2104
|
||||
+avengers_lite1 MACH_AVENGERS_LITE1 AVENGERS_LITE1 2105
|
||||
+omap3axon MACH_OMAP3AXON OMAP3AXON 2106
|
||||
+ma8xx MACH_MA8XX MA8XX 2107
|
||||
+mp201ek MACH_MP201EK MP201EK 2108
|
||||
+davinci_tux MACH_DAVINCI_TUX DAVINCI_TUX 2109
|
||||
+mpa1600 MACH_MPA1600 MPA1600 2110
|
||||
+pelco_troy MACH_PELCO_TROY PELCO_TROY 2111
|
||||
+nsb667 MACH_NSB667 NSB667 2112
|
||||
+rovers5_4mpix MACH_ROVERS5_4MPIX ROVERS5_4MPIX 2113
|
||||
+twocom MACH_TWOCOM TWOCOM 2114
|
||||
+ubisys_p9_rcu3r2 MACH_UBISYS_P9_RCU3R2 UBISYS_P9_RCU3R2 2115
|
||||
+hero_espresso MACH_HERO_ESPRESSO HERO_ESPRESSO 2116
|
||||
+afeusb MACH_AFEUSB AFEUSB 2117
|
||||
+t830 MACH_T830 T830 2118
|
||||
+spd8020_cc MACH_SPD8020_CC SPD8020_CC 2119
|
||||
+om_3d7k MACH_OM_3D7K OM_3D7K 2120
|
||||
+picocom2 MACH_PICOCOM2 PICOCOM2 2121
|
||||
+uwg4mx27 MACH_UWG4MX27 UWG4MX27 2122
|
||||
+uwg4mx31 MACH_UWG4MX31 UWG4MX31 2123
|
||||
+cherry MACH_CHERRY CHERRY 2124
|
||||
+mx51_babbage MACH_MX51_BABBAGE MX51_BABBAGE 2125
|
||||
+s3c2440turkiye MACH_S3C2440TURKIYE S3C2440TURKIYE 2126
|
||||
+tx37 MACH_TX37 TX37 2127
|
||||
+sbc2800_9g20 MACH_SBC2800_9G20 SBC2800_9G20 2128
|
||||
+benzglb MACH_BENZGLB BENZGLB 2129
|
||||
+benztd MACH_BENZTD BENZTD 2130
|
||||
+cartesio_plus MACH_CARTESIO_PLUS CARTESIO_PLUS 2131
|
||||
+solrad_g20 MACH_SOLRAD_G20 SOLRAD_G20 2132
|
||||
+mx27wallace MACH_MX27WALLACE MX27WALLACE 2133
|
||||
+fmzwebmodul MACH_FMZWEBMODUL FMZWEBMODUL 2134
|
||||
+rd78x00_masa MACH_RD78X00_MASA RD78X00_MASA 2135
|
||||
+smallogger MACH_SMALLOGGER SMALLOGGER 2136
|
||||
+ccw9p9215 MACH_CCW9P9215 CCW9P9215 2137
|
||||
+dm355_leopard MACH_DM355_LEOPARD DM355_LEOPARD 2138
|
||||
+ts219 MACH_TS219 TS219 2139
|
||||
+tny_a9263 MACH_TNY_A9263 TNY_A9263 2140
|
||||
57
extras/recipes-kernel/linux/linux-davinci_git.bb
Normal file
57
extras/recipes-kernel/linux/linux-davinci_git.bb
Normal file
@@ -0,0 +1,57 @@
|
||||
require multi-kernel.inc
|
||||
|
||||
DESCRIPTION = "Linux kernel for DaVinci processors"
|
||||
KERNEL_IMAGETYPE = "uImage"
|
||||
|
||||
COMPATIBLE_MACHINE = "hawkboard"
|
||||
|
||||
DEFAULT_PREFERENCE_hawkboard = "1"
|
||||
|
||||
BRANCH = "master"
|
||||
|
||||
SRC_URI_append = " file://defconfig "
|
||||
|
||||
S = "${WORKDIR}/git"
|
||||
|
||||
# The main PR is now using MACHINE_KERNEL_PR, for davinci see conf/machine/include/davinci.inc
|
||||
|
||||
# OMAPL tracking master branch - PSP 3.20.00.12
|
||||
|
||||
ARAGO_L1_REV = "2acf935c01b9adb50164d421c40cdc5862b9e143"
|
||||
ARAGO_L1_BR = "master"
|
||||
ARAGO_L1_PV = "2.6.32+2.6.33-rc4-${PR}+gitr${SRCREV}"
|
||||
ARAGO_L1_URI = "git://arago-project.org/git/projects/linux-omapl1.git;protocol=git;branch=${BRANCH} "
|
||||
|
||||
SRCREV_hawkboard = "${ARAGO_L1_REV}"
|
||||
|
||||
PV_omapl138 = "${ARAGO_L1_PV}"
|
||||
|
||||
BRANCH_omapl138 = "${ARAGO_L1_BR}"
|
||||
|
||||
SRC_URI_append_omapl138 = "${ARAGO_L1_URI}"
|
||||
|
||||
SRC_URI_append_omapl138 = " file://logo_linux_clut224.ppm \
|
||||
file://0001-ahci-ti-Fix-currently-harmless-typo-in-SATA-PHY.patch \
|
||||
file://0002-ahci-ti-Update-SATA-PHY-configuration-RXCDR.patch \
|
||||
file://0001-board-da850-evm-Disable-NAND-SUBPAGE.patch \
|
||||
file://0001-uio_pruss1-Core-driver-addition.patch \
|
||||
file://0002-uio_pruss2-Platform-changes.patch \
|
||||
file://0003-uio_pruss3-Workarounds-put-into-core-code.patch \
|
||||
file://0001-cgroupfs-create-sys-fs-cgroup-to-mount-cgroupfs-on.patch \
|
||||
file://0001-ARM-6329-1-wire-up-sys_accept4-on-ARM.patch \
|
||||
"
|
||||
|
||||
SRC_URI_append_hawkboard = " \
|
||||
file://patch-2.6.33rc4-psp-to-hawkboard.patch \
|
||||
file://0001-board-da850-hawk-Disable-NAND-SUBPAGE.patch \
|
||||
"
|
||||
|
||||
# Perf in 2.6.33rc has broken perl handling, so disable it
|
||||
do_compile_perf() {
|
||||
:
|
||||
}
|
||||
|
||||
do_install_perf() {
|
||||
:
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
From 16c1bdb30f1bcd750b29dffd2ef3003be2d30610 Mon Sep 17 00:00:00 2001
|
||||
From: Koen Kooi <koen@dominion.thruhere.net>
|
||||
Date: Fri, 20 May 2011 12:48:37 +0200
|
||||
Subject: [PATCH 1/7] OMAP3: beagle: add support for beagleboard xM revision C
|
||||
|
||||
The USB enable GPIO has been inverted and the USER button moved.
|
||||
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/board-omap3beagle.c | 34 +++++++++++++++++++++++-------
|
||||
1 files changed, 26 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
index 2de4b02..77bafa8 100644
|
||||
--- a/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
@@ -62,7 +62,9 @@
|
||||
* AXBX = GPIO173, GPIO172, GPIO171: 1 1 1
|
||||
* C1_3 = GPIO173, GPIO172, GPIO171: 1 1 0
|
||||
* C4 = GPIO173, GPIO172, GPIO171: 1 0 1
|
||||
- * XM = GPIO173, GPIO172, GPIO171: 0 0 0
|
||||
+ * XMA = GPIO173, GPIO172, GPIO171: 0 0 0
|
||||
+ * XMB = GPIO173, GPIO172, GPIO171: 0 0 1
|
||||
+ * XMC = GPIO173, GPIO172, GPIO171: 0 1 0
|
||||
*/
|
||||
enum {
|
||||
OMAP3BEAGLE_BOARD_UNKN = 0,
|
||||
@@ -70,6 +72,7 @@ enum {
|
||||
OMAP3BEAGLE_BOARD_C1_3,
|
||||
OMAP3BEAGLE_BOARD_C4,
|
||||
OMAP3BEAGLE_BOARD_XM,
|
||||
+ OMAP3BEAGLE_BOARD_XMC,
|
||||
};
|
||||
|
||||
static u8 omap3_beagle_version;
|
||||
@@ -124,9 +127,18 @@ static void __init omap3_beagle_init_rev(void)
|
||||
printk(KERN_INFO "OMAP3 Beagle Rev: xM\n");
|
||||
omap3_beagle_version = OMAP3BEAGLE_BOARD_XM;
|
||||
break;
|
||||
+ case 1:
|
||||
+ printk(KERN_INFO "OMAP3 Beagle Rev: xM B\n");
|
||||
+ omap3_beagle_version = OMAP3BEAGLE_BOARD_XM;
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ printk(KERN_INFO "OMAP3 Beagle Rev: xM C\n");
|
||||
+ omap3_beagle_version = OMAP3BEAGLE_BOARD_XMC;
|
||||
+ break;
|
||||
default:
|
||||
- printk(KERN_INFO "OMAP3 Beagle Rev: unknown %hd\n", beagle_rev);
|
||||
- omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN;
|
||||
+ printk(KERN_INFO
|
||||
+ "OMAP3 Beagle Rev: unknown %hd, assuming xM C or newer\n", beagle_rev);
|
||||
+ omap3_beagle_version = OMAP3BEAGLE_BOARD_XMC;
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -278,7 +290,7 @@ static int beagle_twl_gpio_setup(struct device *dev,
|
||||
{
|
||||
int r;
|
||||
|
||||
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
|
||||
+ if (cpu_is_omap3630()) {
|
||||
mmc[0].gpio_wp = -EINVAL;
|
||||
} else if ((omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C1_3) ||
|
||||
(omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C4)) {
|
||||
@@ -298,7 +310,8 @@ static int beagle_twl_gpio_setup(struct device *dev,
|
||||
/* REVISIT: need ehci-omap hooks for external VBUS
|
||||
* power switch and overcurrent detect
|
||||
*/
|
||||
- if (omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XM) {
|
||||
+ if (omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XM
|
||||
+ && omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XMC) {
|
||||
r = gpio_request(gpio + 1, "EHCI_nOC");
|
||||
if (!r) {
|
||||
r = gpio_direction_input(gpio + 1);
|
||||
@@ -320,7 +333,7 @@ static int beagle_twl_gpio_setup(struct device *dev,
|
||||
gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
|
||||
|
||||
/* DVI reset GPIO is different between beagle revisions */
|
||||
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM)
|
||||
+ if (cpu_is_omap3630())
|
||||
beagle_dvi_device.reset_gpio = 129;
|
||||
else
|
||||
beagle_dvi_device.reset_gpio = 170;
|
||||
@@ -334,7 +347,7 @@ static int beagle_twl_gpio_setup(struct device *dev,
|
||||
* P7/P8 revisions(prototype): Camera EN
|
||||
* A2+ revisions (production): LDO (supplies DVI, serial, led blocks)
|
||||
*/
|
||||
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
|
||||
+ if (cpu_is_omap3630()) {
|
||||
r = gpio_request(gpio + 1, "nDVI_PWR_EN");
|
||||
if (!r) {
|
||||
r = gpio_direction_output(gpio + 1, 0);
|
||||
@@ -625,7 +638,7 @@ static void __init beagle_opp_init(void)
|
||||
}
|
||||
|
||||
/* Custom OPP enabled for XM */
|
||||
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
|
||||
+ if (cpu_is_omap3630()) {
|
||||
struct omap_hwmod *mh = omap_hwmod_lookup("mpu");
|
||||
struct omap_hwmod *dh = omap_hwmod_lookup("iva");
|
||||
struct device *dev;
|
||||
@@ -665,6 +678,11 @@ static void __init omap3_beagle_init(void)
|
||||
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
|
||||
omap3_beagle_init_rev();
|
||||
omap3_beagle_i2c_init();
|
||||
+
|
||||
+ if (cpu_is_omap3630()) {
|
||||
+ gpio_buttons[0].gpio = 4;
|
||||
+ }
|
||||
+
|
||||
platform_add_devices(omap3_beagle_devices,
|
||||
ARRAY_SIZE(omap3_beagle_devices));
|
||||
omap_display_init(&beagle_dss_data);
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,359 @@
|
||||
From 27494059a5d005b8cad4e0e8640ff031b86220dc Mon Sep 17 00:00:00 2001
|
||||
From: Koen Kooi <koen@dominion.thruhere.net>
|
||||
Date: Fri, 20 May 2011 13:06:24 +0200
|
||||
Subject: [PATCH 2/7] OMAP3: beagle: add support for expansionboards
|
||||
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/board-omap3beagle.c | 272 ++++++++++++++++++++++++++++++-
|
||||
1 files changed, 269 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
index 77bafa8..db285e1 100644
|
||||
--- a/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/gpio.h>
|
||||
+#include <linux/irq.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
#include <linux/opp.h>
|
||||
@@ -154,6 +155,167 @@ fail0:
|
||||
return;
|
||||
}
|
||||
|
||||
+char expansionboard_name[16];
|
||||
+
|
||||
+#if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
|
||||
+#include <linux/regulator/fixed.h>
|
||||
+#include <linux/wl12xx.h>
|
||||
+
|
||||
+#define OMAP_BEAGLE_WLAN_EN_GPIO (139)
|
||||
+#define OMAP_BEAGLE_BT_EN_GPIO (138)
|
||||
+#define OMAP_BEAGLE_WLAN_IRQ_GPIO (137)
|
||||
+#define OMAP_BEAGLE_FM_EN_BT_WU (136)
|
||||
+
|
||||
+struct wl12xx_platform_data omap_beagle_wlan_data __initdata = {
|
||||
+ .irq = OMAP_GPIO_IRQ(OMAP_BEAGLE_WLAN_IRQ_GPIO),
|
||||
+ .board_ref_clock = 2, /* 38.4 MHz */
|
||||
+};
|
||||
+
|
||||
+static int gpios[] = {OMAP_BEAGLE_BT_EN_GPIO, OMAP_BEAGLE_FM_EN_BT_WU, -1};
|
||||
+static struct platform_device wl12xx_device = {
|
||||
+ .name = "kim",
|
||||
+ .id = -1,
|
||||
+ .dev.platform_data = &gpios,
|
||||
+};
|
||||
+
|
||||
+static struct omap2_hsmmc_info mmcbbt[] = {
|
||||
+ {
|
||||
+ .mmc = 1,
|
||||
+ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
|
||||
+ .gpio_wp = 29,
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "wl1271",
|
||||
+ .mmc = 2,
|
||||
+ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
|
||||
+ .gpio_wp = -EINVAL,
|
||||
+ .gpio_cd = -EINVAL,
|
||||
+ .ocr_mask = MMC_VDD_165_195,
|
||||
+ .nonremovable = true,
|
||||
+ },
|
||||
+ {} /* Terminator */
|
||||
+ };
|
||||
+
|
||||
+static struct regulator_consumer_supply beagle_vmmc2_supply =
|
||||
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
|
||||
+
|
||||
+static struct regulator_init_data beagle_vmmc2 = {
|
||||
+ .constraints = {
|
||||
+ .min_uV = 1850000,
|
||||
+ .max_uV = 1850000,
|
||||
+ .apply_uV = true,
|
||||
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
|
||||
+ | REGULATOR_MODE_STANDBY,
|
||||
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
|
||||
+ | REGULATOR_CHANGE_STATUS,
|
||||
+ },
|
||||
+ .num_consumer_supplies = 1,
|
||||
+ .consumer_supplies = &beagle_vmmc2_supply,
|
||||
+};
|
||||
+
|
||||
+static struct fixed_voltage_config beagle_vwlan = {
|
||||
+ .supply_name = "vwl1271",
|
||||
+ .microvolts = 1800000, /* 1.8V */
|
||||
+ .gpio = OMAP_BEAGLE_WLAN_EN_GPIO,
|
||||
+ .startup_delay = 70000, /* 70ms */
|
||||
+ .enable_high = 1,
|
||||
+ .enabled_at_boot = 0,
|
||||
+ .init_data = &beagle_vmmc2,
|
||||
+};
|
||||
+
|
||||
+static struct platform_device omap_vwlan_device = {
|
||||
+ .name = "reg-fixed-voltage",
|
||||
+ .id = 1,
|
||||
+ .dev = {
|
||||
+ .platform_data = &beagle_vwlan,
|
||||
+ },
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
+#if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE)
|
||||
+
|
||||
+#include <plat/mcspi.h>
|
||||
+#include <linux/spi/spi.h>
|
||||
+
|
||||
+#define OMAP3BEAGLE_GPIO_ENC28J60_IRQ 157
|
||||
+
|
||||
+static struct omap2_mcspi_device_config enc28j60_spi_chip_info = {
|
||||
+ .turbo_mode = 0,
|
||||
+ .single_channel = 1, /* 0: slave, 1: master */
|
||||
+};
|
||||
+
|
||||
+static struct spi_board_info omap3beagle_zippy_spi_board_info[] __initdata = {
|
||||
+ {
|
||||
+ .modalias = "enc28j60",
|
||||
+ .bus_num = 4,
|
||||
+ .chip_select = 0,
|
||||
+ .max_speed_hz = 20000000,
|
||||
+ .controller_data = &enc28j60_spi_chip_info,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static void __init omap3beagle_enc28j60_init(void)
|
||||
+{
|
||||
+ if ((gpio_request(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, "ENC28J60_IRQ") == 0) &&
|
||||
+ (gpio_direction_input(OMAP3BEAGLE_GPIO_ENC28J60_IRQ) == 0)) {
|
||||
+ gpio_export(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, 0);
|
||||
+ omap3beagle_zippy_spi_board_info[0].irq = OMAP_GPIO_IRQ(OMAP3BEAGLE_GPIO_ENC28J60_IRQ);
|
||||
+ irq_set_irq_type(omap3beagle_zippy_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING);
|
||||
+ } else {
|
||||
+ printk(KERN_ERR "could not obtain gpio for ENC28J60_IRQ\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ spi_register_board_info(omap3beagle_zippy_spi_board_info,
|
||||
+ ARRAY_SIZE(omap3beagle_zippy_spi_board_info));
|
||||
+}
|
||||
+
|
||||
+#else
|
||||
+static inline void __init omap3beagle_enc28j60_init(void) { return; }
|
||||
+#endif
|
||||
+
|
||||
+#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
|
||||
+
|
||||
+#include <plat/mcspi.h>
|
||||
+#include <linux/spi/spi.h>
|
||||
+
|
||||
+#define OMAP3BEAGLE_GPIO_KS8851_IRQ 157
|
||||
+
|
||||
+static struct omap2_mcspi_device_config ks8851_spi_chip_info = {
|
||||
+ .turbo_mode = 0,
|
||||
+ .single_channel = 1, /* 0: slave, 1: master */
|
||||
+};
|
||||
+
|
||||
+static struct spi_board_info omap3beagle_zippy2_spi_board_info[] __initdata = {
|
||||
+ {
|
||||
+ .modalias = "ks8851",
|
||||
+ .bus_num = 4,
|
||||
+ .chip_select = 0,
|
||||
+ .max_speed_hz = 36000000,
|
||||
+ .controller_data = &ks8851_spi_chip_info,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static void __init omap3beagle_ks8851_init(void)
|
||||
+{
|
||||
+ if ((gpio_request(OMAP3BEAGLE_GPIO_KS8851_IRQ, "KS8851_IRQ") == 0) &&
|
||||
+ (gpio_direction_input(OMAP3BEAGLE_GPIO_KS8851_IRQ) == 0)) {
|
||||
+ gpio_export(OMAP3BEAGLE_GPIO_KS8851_IRQ, 0);
|
||||
+ omap3beagle_zippy2_spi_board_info[0].irq = OMAP_GPIO_IRQ(OMAP3BEAGLE_GPIO_KS8851_IRQ);
|
||||
+ irq_set_irq_type(omap3beagle_zippy2_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING);
|
||||
+ } else {
|
||||
+ printk(KERN_ERR "could not obtain gpio for KS8851_IRQ\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ spi_register_board_info(omap3beagle_zippy2_spi_board_info,
|
||||
+ ARRAY_SIZE(omap3beagle_zippy2_spi_board_info));
|
||||
+}
|
||||
+
|
||||
+#else
|
||||
+static inline void __init omap3beagle_ks8851_init(void) { return; }
|
||||
+#endif
|
||||
+
|
||||
static struct mtd_partition omap3beagle_nand_partitions[] = {
|
||||
/* All the partition sizes are listed in terms of NAND block size */
|
||||
{
|
||||
@@ -272,6 +434,12 @@ static struct omap2_hsmmc_info mmc[] = {
|
||||
.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
|
||||
.gpio_wp = 29,
|
||||
},
|
||||
+ {
|
||||
+ .mmc = 2,
|
||||
+ .caps = MMC_CAP_4_BIT_DATA,
|
||||
+ .transceiver = true,
|
||||
+ .ocr_mask = 0x00100000, /* 3.3V */
|
||||
+ },
|
||||
{} /* Terminator */
|
||||
};
|
||||
|
||||
@@ -301,11 +469,25 @@ static int beagle_twl_gpio_setup(struct device *dev,
|
||||
}
|
||||
/* gpio + 0 is "mmc0_cd" (input/IRQ) */
|
||||
mmc[0].gpio_cd = gpio + 0;
|
||||
+#if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
|
||||
+ if(!strcmp(expansionboard_name, "bbtoys-wifi")) {
|
||||
+ omap2_hsmmc_init(mmcbbt);
|
||||
+ /* link regulators to MMC adapters */
|
||||
+ beagle_vmmc1_supply.dev = mmcbbt[0].dev;
|
||||
+ beagle_vsim_supply.dev = mmcbbt[0].dev;
|
||||
+ } else {
|
||||
+ omap2_hsmmc_init(mmc);
|
||||
+ /* link regulators to MMC adapters */
|
||||
+ beagle_vmmc1_supply.dev = mmc[0].dev;
|
||||
+ beagle_vsim_supply.dev = mmc[0].dev;
|
||||
+ }
|
||||
+#else
|
||||
omap2_hsmmc_init(mmc);
|
||||
|
||||
/* link regulators to MMC adapters */
|
||||
beagle_vmmc1_supply.dev = mmc[0].dev;
|
||||
beagle_vsim_supply.dev = mmc[0].dev;
|
||||
+#endif
|
||||
|
||||
/* REVISIT: need ehci-omap hooks for external VBUS
|
||||
* power switch and overcurrent detect
|
||||
@@ -466,7 +648,7 @@ static struct twl4030_platform_data beagle_twldata = {
|
||||
.vpll2 = &beagle_vpll2,
|
||||
};
|
||||
|
||||
-static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
|
||||
+static struct i2c_board_info __initdata beagle_i2c1_boardinfo[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("twl4030", 0x48),
|
||||
.flags = I2C_CLIENT_WAKE,
|
||||
@@ -481,10 +663,24 @@ static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
|
||||
},
|
||||
};
|
||||
|
||||
+#if defined(CONFIG_RTC_DRV_DS1307) || \
|
||||
+ defined(CONFIG_RTC_DRV_DS1307_MODULE)
|
||||
+
|
||||
+static struct i2c_board_info __initdata beagle_i2c2_boardinfo[] = {
|
||||
+ {
|
||||
+ I2C_BOARD_INFO("ds1307", 0x68),
|
||||
+ },
|
||||
+};
|
||||
+#else
|
||||
+static struct i2c_board_info __initdata beagle_i2c2_boardinfo[] = {};
|
||||
+#endif
|
||||
+
|
||||
static int __init omap3_beagle_i2c_init(void)
|
||||
{
|
||||
- omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
|
||||
- ARRAY_SIZE(beagle_i2c_boardinfo));
|
||||
+ omap_register_i2c_bus(1, 2600, beagle_i2c1_boardinfo,
|
||||
+ ARRAY_SIZE(beagle_i2c1_boardinfo));
|
||||
+ omap_register_i2c_bus(2, 400, beagle_i2c2_boardinfo,
|
||||
+ ARRAY_SIZE(beagle_i2c2_boardinfo));
|
||||
/* Bus 3 is attached to the DVI port where devices like the pico DLP
|
||||
* projector don't work reliably with 400kHz */
|
||||
omap_register_i2c_bus(3, 100, beagle_i2c_eeprom, ARRAY_SIZE(beagle_i2c_eeprom));
|
||||
@@ -627,6 +823,15 @@ static struct omap_musb_board_data musb_board_data = {
|
||||
.power = 100,
|
||||
};
|
||||
|
||||
+static int __init expansionboard_setup(char *str)
|
||||
+{
|
||||
+ if (!str)
|
||||
+ return -EINVAL;
|
||||
+ strncpy(expansionboard_name, str, 16);
|
||||
+ printk(KERN_INFO "Beagle expansionboard: %s\n", expansionboard_name);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void __init beagle_opp_init(void)
|
||||
{
|
||||
int r = 0;
|
||||
@@ -693,6 +898,65 @@ static void __init omap3_beagle_init(void)
|
||||
/* REVISIT leave DVI powered down until it's needed ... */
|
||||
gpio_direction_output(170, true);
|
||||
|
||||
+ if(!strcmp(expansionboard_name, "zippy"))
|
||||
+ {
|
||||
+ printk(KERN_INFO "Beagle expansionboard: initializing enc28j60\n");
|
||||
+ omap3beagle_enc28j60_init();
|
||||
+ printk(KERN_INFO "Beagle expansionboard: assigning GPIO 141 and 162 to MMC1\n");
|
||||
+ mmc[1].gpio_wp = 141;
|
||||
+ mmc[1].gpio_cd = 162;
|
||||
+ }
|
||||
+
|
||||
+ if(!strcmp(expansionboard_name, "zippy2"))
|
||||
+ {
|
||||
+ printk(KERN_INFO "Beagle expansionboard: initializing ks_8851\n");
|
||||
+ omap3beagle_ks8851_init();
|
||||
+ printk(KERN_INFO "Beagle expansionboard: assigning GPIO 141 and 162 to MMC1\n");
|
||||
+ mmc[1].gpio_wp = 141;
|
||||
+ mmc[1].gpio_cd = 162;
|
||||
+ }
|
||||
+
|
||||
+ if(!strcmp(expansionboard_name, "trainer"))
|
||||
+ {
|
||||
+ printk(KERN_INFO "Beagle expansionboard: exporting GPIOs 130-141,162 to userspace\n");
|
||||
+ gpio_request(130, "sysfs");
|
||||
+ gpio_export(130, 1);
|
||||
+ gpio_request(131, "sysfs");
|
||||
+ gpio_export(131, 1);
|
||||
+ gpio_request(132, "sysfs");
|
||||
+ gpio_export(132, 1);
|
||||
+ gpio_request(133, "sysfs");
|
||||
+ gpio_export(133, 1);
|
||||
+ gpio_request(134, "sysfs");
|
||||
+ gpio_export(134, 1);
|
||||
+ gpio_request(135, "sysfs");
|
||||
+ gpio_export(135, 1);
|
||||
+ gpio_request(136, "sysfs");
|
||||
+ gpio_export(136, 1);
|
||||
+ gpio_request(137, "sysfs");
|
||||
+ gpio_export(137, 1);
|
||||
+ gpio_request(138, "sysfs");
|
||||
+ gpio_export(138, 1);
|
||||
+ gpio_request(139, "sysfs");
|
||||
+ gpio_export(139, 1);
|
||||
+ gpio_request(140, "sysfs");
|
||||
+ gpio_export(140, 1);
|
||||
+ gpio_request(141, "sysfs");
|
||||
+ gpio_export(141, 1);
|
||||
+ gpio_request(162, "sysfs");
|
||||
+ gpio_export(162, 1);
|
||||
+ }
|
||||
+
|
||||
+ if(!strcmp(expansionboard_name, "bbtoys-wifi"))
|
||||
+ {
|
||||
+ if (wl12xx_set_platform_data(&omap_beagle_wlan_data))
|
||||
+ pr_err("error setting wl12xx data\n");
|
||||
+ printk(KERN_INFO "Beagle expansionboard: registering wl12xx bt platform device\n");
|
||||
+ platform_device_register(&wl12xx_device);
|
||||
+ printk(KERN_INFO "Beagle expansionboard: registering wl12xx wifi platform device\n");
|
||||
+ platform_device_register(&omap_vwlan_device);
|
||||
+ }
|
||||
+
|
||||
usb_musb_init(&musb_board_data);
|
||||
usbhs_init(&usbhs_bdata);
|
||||
omap3beagle_flash_init();
|
||||
@@ -705,6 +969,8 @@ static void __init omap3_beagle_init(void)
|
||||
beagle_opp_init();
|
||||
}
|
||||
|
||||
+early_param("buddy", expansionboard_setup);
|
||||
+
|
||||
MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
|
||||
/* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
|
||||
.boot_params = 0x80000100,
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
From 91e701f3287923d11dd295b6a62186909e362503 Mon Sep 17 00:00:00 2001
|
||||
From: Koen Kooi <koen@dominion.thruhere.net>
|
||||
Date: Sat, 21 May 2011 16:18:30 +0200
|
||||
Subject: [PATCH 3/7] OMAP3: beagle: add MADC support
|
||||
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/board-omap3beagle.c | 5 +++++
|
||||
1 files changed, 5 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
index db285e1..da4ba50 100644
|
||||
--- a/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
@@ -634,6 +634,10 @@ static struct twl4030_codec_data beagle_codec_data = {
|
||||
.audio = &beagle_audio_data,
|
||||
};
|
||||
|
||||
+static struct twl4030_madc_platform_data beagle_madc_data = {
|
||||
+ .irq_line = 1,
|
||||
+};
|
||||
+
|
||||
static struct twl4030_platform_data beagle_twldata = {
|
||||
.irq_base = TWL4030_IRQ_BASE,
|
||||
.irq_end = TWL4030_IRQ_END,
|
||||
@@ -642,6 +646,7 @@ static struct twl4030_platform_data beagle_twldata = {
|
||||
.usb = &beagle_usb_data,
|
||||
.gpio = &beagle_gpio_data,
|
||||
.codec = &beagle_codec_data,
|
||||
+ .madc = &beagle_madc_data,
|
||||
.vmmc1 = &beagle_vmmc1,
|
||||
.vsim = &beagle_vsim,
|
||||
.vdac = &beagle_vdac,
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
From 9d7f46abab88c74e674461a2f4e9ab35b524a6ef Mon Sep 17 00:00:00 2001
|
||||
From: Koen Kooi <koen@dominion.thruhere.net>
|
||||
Date: Wed, 25 May 2011 08:56:06 +0200
|
||||
Subject: [PATCH 4/7] OMAP3: beagle: add regulators for camera interface
|
||||
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/board-omap3beagle.c | 50 +++++++++++++++++++++++++++++++
|
||||
1 files changed, 50 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
index da4ba50..211cbdf 100644
|
||||
--- a/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
@@ -453,6 +453,44 @@ static struct regulator_consumer_supply beagle_vsim_supply = {
|
||||
|
||||
static struct gpio_led gpio_leds[];
|
||||
|
||||
+static struct regulator_consumer_supply beagle_vaux3_supply = {
|
||||
+ .supply = "cam_1v8",
|
||||
+};
|
||||
+
|
||||
+static struct regulator_consumer_supply beagle_vaux4_supply = {
|
||||
+ .supply = "cam_2v8",
|
||||
+};
|
||||
+
|
||||
+/* VAUX3 for CAM_1V8 */
|
||||
+static struct regulator_init_data beagle_vaux3 = {
|
||||
+ .constraints = {
|
||||
+ .min_uV = 1800000,
|
||||
+ .max_uV = 1800000,
|
||||
+ .apply_uV = true,
|
||||
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
|
||||
+ | REGULATOR_MODE_STANDBY,
|
||||
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
|
||||
+ | REGULATOR_CHANGE_STATUS,
|
||||
+ },
|
||||
+ .num_consumer_supplies = 1,
|
||||
+ .consumer_supplies = &beagle_vaux3_supply,
|
||||
+};
|
||||
+
|
||||
+/* VAUX4 for CAM_2V8 */
|
||||
+static struct regulator_init_data beagle_vaux4 = {
|
||||
+ .constraints = {
|
||||
+ .min_uV = 1800000,
|
||||
+ .max_uV = 1800000,
|
||||
+ .apply_uV = true,
|
||||
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
|
||||
+ | REGULATOR_MODE_STANDBY,
|
||||
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
|
||||
+ | REGULATOR_CHANGE_STATUS,
|
||||
+ },
|
||||
+ .num_consumer_supplies = 1,
|
||||
+ .consumer_supplies = &beagle_vaux4_supply,
|
||||
+};
|
||||
+
|
||||
static int beagle_twl_gpio_setup(struct device *dev,
|
||||
unsigned gpio, unsigned ngpio)
|
||||
{
|
||||
@@ -504,6 +542,16 @@ static int beagle_twl_gpio_setup(struct device *dev,
|
||||
pr_err("%s: unable to configure EHCI_nOC\n", __func__);
|
||||
}
|
||||
|
||||
+ if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
|
||||
+ /*
|
||||
+ * Power on camera interface - only on pre-production, not
|
||||
+ * needed on production boards
|
||||
+ */
|
||||
+ gpio_request(gpio + 2, "CAM_EN");
|
||||
+ gpio_direction_output(gpio + 2, 1);
|
||||
+ }
|
||||
+
|
||||
+
|
||||
/*
|
||||
* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
|
||||
* high / others active low)
|
||||
@@ -651,6 +699,8 @@ static struct twl4030_platform_data beagle_twldata = {
|
||||
.vsim = &beagle_vsim,
|
||||
.vdac = &beagle_vdac,
|
||||
.vpll2 = &beagle_vpll2,
|
||||
+ .vaux3 = &beagle_vaux3,
|
||||
+ .vaux4 = &beagle_vaux4,
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata beagle_i2c1_boardinfo[] = {
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
From aa93263ed7827e33148396656b7e7ab4579509a5 Mon Sep 17 00:00:00 2001
|
||||
From: Koen Kooi <koen@dominion.thruhere.net>
|
||||
Date: Wed, 25 May 2011 08:57:40 +0200
|
||||
Subject: [PATCH 5/7] OMAP3: beagle: HACK! add in 1GHz OPP
|
||||
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/board-omap3beagle.c | 2 ++
|
||||
1 files changed, 2 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
index 211cbdf..221bfda 100644
|
||||
--- a/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
@@ -911,11 +911,13 @@ static void __init beagle_opp_init(void)
|
||||
/* Enable MPU 1GHz and lower opps */
|
||||
dev = &mh->od->pdev.dev;
|
||||
r = opp_enable(dev, 800000000);
|
||||
+ r |= opp_enable(dev, 1000000000);
|
||||
/* TODO: MPU 1GHz needs SR and ABB */
|
||||
|
||||
/* Enable IVA 800MHz and lower opps */
|
||||
dev = &dh->od->pdev.dev;
|
||||
r |= opp_enable(dev, 660000000);
|
||||
+ r |= opp_enable(dev, 800000000);
|
||||
/* TODO: DSP 800MHz needs SR and ABB */
|
||||
if (r) {
|
||||
pr_err("%s: failed to enable higher opp %d\n",
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
From dd2c7ba245ec1b17e3d323a6c4a1cad9697dbbbe Mon Sep 17 00:00:00 2001
|
||||
From: Koen Kooi <koen@dominion.thruhere.net>
|
||||
Date: Wed, 15 Jun 2011 16:25:50 +0200
|
||||
Subject: [PATCH 6/7] OMAP3: BEAGLE: fix RTC
|
||||
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/board-omap3beagle.c | 3 +++
|
||||
1 files changed, 3 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
index 221bfda..61564a4 100644
|
||||
--- a/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
@@ -941,6 +941,9 @@ static void __init omap3_beagle_init(void)
|
||||
omap3_beagle_init_rev();
|
||||
omap3_beagle_i2c_init();
|
||||
|
||||
+ /* Ensure msecure is mux'd to be able to set the RTC. */
|
||||
+ omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH);
|
||||
+
|
||||
if (cpu_is_omap3630()) {
|
||||
gpio_buttons[0].gpio = 4;
|
||||
}
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
From bd0b2f97c48aa6aac0c6a494f1c6ba5af5de486b Mon Sep 17 00:00:00 2001
|
||||
From: Steve Sakoman <steve@sakoman.com>
|
||||
Date: Mon, 18 Jul 2011 23:13:41 -0500
|
||||
Subject: [PATCH] omap_hsmmc: Set dto to max value of 14 to avoid SD Card timeouts
|
||||
|
||||
This fixes MMC errors due to timeouts on certain SD Cards following suggestions
|
||||
to set dto to 14 by Jason Kridner and Steven Kipisz
|
||||
|
||||
Details of the issue:
|
||||
http://talk.maemo.org/showthread.php?p=1000707#post1000707
|
||||
|
||||
This fix was originally proposed by Sukumar Ghoral of TI.
|
||||
---
|
||||
drivers/mmc/host/omap_hsmmc.c | 3 +++
|
||||
1 files changed, 3 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
|
||||
index 9646a75..7443647 100644
|
||||
--- a/drivers/mmc/host/omap_hsmmc.c
|
||||
+++ b/drivers/mmc/host/omap_hsmmc.c
|
||||
@@ -1049,6 +1049,9 @@ static void set_data_timeout(struct omap_hsmmc_host *host,
|
||||
dto = 14;
|
||||
}
|
||||
|
||||
+ /* Set dto to max value of 14 to avoid SD Card timeouts */
|
||||
+ dto = 14;
|
||||
+
|
||||
reg &= ~DTO_MASK;
|
||||
reg |= dto << DTO_SHIFT;
|
||||
OMAP_HSMMC_WRITE(host->base, SYSCTL, reg);
|
||||
--
|
||||
1.7.0.4
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
From 101b0aedf8152711847e2f9f347d267a3ac7f287 Mon Sep 17 00:00:00 2001
|
||||
From: Sanjeev Premi <premi@ti.com>
|
||||
Date: Fri, 24 Jun 2011 16:23:45 +0000
|
||||
Subject: [PATCH 7/7] omap3: beagle: Use GPTIMERi 1 for clockevents
|
||||
|
||||
The current selection of the GPTIMER on was result of
|
||||
a hardware issue in early versions of the Beagleboards
|
||||
(Ax and B1 thru B4). [1] [2]
|
||||
|
||||
Its been long since the hardware issue has been fixed.
|
||||
This patch uses GPTIMER 1 for all newer board revisions
|
||||
incl. Beagleboard XM.
|
||||
|
||||
[1] http://thread.gmane.org/gmane.comp.hardware.beagleboard.general/91
|
||||
[2] Errata #7 at http://elinux.org/BeagleBoard#Errata
|
||||
|
||||
Signed-off-by: Sanjeev Premi <premi@ti.com>
|
||||
Cc: Paul Walmsley <paul@pwsan.com>
|
||||
Reviewed-by: Paul Walmsley <paul@pwsan.com>
|
||||
---
|
||||
arch/arm/mach-omap2/board-omap3beagle.c | 5 ++++-
|
||||
1 files changed, 4 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
index 61564a4..20d5912 100644
|
||||
--- a/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
@@ -806,7 +806,10 @@ static void __init omap3_beagle_init_irq(void)
|
||||
{
|
||||
omap_init_irq();
|
||||
#ifdef CONFIG_OMAP_32K_TIMER
|
||||
- omap2_gp_clockevent_set_gptimer(12);
|
||||
+ if (omap3_beagle_version == OMAP3BEAGLE_BOARD_AXBX)
|
||||
+ omap2_gp_clockevent_set_gptimer(12);
|
||||
+ else
|
||||
+ omap2_gp_clockevent_set_gptimer(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
3517
extras/recipes-kernel/linux/linux-omap-2.6.39/beagleboard/defconfig
Normal file
3517
extras/recipes-kernel/linux/linux-omap-2.6.39/beagleboard/defconfig
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,859 @@
|
||||
From e630a914bf14bf190feaf4a2cc57f6b27c4024e1 Mon Sep 17 00:00:00 2001
|
||||
From: Javier Martin <javier.martin@vista-silicon.com>
|
||||
Date: Wed, 1 Jun 2011 17:36:48 +0200
|
||||
Subject: [PATCH 1/3] Add driver for Aptina (Micron) mt9p031 sensor.
|
||||
|
||||
Clock frequency of 57MHz used in previous version was wrong since
|
||||
when VDD_IO is 1.8V it can only support 48MHz.
|
||||
|
||||
Two new platform flags have been added:
|
||||
|
||||
- vdd_io: indicates whether the chip is powered with 1.8 or 2.8 VDD_IO.
|
||||
So that it can use the maximum allowed frequency.
|
||||
- version: monochrome and color versions of the chip have exactly
|
||||
the same ID, so the only way to select one of them is through
|
||||
platform data.
|
||||
|
||||
Internal PLL is now used to generate PIXCLK depending on VDD_IO.
|
||||
|
||||
Signed-off-by: Javier Martin <javier.martin@vista-silicon.com>
|
||||
---
|
||||
drivers/media/video/Kconfig | 7 +
|
||||
drivers/media/video/Makefile | 1 +
|
||||
drivers/media/video/mt9p031.c | 763 +++++++++++++++++++++++++++++++++++++++++
|
||||
include/media/mt9p031.h | 23 ++
|
||||
4 files changed, 794 insertions(+), 0 deletions(-)
|
||||
create mode 100644 drivers/media/video/mt9p031.c
|
||||
create mode 100644 include/media/mt9p031.h
|
||||
|
||||
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
|
||||
index 00f51dd..cb87e35 100644
|
||||
--- a/drivers/media/video/Kconfig
|
||||
+++ b/drivers/media/video/Kconfig
|
||||
@@ -329,6 +329,13 @@ config VIDEO_OV7670
|
||||
OV7670 VGA camera. It currently only works with the M88ALP01
|
||||
controller.
|
||||
|
||||
+config VIDEO_MT9P031
|
||||
+ tristate "Aptina MT9P031 support"
|
||||
+ depends on I2C && VIDEO_V4L2
|
||||
+ ---help---
|
||||
+ This is a Video4Linux2 sensor-level driver for the Aptina
|
||||
+ (Micron) mt9p031 5 Mpixel camera.
|
||||
+
|
||||
config VIDEO_MT9V011
|
||||
tristate "Micron mt9v011 sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
|
||||
index ace5d8b..912b29b 100644
|
||||
--- a/drivers/media/video/Makefile
|
||||
+++ b/drivers/media/video/Makefile
|
||||
@@ -65,6 +65,7 @@ obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
|
||||
obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
|
||||
obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
|
||||
obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
|
||||
+obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o
|
||||
obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
|
||||
obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o
|
||||
obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o
|
||||
diff --git a/drivers/media/video/mt9p031.c b/drivers/media/video/mt9p031.c
|
||||
new file mode 100644
|
||||
index 0000000..cd830b1
|
||||
--- /dev/null
|
||||
+++ b/drivers/media/video/mt9p031.c
|
||||
@@ -0,0 +1,763 @@
|
||||
+/*
|
||||
+ * Driver for MT9P031 CMOS Image Sensor from Aptina
|
||||
+ *
|
||||
+ * Copyright (C) 2011, Javier Martin <javier.martin@vista-silicon.com>
|
||||
+ *
|
||||
+ * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
|
||||
+ *
|
||||
+ * Based on the MT9V032 driver and Bastian Hecht's code.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License version 2 as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/log2.h>
|
||||
+#include <linux/pm.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <media/v4l2-subdev.h>
|
||||
+#include <linux/videodev2.h>
|
||||
+
|
||||
+#include <media/mt9p031.h>
|
||||
+#include <media/v4l2-chip-ident.h>
|
||||
+#include <media/v4l2-subdev.h>
|
||||
+#include <media/v4l2-device.h>
|
||||
+
|
||||
+#define MT9P031_EXTCLK_FREQ 20000000
|
||||
+
|
||||
+#define MT9P031_CHIP_VERSION 0x00
|
||||
+#define MT9P031_CHIP_VERSION_VALUE 0x1801
|
||||
+#define MT9P031_ROW_START 0x01
|
||||
+#define MT9P031_ROW_START_MIN 1
|
||||
+#define MT9P031_ROW_START_MAX 2004
|
||||
+#define MT9P031_ROW_START_DEF 54
|
||||
+#define MT9P031_COLUMN_START 0x02
|
||||
+#define MT9P031_COLUMN_START_MIN 1
|
||||
+#define MT9P031_COLUMN_START_MAX 2750
|
||||
+#define MT9P031_COLUMN_START_DEF 16
|
||||
+#define MT9P031_WINDOW_HEIGHT 0x03
|
||||
+#define MT9P031_WINDOW_HEIGHT_MIN 2
|
||||
+#define MT9P031_WINDOW_HEIGHT_MAX 2003
|
||||
+#define MT9P031_WINDOW_HEIGHT_DEF 2003
|
||||
+#define MT9P031_WINDOW_WIDTH 0x04
|
||||
+#define MT9P031_WINDOW_WIDTH_MIN 18
|
||||
+#define MT9P031_WINDOW_WIDTH_MAX 2751
|
||||
+#define MT9P031_WINDOW_WIDTH_DEF 2751
|
||||
+#define MT9P031_H_BLANKING 0x05
|
||||
+#define MT9P031_H_BLANKING_VALUE 0
|
||||
+#define MT9P031_V_BLANKING 0x06
|
||||
+#define MT9P031_V_BLANKING_VALUE 25
|
||||
+#define MT9P031_OUTPUT_CONTROL 0x07
|
||||
+#define MT9P031_OUTPUT_CONTROL_CEN 2
|
||||
+#define MT9P031_OUTPUT_CONTROL_SYN 1
|
||||
+#define MT9P031_SHUTTER_WIDTH_UPPER 0x08
|
||||
+#define MT9P031_SHUTTER_WIDTH 0x09
|
||||
+#define MT9P031_PLL_CONTROL 0x10
|
||||
+#define MT9P031_PLL_CONTROL_PWROFF 0x0050
|
||||
+#define MT9P031_PLL_CONTROL_PWRON 0x0051
|
||||
+#define MT9P031_PLL_CONTROL_USEPLL 0x0052
|
||||
+#define MT9P031_PLL_CONFIG_1 0x11
|
||||
+#define MT9P031_PLL_CONFIG_1_M_48MHZ 0x5000
|
||||
+#define MT9P031_PLL_CONFIG_1_N_48MHZ 0x05
|
||||
+#define MT9P031_PLL_CONFIG_1_M_96MHZ 0x3600
|
||||
+#define MT9P031_PLL_CONFIG_1_N_96MHZ 0x05
|
||||
+#define MT9P031_PLL_CONFIG_2 0x12
|
||||
+#define MT9P031_PLL_CONFIG_2_P1_48MHZ 5
|
||||
+#define MT9P031_PLL_CONFIG_2_P1_96MHZ 2
|
||||
+#define MT9P031_PIXEL_CLOCK_CONTROL 0x0a
|
||||
+#define MT9P031_FRAME_RESTART 0x0b
|
||||
+#define MT9P031_SHUTTER_DELAY 0x0c
|
||||
+#define MT9P031_RST 0x0d
|
||||
+#define MT9P031_RST_ENABLE 1
|
||||
+#define MT9P031_RST_DISABLE 0
|
||||
+#define MT9P031_READ_MODE_1 0x1e
|
||||
+#define MT9P031_READ_MODE_2 0x20
|
||||
+#define MT9P031_READ_MODE_2_ROW_MIR 0x8000
|
||||
+#define MT9P031_READ_MODE_2_COL_MIR 0x4000
|
||||
+#define MT9P031_ROW_ADDRESS_MODE 0x22
|
||||
+#define MT9P031_COLUMN_ADDRESS_MODE 0x23
|
||||
+#define MT9P031_GLOBAL_GAIN 0x35
|
||||
+
|
||||
+struct mt9p031 {
|
||||
+ struct v4l2_subdev subdev;
|
||||
+ struct media_pad pad;
|
||||
+ struct v4l2_rect rect; /* Sensor window */
|
||||
+ struct v4l2_mbus_framefmt format;
|
||||
+ struct mt9p031_platform_data *pdata;
|
||||
+ struct mutex power_lock; /* lock to protect power_count */
|
||||
+ int power_count;
|
||||
+ u16 xskip;
|
||||
+ u16 yskip;
|
||||
+ /* cache register values */
|
||||
+ u16 output_control;
|
||||
+};
|
||||
+
|
||||
+static struct mt9p031 *to_mt9p031(const struct i2c_client *client)
|
||||
+{
|
||||
+ return container_of(i2c_get_clientdata(client), struct mt9p031, subdev);
|
||||
+}
|
||||
+
|
||||
+static int reg_read(struct i2c_client *client, const u8 reg)
|
||||
+{
|
||||
+ s32 data = i2c_smbus_read_word_data(client, reg);
|
||||
+ return data < 0 ? data : swab16(data);
|
||||
+}
|
||||
+
|
||||
+static int reg_write(struct i2c_client *client, const u8 reg,
|
||||
+ const u16 data)
|
||||
+{
|
||||
+ return i2c_smbus_write_word_data(client, reg, swab16(data));
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_set_output_control(struct mt9p031 *mt9p031, u16 clear,
|
||||
+ u16 set)
|
||||
+{
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
|
||||
+ u16 value = (mt9p031->output_control & ~clear) | set;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = reg_write(client, MT9P031_OUTPUT_CONTROL, value);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ mt9p031->output_control = value;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_reset(struct i2c_client *client)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = to_mt9p031(client);
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Disable chip output, synchronous option update */
|
||||
+ ret = reg_write(client, MT9P031_RST, MT9P031_RST_ENABLE);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ret = reg_write(client, MT9P031_RST, MT9P031_RST_DISABLE);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ return mt9p031_set_output_control(mt9p031,
|
||||
+ MT9P031_OUTPUT_CONTROL_CEN, 0);
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_power_on(struct mt9p031 *mt9p031)
|
||||
+{
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Ensure RESET_BAR is low */
|
||||
+ if (mt9p031->pdata->reset) {
|
||||
+ mt9p031->pdata->reset(&mt9p031->subdev, 1);
|
||||
+ msleep(1);
|
||||
+ }
|
||||
+ /* Emable clock */
|
||||
+ if (mt9p031->pdata->set_xclk)
|
||||
+ mt9p031->pdata->set_xclk(&mt9p031->subdev, MT9P031_EXTCLK_FREQ);
|
||||
+ /* Now RESET_BAR must be high */
|
||||
+ if (mt9p031->pdata->reset) {
|
||||
+ mt9p031->pdata->reset(&mt9p031->subdev, 0);
|
||||
+ msleep(1);
|
||||
+ }
|
||||
+ /* soft reset */
|
||||
+ ret = mt9p031_reset(client);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(&client->dev, "Failed to reset the camera\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void mt9p031_power_off(struct mt9p031 *mt9p031)
|
||||
+{
|
||||
+ if (mt9p031->pdata->reset) {
|
||||
+ mt9p031->pdata->reset(&mt9p031->subdev, 1);
|
||||
+ msleep(1);
|
||||
+ }
|
||||
+ if (mt9p031->pdata->set_xclk)
|
||||
+ mt9p031->pdata->set_xclk(&mt9p031->subdev, 0);
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_enum_mbus_code(struct v4l2_subdev *sd,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_mbus_code_enum *code)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+
|
||||
+ if (code->pad || code->index)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ code->code = mt9p031->format.code;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct v4l2_mbus_framefmt *mt9p031_get_pad_format(
|
||||
+ struct mt9p031 *mt9p031,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ unsigned int pad, u32 which)
|
||||
+{
|
||||
+ switch (which) {
|
||||
+ case V4L2_SUBDEV_FORMAT_TRY:
|
||||
+ return v4l2_subdev_get_try_format(fh, pad);
|
||||
+ case V4L2_SUBDEV_FORMAT_ACTIVE:
|
||||
+ return &mt9p031->format;
|
||||
+ default:
|
||||
+ return NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static struct v4l2_rect *mt9p031_get_pad_crop(struct mt9p031 *mt9p031,
|
||||
+ struct v4l2_subdev_fh *fh, unsigned int pad, u32 which)
|
||||
+{
|
||||
+ switch (which) {
|
||||
+ case V4L2_SUBDEV_FORMAT_TRY:
|
||||
+ return v4l2_subdev_get_try_crop(fh, pad);
|
||||
+ case V4L2_SUBDEV_FORMAT_ACTIVE:
|
||||
+ return &mt9p031->rect;
|
||||
+ default:
|
||||
+ return NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_get_crop(struct v4l2_subdev *sd,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_crop *crop)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+ struct v4l2_rect *rect = mt9p031_get_pad_crop(mt9p031, fh, crop->pad,
|
||||
+ crop->which);
|
||||
+ if (!rect)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ crop->rect = *rect;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static u16 mt9p031_skip_for_crop(s32 source, s32 *target, s32 max_skip)
|
||||
+{
|
||||
+ unsigned int skip;
|
||||
+
|
||||
+ if (source - source / 4 < *target) {
|
||||
+ *target = source;
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ skip = DIV_ROUND_CLOSEST(source, *target);
|
||||
+ if (skip > max_skip)
|
||||
+ skip = max_skip;
|
||||
+ *target = 2 * DIV_ROUND_UP(source, 2 * skip);
|
||||
+
|
||||
+ return skip;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_set_params(struct i2c_client *client,
|
||||
+ struct v4l2_rect *rect, u16 xskip, u16 yskip)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = to_mt9p031(client);
|
||||
+ int ret;
|
||||
+ u16 xbin, ybin;
|
||||
+ const u16 hblank = MT9P031_H_BLANKING_VALUE,
|
||||
+ vblank = MT9P031_V_BLANKING_VALUE;
|
||||
+ __s32 left;
|
||||
+
|
||||
+ /*
|
||||
+ * TODO: Attention! When implementing horizontal flipping, adjust
|
||||
+ * alignment according to R2 "Column Start" description in the datasheet
|
||||
+ */
|
||||
+ if (xskip & 1) {
|
||||
+ xbin = 1;
|
||||
+ left = rect->left & (~3);
|
||||
+ } else if (xskip & 2) {
|
||||
+ xbin = 2;
|
||||
+ left = rect->left & (~7);
|
||||
+ } else {
|
||||
+ xbin = 4;
|
||||
+ left = rect->left & (~15);
|
||||
+ }
|
||||
+ ybin = min(yskip, (u16)4);
|
||||
+
|
||||
+ /* Disable register update, reconfigure atomically */
|
||||
+ ret = mt9p031_set_output_control(mt9p031, 0,
|
||||
+ MT9P031_OUTPUT_CONTROL_SYN);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ dev_dbg(&client->dev, "skip %u:%u, rect %ux%u@%u:%u\n",
|
||||
+ xskip, yskip, rect->width, rect->height, rect->left, rect->top);
|
||||
+
|
||||
+ /* Blanking and start values - default... */
|
||||
+ ret = reg_write(client, MT9P031_H_BLANKING, hblank);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ret = reg_write(client, MT9P031_V_BLANKING, vblank);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = reg_write(client, MT9P031_COLUMN_ADDRESS_MODE,
|
||||
+ ((xbin - 1) << 4) | (xskip - 1));
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ret = reg_write(client, MT9P031_ROW_ADDRESS_MODE,
|
||||
+ ((ybin - 1) << 4) | (yskip - 1));
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ dev_dbg(&client->dev, "new physical left %u, top %u\n",
|
||||
+ rect->left, rect->top);
|
||||
+
|
||||
+ ret = reg_write(client, MT9P031_COLUMN_START,
|
||||
+ rect->left);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ret = reg_write(client, MT9P031_ROW_START,
|
||||
+ rect->top);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = reg_write(client, MT9P031_WINDOW_WIDTH,
|
||||
+ rect->width - 1);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ret = reg_write(client, MT9P031_WINDOW_HEIGHT,
|
||||
+ rect->height - 1);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Re-enable register update, commit all changes */
|
||||
+ ret = mt9p031_set_output_control(mt9p031,
|
||||
+ MT9P031_OUTPUT_CONTROL_SYN, 0);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ mt9p031->xskip = xskip;
|
||||
+ mt9p031->yskip = yskip;
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_set_crop(struct v4l2_subdev *sd,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_crop *crop)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+ struct v4l2_mbus_framefmt *f;
|
||||
+ struct v4l2_rect *c;
|
||||
+ struct v4l2_rect rect;
|
||||
+ u16 xskip, yskip;
|
||||
+ s32 width, height;
|
||||
+
|
||||
+ dev_dbg(mt9p031->subdev.v4l2_dev->dev, "%s(%ux%u@%u:%u : %u)\n",
|
||||
+ __func__, crop->rect.width, crop->rect.height,
|
||||
+ crop->rect.left, crop->rect.top, crop->which);
|
||||
+
|
||||
+ /*
|
||||
+ * Clamp the crop rectangle boundaries and align them to a multiple of 2
|
||||
+ * pixels.
|
||||
+ */
|
||||
+ rect.width = ALIGN(clamp(crop->rect.width,
|
||||
+ MT9P031_WINDOW_WIDTH_MIN,
|
||||
+ MT9P031_WINDOW_WIDTH_MAX), 2);
|
||||
+ rect.height = ALIGN(clamp(crop->rect.height,
|
||||
+ MT9P031_WINDOW_HEIGHT_MIN,
|
||||
+ MT9P031_WINDOW_HEIGHT_MAX), 2);
|
||||
+ rect.left = ALIGN(clamp(crop->rect.left,
|
||||
+ MT9P031_COLUMN_START_MIN,
|
||||
+ MT9P031_COLUMN_START_MAX), 2);
|
||||
+ rect.top = ALIGN(clamp(crop->rect.top,
|
||||
+ MT9P031_ROW_START_MIN,
|
||||
+ MT9P031_ROW_START_MAX), 2);
|
||||
+
|
||||
+ c = mt9p031_get_pad_crop(mt9p031, fh, crop->pad, crop->which);
|
||||
+
|
||||
+ if (rect.width != c->width || rect.height != c->height) {
|
||||
+ /*
|
||||
+ * Reset the output image size if the crop rectangle size has
|
||||
+ * been modified.
|
||||
+ */
|
||||
+ f = mt9p031_get_pad_format(mt9p031, fh, crop->pad,
|
||||
+ crop->which);
|
||||
+ width = f->width;
|
||||
+ height = f->height;
|
||||
+
|
||||
+ xskip = mt9p031_skip_for_crop(rect.width, &width, 7);
|
||||
+ yskip = mt9p031_skip_for_crop(rect.height, &height, 8);
|
||||
+ } else {
|
||||
+ xskip = mt9p031->xskip;
|
||||
+ yskip = mt9p031->yskip;
|
||||
+ f = NULL;
|
||||
+ }
|
||||
+ if (f) {
|
||||
+ f->width = width;
|
||||
+ f->height = height;
|
||||
+ }
|
||||
+
|
||||
+ *c = rect;
|
||||
+ crop->rect = rect;
|
||||
+
|
||||
+ mt9p031->xskip = xskip;
|
||||
+ mt9p031->yskip = yskip;
|
||||
+ mt9p031->rect = *c;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_get_format(struct v4l2_subdev *sd,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_format *fmt)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+
|
||||
+ fmt->format =
|
||||
+ *mt9p031_get_pad_format(mt9p031, fh, fmt->pad, fmt->which);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static u16 mt9p031_skip_for_scale(s32 *source, s32 target,
|
||||
+ s32 max_skip, s32 max)
|
||||
+{
|
||||
+ unsigned int skip;
|
||||
+
|
||||
+ if (*source - *source / 4 < target) {
|
||||
+ *source = target;
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ skip = min(max, *source + target / 2) / target;
|
||||
+ if (skip > max_skip)
|
||||
+ skip = max_skip;
|
||||
+ *source = target * skip;
|
||||
+
|
||||
+ return skip;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_set_format(struct v4l2_subdev *sd,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_format *format)
|
||||
+{
|
||||
+ struct v4l2_mbus_framefmt *__format;
|
||||
+ struct v4l2_rect *__crop, rect;
|
||||
+ struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+ unsigned int width;
|
||||
+ unsigned int height;
|
||||
+ u16 xskip, yskip;
|
||||
+
|
||||
+ __crop = mt9p031_get_pad_crop(mt9p031, fh, format->pad, format->which);
|
||||
+
|
||||
+ width = clamp_t(int, ALIGN(format->format.width, 2), 2,
|
||||
+ MT9P031_WINDOW_WIDTH_MAX);
|
||||
+ height = clamp_t(int, ALIGN(format->format.height, 2), 2,
|
||||
+ MT9P031_WINDOW_HEIGHT_MAX);
|
||||
+
|
||||
+ rect.width = __crop->width;
|
||||
+ rect.height = __crop->height;
|
||||
+
|
||||
+ xskip = mt9p031_skip_for_scale(&rect.width, width, 7,
|
||||
+ MT9P031_WINDOW_WIDTH_MAX);
|
||||
+ if (rect.width + __crop->left > MT9P031_WINDOW_WIDTH_MAX)
|
||||
+ rect.left = (MT9P031_WINDOW_WIDTH_MAX - rect.width) / 2;
|
||||
+ else
|
||||
+ rect.left = __crop->left;
|
||||
+ yskip = mt9p031_skip_for_scale(&rect.height, height, 8,
|
||||
+ MT9P031_WINDOW_HEIGHT_MAX);
|
||||
+ if (rect.height + __crop->top > MT9P031_WINDOW_HEIGHT_MAX)
|
||||
+ rect.top = (MT9P031_WINDOW_HEIGHT_MAX - rect.height) / 2;
|
||||
+ else
|
||||
+ rect.top = __crop->top;
|
||||
+
|
||||
+ dev_dbg(mt9p031->subdev.v4l2_dev->dev, "%s(%ux%u : %u)\n", __func__,
|
||||
+ width, height, format->which);
|
||||
+ if (__crop)
|
||||
+ *__crop = rect;
|
||||
+
|
||||
+ __format = mt9p031_get_pad_format(mt9p031, fh, format->pad,
|
||||
+ format->which);
|
||||
+ __format->width = width;
|
||||
+ __format->height = height;
|
||||
+ format->format = *__format;
|
||||
+
|
||||
+ mt9p031->xskip = xskip;
|
||||
+ mt9p031->yskip = yskip;
|
||||
+ mt9p031->rect = *__crop;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_pll_enable(struct i2c_client *client)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = to_mt9p031(client);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = reg_write(client, MT9P031_PLL_CONTROL, MT9P031_PLL_CONTROL_PWRON);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Always set the maximum frequency allowed by VDD_IO */
|
||||
+ if (mt9p031->pdata->vdd_io == MT9P031_VDD_IO_2V8) {
|
||||
+ ret = reg_write(client, MT9P031_PLL_CONFIG_1,
|
||||
+ MT9P031_PLL_CONFIG_1_M_96MHZ |
|
||||
+ MT9P031_PLL_CONFIG_1_N_96MHZ);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ret = reg_write(client, MT9P031_PLL_CONFIG_2,
|
||||
+ MT9P031_PLL_CONFIG_2_P1_96MHZ);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ } else {
|
||||
+ ret = reg_write(client, MT9P031_PLL_CONFIG_1,
|
||||
+ MT9P031_PLL_CONFIG_1_M_48MHZ |
|
||||
+ MT9P031_PLL_CONFIG_1_N_48MHZ);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ret = reg_write(client, MT9P031_PLL_CONFIG_2,
|
||||
+ MT9P031_PLL_CONFIG_2_P1_48MHZ);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ }
|
||||
+ mdelay(1);
|
||||
+ ret = reg_write(client, MT9P031_PLL_CONTROL,
|
||||
+ MT9P031_PLL_CONTROL_PWRON |
|
||||
+ MT9P031_PLL_CONTROL_USEPLL);
|
||||
+ mdelay(1);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static inline int mt9p031_pll_disable(struct i2c_client *client)
|
||||
+{
|
||||
+ return reg_write(client, MT9P031_PLL_CONTROL,
|
||||
+ MT9P031_PLL_CONTROL_PWROFF);
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_s_stream(struct v4l2_subdev *sd, int enable)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
|
||||
+ struct v4l2_rect rect = mt9p031->rect;
|
||||
+ u16 xskip = mt9p031->xskip;
|
||||
+ u16 yskip = mt9p031->yskip;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (enable) {
|
||||
+ ret = mt9p031_set_params(client, &rect, xskip, yskip);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ /* Switch to master "normal" mode */
|
||||
+ ret = mt9p031_set_output_control(mt9p031, 0,
|
||||
+ MT9P031_OUTPUT_CONTROL_CEN);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ret = mt9p031_pll_enable(client);
|
||||
+ } else {
|
||||
+ /* Stop sensor readout */
|
||||
+ ret = mt9p031_set_output_control(mt9p031,
|
||||
+ MT9P031_OUTPUT_CONTROL_CEN, 0);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ret = mt9p031_pll_disable(client);
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_video_probe(struct i2c_client *client)
|
||||
+{
|
||||
+ s32 data;
|
||||
+
|
||||
+ /* Read out the chip version register */
|
||||
+ data = reg_read(client, MT9P031_CHIP_VERSION);
|
||||
+ if (data != MT9P031_CHIP_VERSION_VALUE) {
|
||||
+ dev_err(&client->dev,
|
||||
+ "No MT9P031 chip detected, register read %x\n", data);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ dev_info(&client->dev, "Detected a MT9P031 chip ID %x\n", data);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_set_power(struct v4l2_subdev *sd, int on)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ mutex_lock(&mt9p031->power_lock);
|
||||
+
|
||||
+ /*
|
||||
+ * If the power count is modified from 0 to != 0 or from != 0 to 0,
|
||||
+ * update the power state.
|
||||
+ */
|
||||
+ if (mt9p031->power_count == !on) {
|
||||
+ if (on) {
|
||||
+ ret = mt9p031_power_on(mt9p031);
|
||||
+ if (ret) {
|
||||
+ dev_err(mt9p031->subdev.v4l2_dev->dev,
|
||||
+ "Failed to power on: %d\n", ret);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ } else {
|
||||
+ mt9p031_power_off(mt9p031);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Update the power count. */
|
||||
+ mt9p031->power_count += on ? 1 : -1;
|
||||
+ WARN_ON(mt9p031->power_count < 0);
|
||||
+
|
||||
+out:
|
||||
+ mutex_unlock(&mt9p031->power_lock);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_registered(struct v4l2_subdev *sd)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = mt9p031_set_power(&mt9p031->subdev, 1);
|
||||
+ if (ret) {
|
||||
+ dev_err(&client->dev,
|
||||
+ "Failed to power on device: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = mt9p031_video_probe(client);
|
||||
+
|
||||
+ mt9p031_set_power(&mt9p031->subdev, 0);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031;
|
||||
+ mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+
|
||||
+ mt9p031->rect.width = MT9P031_WINDOW_WIDTH_DEF;
|
||||
+ mt9p031->rect.height = MT9P031_WINDOW_HEIGHT_DEF;
|
||||
+ mt9p031->rect.left = MT9P031_COLUMN_START_DEF;
|
||||
+ mt9p031->rect.top = MT9P031_ROW_START_DEF;
|
||||
+
|
||||
+ if (mt9p031->pdata->version == MT9P031_MONOCHROME_VERSION)
|
||||
+ mt9p031->format.code = V4L2_MBUS_FMT_Y12_1X12;
|
||||
+ else
|
||||
+ mt9p031->format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
|
||||
+
|
||||
+ mt9p031->format.width = MT9P031_WINDOW_WIDTH_DEF;
|
||||
+ mt9p031->format.height = MT9P031_WINDOW_HEIGHT_DEF;
|
||||
+ mt9p031->format.field = V4L2_FIELD_NONE;
|
||||
+ mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB;
|
||||
+
|
||||
+ mt9p031->xskip = 1;
|
||||
+ mt9p031->yskip = 1;
|
||||
+ return mt9p031_set_power(sd, 1);
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
+{
|
||||
+ return mt9p031_set_power(sd, 0);
|
||||
+}
|
||||
+
|
||||
+static struct v4l2_subdev_core_ops mt9p031_subdev_core_ops = {
|
||||
+ .s_power = mt9p031_set_power,
|
||||
+};
|
||||
+
|
||||
+static struct v4l2_subdev_video_ops mt9p031_subdev_video_ops = {
|
||||
+ .s_stream = mt9p031_s_stream,
|
||||
+};
|
||||
+
|
||||
+static struct v4l2_subdev_pad_ops mt9p031_subdev_pad_ops = {
|
||||
+ .enum_mbus_code = mt9p031_enum_mbus_code,
|
||||
+ .get_fmt = mt9p031_get_format,
|
||||
+ .set_fmt = mt9p031_set_format,
|
||||
+ .get_crop = mt9p031_get_crop,
|
||||
+ .set_crop = mt9p031_set_crop,
|
||||
+};
|
||||
+
|
||||
+static struct v4l2_subdev_ops mt9p031_subdev_ops = {
|
||||
+ .core = &mt9p031_subdev_core_ops,
|
||||
+ .video = &mt9p031_subdev_video_ops,
|
||||
+ .pad = &mt9p031_subdev_pad_ops,
|
||||
+};
|
||||
+
|
||||
+static const struct v4l2_subdev_internal_ops mt9p031_subdev_internal_ops = {
|
||||
+ .registered = mt9p031_registered,
|
||||
+ .open = mt9p031_open,
|
||||
+ .close = mt9p031_close,
|
||||
+};
|
||||
+
|
||||
+static int mt9p031_probe(struct i2c_client *client,
|
||||
+ const struct i2c_device_id *did)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct mt9p031 *mt9p031;
|
||||
+ struct mt9p031_platform_data *pdata = client->dev.platform_data;
|
||||
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
|
||||
+
|
||||
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
|
||||
+ dev_warn(&adapter->dev,
|
||||
+ "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ mt9p031 = kzalloc(sizeof(struct mt9p031), GFP_KERNEL);
|
||||
+ if (!mt9p031)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ mutex_init(&mt9p031->power_lock);
|
||||
+ v4l2_i2c_subdev_init(&mt9p031->subdev, client, &mt9p031_subdev_ops);
|
||||
+ mt9p031->subdev.internal_ops = &mt9p031_subdev_internal_ops;
|
||||
+
|
||||
+ mt9p031->pdata = pdata;
|
||||
+
|
||||
+ mt9p031->pad.flags = MEDIA_PAD_FL_SOURCE;
|
||||
+ ret = media_entity_init(&mt9p031->subdev.entity, 1, &mt9p031->pad, 0);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ mt9p031->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_remove(struct i2c_client *client)
|
||||
+{
|
||||
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
|
||||
+ struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+
|
||||
+ v4l2_device_unregister_subdev(sd);
|
||||
+ media_entity_cleanup(&sd->entity);
|
||||
+ kfree(mt9p031);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct i2c_device_id mt9p031_id[] = {
|
||||
+ { "mt9p031", 0 },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(i2c, mt9p031_id);
|
||||
+
|
||||
+static struct i2c_driver mt9p031_i2c_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "mt9p031",
|
||||
+ },
|
||||
+ .probe = mt9p031_probe,
|
||||
+ .remove = mt9p031_remove,
|
||||
+ .id_table = mt9p031_id,
|
||||
+};
|
||||
+
|
||||
+static int __init mt9p031_mod_init(void)
|
||||
+{
|
||||
+ return i2c_add_driver(&mt9p031_i2c_driver);
|
||||
+}
|
||||
+
|
||||
+static void __exit mt9p031_mod_exit(void)
|
||||
+{
|
||||
+ i2c_del_driver(&mt9p031_i2c_driver);
|
||||
+}
|
||||
+
|
||||
+module_init(mt9p031_mod_init);
|
||||
+module_exit(mt9p031_mod_exit);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Aptina MT9P031 Camera driver");
|
||||
+MODULE_AUTHOR("Bastian Hecht <hechtb@gmail.com>");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
diff --git a/include/media/mt9p031.h b/include/media/mt9p031.h
|
||||
new file mode 100644
|
||||
index 0000000..27b4c75
|
||||
--- /dev/null
|
||||
+++ b/include/media/mt9p031.h
|
||||
@@ -0,0 +1,23 @@
|
||||
+#ifndef MT9P031_H
|
||||
+#define MT9P031_H
|
||||
+
|
||||
+struct v4l2_subdev;
|
||||
+
|
||||
+enum {
|
||||
+ MT9P031_COLOR_VERSION = 0,
|
||||
+ MT9P031_MONOCHROME_VERSION = 1,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ MT9P031_VDD_IO_1V8 = 0,
|
||||
+ MT9P031_VDD_IO_2V8 = 1,
|
||||
+};
|
||||
+
|
||||
+struct mt9p031_platform_data {
|
||||
+ int (*set_xclk)(struct v4l2_subdev *subdev, int hz);
|
||||
+ int (*reset)(struct v4l2_subdev *subdev, int active);
|
||||
+ int vdd_io; /* MT9P031_VDD_IO_1V8 or MT9P031_VDD_IO_2V8 */
|
||||
+ int version; /* MT9P031_COLOR_VERSION or MT9P031_MONOCHROME_VERSION */
|
||||
+};
|
||||
+
|
||||
+#endif
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,853 @@
|
||||
From ba65e798c98e9c4d331deb2b51337964336d3f78 Mon Sep 17 00:00:00 2001
|
||||
From: Detlev Casanova <detlev.casanova@gmail.com>
|
||||
Date: Sun, 28 Nov 2010 19:07:20 +0100
|
||||
Subject: [PATCH 2/3] v4l: Add mt9v032 sensor driver
|
||||
|
||||
The MT9V032 is a parallel wide VGA sensor from Aptina (formerly Micron)
|
||||
controlled through I2C.
|
||||
|
||||
The driver creates a V4L2 subdevice. It currently supports binning and
|
||||
cropping, and the gain, auto gain, exposure, auto exposure and test
|
||||
pattern controls.
|
||||
|
||||
Signed-off-by: Detlev Casanova <detlev.casanova@gmail.com>
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
---
|
||||
drivers/media/video/Kconfig | 7 +
|
||||
drivers/media/video/Makefile | 1 +
|
||||
drivers/media/video/mt9v032.c | 773 +++++++++++++++++++++++++++++++++++++++++
|
||||
include/media/mt9v032.h | 12 +
|
||||
4 files changed, 793 insertions(+), 0 deletions(-)
|
||||
create mode 100644 drivers/media/video/mt9v032.c
|
||||
create mode 100644 include/media/mt9v032.h
|
||||
|
||||
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
|
||||
index cb87e35..3a5bc57 100644
|
||||
--- a/drivers/media/video/Kconfig
|
||||
+++ b/drivers/media/video/Kconfig
|
||||
@@ -344,6 +344,13 @@ config VIDEO_MT9V011
|
||||
mt0v011 1.3 Mpixel camera. It currently only works with the
|
||||
em28xx driver.
|
||||
|
||||
+config VIDEO_MT9V032
|
||||
+ tristate "Micron MT9V032 sensor support"
|
||||
+ depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
+ ---help---
|
||||
+ This is a Video4Linux2 sensor-level driver for the Micron
|
||||
+ MT9V032 752x480 CMOS sensor.
|
||||
+
|
||||
config VIDEO_TCM825X
|
||||
tristate "TCM825x camera sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
|
||||
index 912b29b..6679c6a 100644
|
||||
--- a/drivers/media/video/Makefile
|
||||
+++ b/drivers/media/video/Makefile
|
||||
@@ -67,6 +67,7 @@ obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
|
||||
obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
|
||||
obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o
|
||||
obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
|
||||
+obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
|
||||
obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o
|
||||
obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o
|
||||
|
||||
diff --git a/drivers/media/video/mt9v032.c b/drivers/media/video/mt9v032.c
|
||||
new file mode 100644
|
||||
index 0000000..c64e1dc
|
||||
--- /dev/null
|
||||
+++ b/drivers/media/video/mt9v032.c
|
||||
@@ -0,0 +1,773 @@
|
||||
+/*
|
||||
+ * Driver for MT9V032 CMOS Image Sensor from Micron
|
||||
+ *
|
||||
+ * Copyright (C) 2010, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
+ *
|
||||
+ * Based on the MT9M001 driver,
|
||||
+ *
|
||||
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License version 2 as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/log2.h>
|
||||
+#include <linux/mutex.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/videodev2.h>
|
||||
+#include <linux/v4l2-mediabus.h>
|
||||
+
|
||||
+#include <media/mt9v032.h>
|
||||
+#include <media/v4l2-ctrls.h>
|
||||
+#include <media/v4l2-device.h>
|
||||
+#include <media/v4l2-subdev.h>
|
||||
+
|
||||
+#define MT9V032_PIXEL_ARRAY_HEIGHT 492
|
||||
+#define MT9V032_PIXEL_ARRAY_WIDTH 782
|
||||
+
|
||||
+#define MT9V032_CHIP_VERSION 0x00
|
||||
+#define MT9V032_CHIP_ID_REV1 0x1311
|
||||
+#define MT9V032_CHIP_ID_REV3 0x1313
|
||||
+#define MT9V032_COLUMN_START 0x01
|
||||
+#define MT9V032_COLUMN_START_MIN 1
|
||||
+#define MT9V032_COLUMN_START_DEF 1
|
||||
+#define MT9V032_COLUMN_START_MAX 752
|
||||
+#define MT9V032_ROW_START 0x02
|
||||
+#define MT9V032_ROW_START_MIN 4
|
||||
+#define MT9V032_ROW_START_DEF 5
|
||||
+#define MT9V032_ROW_START_MAX 482
|
||||
+#define MT9V032_WINDOW_HEIGHT 0x03
|
||||
+#define MT9V032_WINDOW_HEIGHT_MIN 1
|
||||
+#define MT9V032_WINDOW_HEIGHT_DEF 480
|
||||
+#define MT9V032_WINDOW_HEIGHT_MAX 480
|
||||
+#define MT9V032_WINDOW_WIDTH 0x04
|
||||
+#define MT9V032_WINDOW_WIDTH_MIN 1
|
||||
+#define MT9V032_WINDOW_WIDTH_DEF 752
|
||||
+#define MT9V032_WINDOW_WIDTH_MAX 752
|
||||
+#define MT9V032_HORIZONTAL_BLANKING 0x05
|
||||
+#define MT9V032_HORIZONTAL_BLANKING_MIN 43
|
||||
+#define MT9V032_HORIZONTAL_BLANKING_MAX 1023
|
||||
+#define MT9V032_VERTICAL_BLANKING 0x06
|
||||
+#define MT9V032_VERTICAL_BLANKING_MIN 4
|
||||
+#define MT9V032_VERTICAL_BLANKING_MAX 3000
|
||||
+#define MT9V032_CHIP_CONTROL 0x07
|
||||
+#define MT9V032_CHIP_CONTROL_MASTER_MODE (1 << 3)
|
||||
+#define MT9V032_CHIP_CONTROL_DOUT_ENABLE (1 << 7)
|
||||
+#define MT9V032_CHIP_CONTROL_SEQUENTIAL (1 << 8)
|
||||
+#define MT9V032_SHUTTER_WIDTH1 0x08
|
||||
+#define MT9V032_SHUTTER_WIDTH2 0x09
|
||||
+#define MT9V032_SHUTTER_WIDTH_CONTROL 0x0a
|
||||
+#define MT9V032_TOTAL_SHUTTER_WIDTH 0x0b
|
||||
+#define MT9V032_TOTAL_SHUTTER_WIDTH_MIN 1
|
||||
+#define MT9V032_TOTAL_SHUTTER_WIDTH_DEF 480
|
||||
+#define MT9V032_TOTAL_SHUTTER_WIDTH_MAX 32767
|
||||
+#define MT9V032_RESET 0x0c
|
||||
+#define MT9V032_READ_MODE 0x0d
|
||||
+#define MT9V032_READ_MODE_ROW_BIN_MASK (3 << 0)
|
||||
+#define MT9V032_READ_MODE_ROW_BIN_SHIFT 0
|
||||
+#define MT9V032_READ_MODE_COLUMN_BIN_MASK (3 << 2)
|
||||
+#define MT9V032_READ_MODE_COLUMN_BIN_SHIFT 2
|
||||
+#define MT9V032_READ_MODE_ROW_FLIP (1 << 4)
|
||||
+#define MT9V032_READ_MODE_COLUMN_FLIP (1 << 5)
|
||||
+#define MT9V032_READ_MODE_DARK_COLUMNS (1 << 6)
|
||||
+#define MT9V032_READ_MODE_DARK_ROWS (1 << 7)
|
||||
+#define MT9V032_PIXEL_OPERATION_MODE 0x0f
|
||||
+#define MT9V032_PIXEL_OPERATION_MODE_COLOR (1 << 2)
|
||||
+#define MT9V032_PIXEL_OPERATION_MODE_HDR (1 << 6)
|
||||
+#define MT9V032_ANALOG_GAIN 0x35
|
||||
+#define MT9V032_ANALOG_GAIN_MIN 16
|
||||
+#define MT9V032_ANALOG_GAIN_DEF 16
|
||||
+#define MT9V032_ANALOG_GAIN_MAX 64
|
||||
+#define MT9V032_MAX_ANALOG_GAIN 0x36
|
||||
+#define MT9V032_MAX_ANALOG_GAIN_MAX 127
|
||||
+#define MT9V032_FRAME_DARK_AVERAGE 0x42
|
||||
+#define MT9V032_DARK_AVG_THRESH 0x46
|
||||
+#define MT9V032_DARK_AVG_LOW_THRESH_MASK (255 << 0)
|
||||
+#define MT9V032_DARK_AVG_LOW_THRESH_SHIFT 0
|
||||
+#define MT9V032_DARK_AVG_HIGH_THRESH_MASK (255 << 8)
|
||||
+#define MT9V032_DARK_AVG_HIGH_THRESH_SHIFT 8
|
||||
+#define MT9V032_ROW_NOISE_CORR_CONTROL 0x70
|
||||
+#define MT9V032_ROW_NOISE_CORR_ENABLE (1 << 5)
|
||||
+#define MT9V032_ROW_NOISE_CORR_USE_BLK_AVG (1 << 7)
|
||||
+#define MT9V032_PIXEL_CLOCK 0x74
|
||||
+#define MT9V032_PIXEL_CLOCK_INV_LINE (1 << 0)
|
||||
+#define MT9V032_PIXEL_CLOCK_INV_FRAME (1 << 1)
|
||||
+#define MT9V032_PIXEL_CLOCK_XOR_LINE (1 << 2)
|
||||
+#define MT9V032_PIXEL_CLOCK_CONT_LINE (1 << 3)
|
||||
+#define MT9V032_PIXEL_CLOCK_INV_PXL_CLK (1 << 4)
|
||||
+#define MT9V032_TEST_PATTERN 0x7f
|
||||
+#define MT9V032_TEST_PATTERN_DATA_MASK (1023 << 0)
|
||||
+#define MT9V032_TEST_PATTERN_DATA_SHIFT 0
|
||||
+#define MT9V032_TEST_PATTERN_USE_DATA (1 << 10)
|
||||
+#define MT9V032_TEST_PATTERN_GRAY_MASK (3 << 11)
|
||||
+#define MT9V032_TEST_PATTERN_GRAY_NONE (0 << 11)
|
||||
+#define MT9V032_TEST_PATTERN_GRAY_VERTICAL (1 << 11)
|
||||
+#define MT9V032_TEST_PATTERN_GRAY_HORIZONTAL (2 << 11)
|
||||
+#define MT9V032_TEST_PATTERN_GRAY_DIAGONAL (3 << 11)
|
||||
+#define MT9V032_TEST_PATTERN_ENABLE (1 << 13)
|
||||
+#define MT9V032_TEST_PATTERN_FLIP (1 << 14)
|
||||
+#define MT9V032_AEC_AGC_ENABLE 0xaf
|
||||
+#define MT9V032_AEC_ENABLE (1 << 0)
|
||||
+#define MT9V032_AGC_ENABLE (1 << 1)
|
||||
+#define MT9V032_THERMAL_INFO 0xc1
|
||||
+
|
||||
+struct mt9v032 {
|
||||
+ struct v4l2_subdev subdev;
|
||||
+ struct media_pad pad;
|
||||
+
|
||||
+ struct v4l2_mbus_framefmt format;
|
||||
+ struct v4l2_rect crop;
|
||||
+
|
||||
+ struct v4l2_ctrl_handler ctrls;
|
||||
+
|
||||
+ struct mutex power_lock;
|
||||
+ int power_count;
|
||||
+
|
||||
+ struct mt9v032_platform_data *pdata;
|
||||
+ u16 chip_control;
|
||||
+ u16 aec_agc;
|
||||
+};
|
||||
+
|
||||
+static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd)
|
||||
+{
|
||||
+ return container_of(sd, struct mt9v032, subdev);
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_read(struct i2c_client *client, const u8 reg)
|
||||
+{
|
||||
+ s32 data = i2c_smbus_read_word_data(client, reg);
|
||||
+ dev_dbg(&client->dev, "%s: read 0x%04x from 0x%02x\n", __func__,
|
||||
+ swab16(data), reg);
|
||||
+ return data < 0 ? data : swab16(data);
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_write(struct i2c_client *client, const u8 reg,
|
||||
+ const u16 data)
|
||||
+{
|
||||
+ dev_dbg(&client->dev, "%s: writing 0x%04x to 0x%02x\n", __func__,
|
||||
+ data, reg);
|
||||
+ return i2c_smbus_write_word_data(client, reg, swab16(data));
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_set_chip_control(struct mt9v032 *mt9v032, u16 clear, u16 set)
|
||||
+{
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
|
||||
+ u16 value = (mt9v032->chip_control & ~clear) | set;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = mt9v032_write(client, MT9V032_CHIP_CONTROL, value);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ mt9v032->chip_control = value;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
|
||||
+{
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
|
||||
+ u16 value = mt9v032->aec_agc;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (enable)
|
||||
+ value |= which;
|
||||
+ else
|
||||
+ value &= ~which;
|
||||
+
|
||||
+ ret = mt9v032_write(client, MT9V032_AEC_AGC_ENABLE, value);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ mt9v032->aec_agc = value;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_power_on(struct mt9v032 *mt9v032)
|
||||
+{
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
|
||||
+ int ret;
|
||||
+
|
||||
+ if (mt9v032->pdata->set_clock) {
|
||||
+ mt9v032->pdata->set_clock(&mt9v032->subdev, 25000000);
|
||||
+ udelay(1);
|
||||
+ }
|
||||
+
|
||||
+ /* Reset the chip and stop data read out */
|
||||
+ ret = mt9v032_write(client, MT9V032_RESET, 1);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = mt9v032_write(client, MT9V032_RESET, 0);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ return mt9v032_write(client, MT9V032_CHIP_CONTROL, 0);
|
||||
+}
|
||||
+
|
||||
+static void mt9v032_power_off(struct mt9v032 *mt9v032)
|
||||
+{
|
||||
+ if (mt9v032->pdata->set_clock)
|
||||
+ mt9v032->pdata->set_clock(&mt9v032->subdev, 0);
|
||||
+}
|
||||
+
|
||||
+static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
|
||||
+{
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!on) {
|
||||
+ mt9v032_power_off(mt9v032);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ ret = mt9v032_power_on(mt9v032);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Configure the pixel clock polarity */
|
||||
+ if (mt9v032->pdata && mt9v032->pdata->clk_pol) {
|
||||
+ ret = mt9v032_write(client, MT9V032_PIXEL_CLOCK,
|
||||
+ MT9V032_PIXEL_CLOCK_INV_PXL_CLK);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Disable the noise correction algorithm and restore the controls. */
|
||||
+ ret = mt9v032_write(client, MT9V032_ROW_NOISE_CORR_CONTROL, 0);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ return v4l2_ctrl_handler_setup(&mt9v032->ctrls);
|
||||
+}
|
||||
+
|
||||
+/* -----------------------------------------------------------------------------
|
||||
+ * V4L2 subdev video operations
|
||||
+ */
|
||||
+
|
||||
+static struct v4l2_mbus_framefmt *
|
||||
+__mt9v032_get_pad_format(struct mt9v032 *mt9v032, struct v4l2_subdev_fh *fh,
|
||||
+ unsigned int pad, enum v4l2_subdev_format_whence which)
|
||||
+{
|
||||
+ switch (which) {
|
||||
+ case V4L2_SUBDEV_FORMAT_TRY:
|
||||
+ return v4l2_subdev_get_try_format(fh, pad);
|
||||
+ case V4L2_SUBDEV_FORMAT_ACTIVE:
|
||||
+ return &mt9v032->format;
|
||||
+ default:
|
||||
+ return NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static struct v4l2_rect *
|
||||
+__mt9v032_get_pad_crop(struct mt9v032 *mt9v032, struct v4l2_subdev_fh *fh,
|
||||
+ unsigned int pad, enum v4l2_subdev_format_whence which)
|
||||
+{
|
||||
+ switch (which) {
|
||||
+ case V4L2_SUBDEV_FORMAT_TRY:
|
||||
+ return v4l2_subdev_get_try_crop(fh, pad);
|
||||
+ case V4L2_SUBDEV_FORMAT_ACTIVE:
|
||||
+ return &mt9v032->crop;
|
||||
+ default:
|
||||
+ return NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
|
||||
+{
|
||||
+ const u16 mode = MT9V032_CHIP_CONTROL_MASTER_MODE
|
||||
+ | MT9V032_CHIP_CONTROL_DOUT_ENABLE
|
||||
+ | MT9V032_CHIP_CONTROL_SEQUENTIAL;
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(subdev);
|
||||
+ struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
+ struct v4l2_mbus_framefmt *format = &mt9v032->format;
|
||||
+ struct v4l2_rect *crop = &mt9v032->crop;
|
||||
+ unsigned int hratio;
|
||||
+ unsigned int vratio;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!enable)
|
||||
+ return mt9v032_set_chip_control(mt9v032, mode, 0);
|
||||
+
|
||||
+ /* Configure the window size and row/column bin */
|
||||
+ hratio = DIV_ROUND_CLOSEST(crop->width, format->width);
|
||||
+ vratio = DIV_ROUND_CLOSEST(crop->height, format->height);
|
||||
+
|
||||
+ ret = mt9v032_write(client, MT9V032_READ_MODE,
|
||||
+ (hratio - 1) << MT9V032_READ_MODE_ROW_BIN_SHIFT |
|
||||
+ (vratio - 1) << MT9V032_READ_MODE_COLUMN_BIN_SHIFT);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = mt9v032_write(client, MT9V032_COLUMN_START, crop->left);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = mt9v032_write(client, MT9V032_ROW_START, crop->top);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = mt9v032_write(client, MT9V032_WINDOW_WIDTH, crop->width);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = mt9v032_write(client, MT9V032_WINDOW_HEIGHT, crop->height);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING,
|
||||
+ max(43, 660 - crop->width));
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Switch to master "normal" mode */
|
||||
+ return mt9v032_set_chip_control(mt9v032, 0, mode);
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_mbus_code_enum *code)
|
||||
+{
|
||||
+ if (code->index > 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ code->code = V4L2_MBUS_FMT_SGRBG10_1X10;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_enum_frame_size(struct v4l2_subdev *subdev,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_frame_size_enum *fse)
|
||||
+{
|
||||
+ if (fse->index >= 8 || fse->code != V4L2_MBUS_FMT_SGRBG10_1X10)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ fse->min_width = MT9V032_WINDOW_WIDTH_DEF / fse->index;
|
||||
+ fse->max_width = fse->min_width;
|
||||
+ fse->min_height = MT9V032_WINDOW_HEIGHT_DEF / fse->index;
|
||||
+ fse->max_height = fse->min_height;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_get_format(struct v4l2_subdev *subdev,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_format *format)
|
||||
+{
|
||||
+ struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
+
|
||||
+ format->format = *__mt9v032_get_pad_format(mt9v032, fh, format->pad,
|
||||
+ format->which);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_set_format(struct v4l2_subdev *subdev,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_format *format)
|
||||
+{
|
||||
+ struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
+ struct v4l2_mbus_framefmt *__format;
|
||||
+ struct v4l2_rect *__crop;
|
||||
+ unsigned int width;
|
||||
+ unsigned int height;
|
||||
+ unsigned int hratio;
|
||||
+ unsigned int vratio;
|
||||
+
|
||||
+ __crop = __mt9v032_get_pad_crop(mt9v032, fh, format->pad,
|
||||
+ format->which);
|
||||
+
|
||||
+ /* Clamp the width and height to avoid dividing by zero. */
|
||||
+ width = clamp_t(unsigned int, ALIGN(format->format.width, 2),
|
||||
+ max(__crop->width / 8, MT9V032_WINDOW_WIDTH_MIN),
|
||||
+ __crop->width);
|
||||
+ height = clamp_t(unsigned int, ALIGN(format->format.height, 2),
|
||||
+ max(__crop->height / 8, MT9V032_WINDOW_HEIGHT_MIN),
|
||||
+ __crop->height);
|
||||
+
|
||||
+ hratio = DIV_ROUND_CLOSEST(__crop->width, width);
|
||||
+ vratio = DIV_ROUND_CLOSEST(__crop->height, height);
|
||||
+
|
||||
+ __format = __mt9v032_get_pad_format(mt9v032, fh, format->pad,
|
||||
+ format->which);
|
||||
+ __format->width = __crop->width / hratio;
|
||||
+ __format->height = __crop->height / vratio;
|
||||
+
|
||||
+ format->format = *__format;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_get_crop(struct v4l2_subdev *subdev,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_crop *crop)
|
||||
+{
|
||||
+ struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
+
|
||||
+ crop->rect = *__mt9v032_get_pad_crop(mt9v032, fh, crop->pad,
|
||||
+ crop->which);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_set_crop(struct v4l2_subdev *subdev,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_crop *crop)
|
||||
+{
|
||||
+ struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
+ struct v4l2_mbus_framefmt *__format;
|
||||
+ struct v4l2_rect *__crop;
|
||||
+ struct v4l2_rect rect;
|
||||
+
|
||||
+ /* Clamp the crop rectangle boundaries and align them to a non multiple
|
||||
+ * of 2 pixels to ensure a GRBG Bayer pattern.
|
||||
+ */
|
||||
+ rect.left = clamp(ALIGN(crop->rect.left + 1, 2) - 1,
|
||||
+ MT9V032_COLUMN_START_MIN,
|
||||
+ MT9V032_COLUMN_START_MAX);
|
||||
+ rect.top = clamp(ALIGN(crop->rect.top + 1, 2) - 1,
|
||||
+ MT9V032_ROW_START_MIN,
|
||||
+ MT9V032_ROW_START_MAX);
|
||||
+ rect.width = clamp(ALIGN(crop->rect.width, 2),
|
||||
+ MT9V032_WINDOW_WIDTH_MIN,
|
||||
+ MT9V032_WINDOW_WIDTH_MAX);
|
||||
+ rect.height = clamp(ALIGN(crop->rect.height, 2),
|
||||
+ MT9V032_WINDOW_HEIGHT_MIN,
|
||||
+ MT9V032_WINDOW_HEIGHT_MAX);
|
||||
+
|
||||
+ rect.width = min(rect.width, MT9V032_PIXEL_ARRAY_WIDTH - rect.left);
|
||||
+ rect.height = min(rect.height, MT9V032_PIXEL_ARRAY_HEIGHT - rect.top);
|
||||
+
|
||||
+ __crop = __mt9v032_get_pad_crop(mt9v032, fh, crop->pad, crop->which);
|
||||
+
|
||||
+ if (rect.width != __crop->width || rect.height != __crop->height) {
|
||||
+ /* Reset the output image size if the crop rectangle size has
|
||||
+ * been modified.
|
||||
+ */
|
||||
+ __format = __mt9v032_get_pad_format(mt9v032, fh, crop->pad,
|
||||
+ crop->which);
|
||||
+ __format->width = rect.width;
|
||||
+ __format->height = rect.height;
|
||||
+ }
|
||||
+
|
||||
+ *__crop = rect;
|
||||
+ crop->rect = rect;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* -----------------------------------------------------------------------------
|
||||
+ * V4L2 subdev control operations
|
||||
+ */
|
||||
+
|
||||
+#define V4L2_CID_TEST_PATTERN (V4L2_CID_USER_BASE | 0x1001)
|
||||
+
|
||||
+static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||
+{
|
||||
+ struct mt9v032 *mt9v032 =
|
||||
+ container_of(ctrl->handler, struct mt9v032, ctrls);
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
|
||||
+ u16 data;
|
||||
+
|
||||
+ switch (ctrl->id) {
|
||||
+ case V4L2_CID_AUTOGAIN:
|
||||
+ return mt9v032_update_aec_agc(mt9v032, MT9V032_AGC_ENABLE,
|
||||
+ ctrl->val);
|
||||
+
|
||||
+ case V4L2_CID_GAIN:
|
||||
+ return mt9v032_write(client, MT9V032_ANALOG_GAIN, ctrl->val);
|
||||
+
|
||||
+ case V4L2_CID_EXPOSURE_AUTO:
|
||||
+ return mt9v032_update_aec_agc(mt9v032, MT9V032_AEC_ENABLE,
|
||||
+ ctrl->val);
|
||||
+
|
||||
+ case V4L2_CID_EXPOSURE:
|
||||
+ return mt9v032_write(client, MT9V032_TOTAL_SHUTTER_WIDTH,
|
||||
+ ctrl->val);
|
||||
+
|
||||
+ case V4L2_CID_TEST_PATTERN:
|
||||
+ switch (ctrl->val) {
|
||||
+ case 0:
|
||||
+ data = 0;
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ data = MT9V032_TEST_PATTERN_GRAY_VERTICAL
|
||||
+ | MT9V032_TEST_PATTERN_ENABLE;
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ data = MT9V032_TEST_PATTERN_GRAY_HORIZONTAL
|
||||
+ | MT9V032_TEST_PATTERN_ENABLE;
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ data = MT9V032_TEST_PATTERN_GRAY_DIAGONAL
|
||||
+ | MT9V032_TEST_PATTERN_ENABLE;
|
||||
+ break;
|
||||
+ default:
|
||||
+ data = (ctrl->val << MT9V032_TEST_PATTERN_DATA_SHIFT)
|
||||
+ | MT9V032_TEST_PATTERN_USE_DATA
|
||||
+ | MT9V032_TEST_PATTERN_ENABLE
|
||||
+ | MT9V032_TEST_PATTERN_FLIP;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return mt9v032_write(client, MT9V032_TEST_PATTERN, data);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct v4l2_ctrl_ops mt9v032_ctrl_ops = {
|
||||
+ .s_ctrl = mt9v032_s_ctrl,
|
||||
+};
|
||||
+
|
||||
+static const struct v4l2_ctrl_config mt9v032_ctrls[] = {
|
||||
+ {
|
||||
+ .ops = &mt9v032_ctrl_ops,
|
||||
+ .id = V4L2_CID_TEST_PATTERN,
|
||||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||||
+ .name = "Test pattern",
|
||||
+ .min = 0,
|
||||
+ .max = 1023,
|
||||
+ .step = 1,
|
||||
+ .def = 0,
|
||||
+ .flags = 0,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+/* -----------------------------------------------------------------------------
|
||||
+ * V4L2 subdev core operations
|
||||
+ */
|
||||
+
|
||||
+static int mt9v032_set_power(struct v4l2_subdev *subdev, int on)
|
||||
+{
|
||||
+ struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ mutex_lock(&mt9v032->power_lock);
|
||||
+
|
||||
+ /* If the power count is modified from 0 to != 0 or from != 0 to 0,
|
||||
+ * update the power state.
|
||||
+ */
|
||||
+ if (mt9v032->power_count == !on) {
|
||||
+ ret = __mt9v032_set_power(mt9v032, !!on);
|
||||
+ if (ret < 0)
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ /* Update the power count. */
|
||||
+ mt9v032->power_count += on ? 1 : -1;
|
||||
+ WARN_ON(mt9v032->power_count < 0);
|
||||
+
|
||||
+done:
|
||||
+ mutex_unlock(&mt9v032->power_lock);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/* -----------------------------------------------------------------------------
|
||||
+ * V4L2 subdev internal operations
|
||||
+ */
|
||||
+
|
||||
+static int mt9v032_registered(struct v4l2_subdev *subdev)
|
||||
+{
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(subdev);
|
||||
+ struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
+ s32 data;
|
||||
+ int ret;
|
||||
+
|
||||
+ dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n",
|
||||
+ client->addr);
|
||||
+
|
||||
+ ret = mt9v032_power_on(mt9v032);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(&client->dev, "MT9V032 power up failed\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Read and check the sensor version */
|
||||
+ data = mt9v032_read(client, MT9V032_CHIP_VERSION);
|
||||
+ if (data != MT9V032_CHIP_ID_REV1 && data != MT9V032_CHIP_ID_REV3) {
|
||||
+ dev_err(&client->dev, "MT9V032 not detected, wrong version "
|
||||
+ "0x%04x\n", data);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ mt9v032_power_off(mt9v032);
|
||||
+
|
||||
+ dev_info(&client->dev, "MT9V032 detected at address 0x%02x\n",
|
||||
+ client->addr);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
|
||||
+{
|
||||
+ struct v4l2_mbus_framefmt *format;
|
||||
+ struct v4l2_rect *crop;
|
||||
+
|
||||
+ crop = v4l2_subdev_get_try_crop(fh, 0);
|
||||
+ crop->left = MT9V032_COLUMN_START_DEF;
|
||||
+ crop->top = MT9V032_ROW_START_DEF;
|
||||
+ crop->width = MT9V032_WINDOW_WIDTH_DEF;
|
||||
+ crop->height = MT9V032_WINDOW_HEIGHT_DEF;
|
||||
+
|
||||
+ format = v4l2_subdev_get_try_format(fh, 0);
|
||||
+ format->code = V4L2_MBUS_FMT_SGRBG10_1X10;
|
||||
+ format->width = MT9V032_WINDOW_WIDTH_DEF;
|
||||
+ format->height = MT9V032_WINDOW_HEIGHT_DEF;
|
||||
+ format->field = V4L2_FIELD_NONE;
|
||||
+ format->colorspace = V4L2_COLORSPACE_SRGB;
|
||||
+
|
||||
+ return mt9v032_set_power(subdev, 1);
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
|
||||
+{
|
||||
+ return mt9v032_set_power(subdev, 0);
|
||||
+}
|
||||
+
|
||||
+static struct v4l2_subdev_core_ops mt9v032_subdev_core_ops = {
|
||||
+ .s_power = mt9v032_set_power,
|
||||
+};
|
||||
+
|
||||
+static struct v4l2_subdev_video_ops mt9v032_subdev_video_ops = {
|
||||
+ .s_stream = mt9v032_s_stream,
|
||||
+};
|
||||
+
|
||||
+static struct v4l2_subdev_pad_ops mt9v032_subdev_pad_ops = {
|
||||
+ .enum_mbus_code = mt9v032_enum_mbus_code,
|
||||
+ .enum_frame_size = mt9v032_enum_frame_size,
|
||||
+ .get_fmt = mt9v032_get_format,
|
||||
+ .set_fmt = mt9v032_set_format,
|
||||
+ .get_crop = mt9v032_get_crop,
|
||||
+ .set_crop = mt9v032_set_crop,
|
||||
+};
|
||||
+
|
||||
+static struct v4l2_subdev_ops mt9v032_subdev_ops = {
|
||||
+ .core = &mt9v032_subdev_core_ops,
|
||||
+ .video = &mt9v032_subdev_video_ops,
|
||||
+ .pad = &mt9v032_subdev_pad_ops,
|
||||
+};
|
||||
+
|
||||
+static const struct v4l2_subdev_internal_ops mt9v032_subdev_internal_ops = {
|
||||
+ .registered = mt9v032_registered,
|
||||
+ .open = mt9v032_open,
|
||||
+ .close = mt9v032_close,
|
||||
+};
|
||||
+
|
||||
+/* -----------------------------------------------------------------------------
|
||||
+ * Driver initialization and probing
|
||||
+ */
|
||||
+
|
||||
+static int mt9v032_probe(struct i2c_client *client,
|
||||
+ const struct i2c_device_id *did)
|
||||
+{
|
||||
+ struct mt9v032 *mt9v032;
|
||||
+ unsigned int i;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!i2c_check_functionality(client->adapter,
|
||||
+ I2C_FUNC_SMBUS_WORD_DATA)) {
|
||||
+ dev_warn(&client->adapter->dev,
|
||||
+ "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ mt9v032 = kzalloc(sizeof(*mt9v032), GFP_KERNEL);
|
||||
+ if (!mt9v032)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ mutex_init(&mt9v032->power_lock);
|
||||
+ mt9v032->pdata = client->dev.platform_data;
|
||||
+
|
||||
+ v4l2_ctrl_handler_init(&mt9v032->ctrls, ARRAY_SIZE(mt9v032_ctrls) + 4);
|
||||
+
|
||||
+ v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
|
||||
+ V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
|
||||
+ v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
|
||||
+ V4L2_CID_GAIN, MT9V032_ANALOG_GAIN_MIN,
|
||||
+ MT9V032_ANALOG_GAIN_MAX, 1, MT9V032_ANALOG_GAIN_DEF);
|
||||
+ v4l2_ctrl_new_std_menu(&mt9v032->ctrls, &mt9v032_ctrl_ops,
|
||||
+ V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL, 0,
|
||||
+ V4L2_EXPOSURE_AUTO);
|
||||
+ v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
|
||||
+ V4L2_CID_EXPOSURE, MT9V032_TOTAL_SHUTTER_WIDTH_MIN,
|
||||
+ MT9V032_TOTAL_SHUTTER_WIDTH_MAX, 1,
|
||||
+ MT9V032_TOTAL_SHUTTER_WIDTH_DEF);
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(mt9v032_ctrls); ++i)
|
||||
+ v4l2_ctrl_new_custom(&mt9v032->ctrls, &mt9v032_ctrls[i], NULL);
|
||||
+
|
||||
+ mt9v032->subdev.ctrl_handler = &mt9v032->ctrls;
|
||||
+
|
||||
+ if (mt9v032->ctrls.error)
|
||||
+ printk(KERN_INFO "%s: control initialization error %d\n",
|
||||
+ __func__, mt9v032->ctrls.error);
|
||||
+
|
||||
+ mt9v032->crop.left = MT9V032_COLUMN_START_DEF;
|
||||
+ mt9v032->crop.top = MT9V032_ROW_START_DEF;
|
||||
+ mt9v032->crop.width = MT9V032_WINDOW_WIDTH_DEF;
|
||||
+ mt9v032->crop.height = MT9V032_WINDOW_HEIGHT_DEF;
|
||||
+
|
||||
+ mt9v032->format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
|
||||
+ mt9v032->format.width = MT9V032_WINDOW_WIDTH_DEF;
|
||||
+ mt9v032->format.height = MT9V032_WINDOW_HEIGHT_DEF;
|
||||
+ mt9v032->format.field = V4L2_FIELD_NONE;
|
||||
+ mt9v032->format.colorspace = V4L2_COLORSPACE_SRGB;
|
||||
+
|
||||
+ mt9v032->aec_agc = MT9V032_AEC_ENABLE | MT9V032_AGC_ENABLE;
|
||||
+
|
||||
+ v4l2_i2c_subdev_init(&mt9v032->subdev, client, &mt9v032_subdev_ops);
|
||||
+ mt9v032->subdev.internal_ops = &mt9v032_subdev_internal_ops;
|
||||
+ mt9v032->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
+
|
||||
+ mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE;
|
||||
+ ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0);
|
||||
+ if (ret < 0)
|
||||
+ kfree(mt9v032);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_remove(struct i2c_client *client)
|
||||
+{
|
||||
+ struct v4l2_subdev *subdev = i2c_get_clientdata(client);
|
||||
+ struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
+
|
||||
+ v4l2_device_unregister_subdev(subdev);
|
||||
+ media_entity_cleanup(&subdev->entity);
|
||||
+ kfree(mt9v032);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct i2c_device_id mt9v032_id[] = {
|
||||
+ { "mt9v032", 0 },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(i2c, mt9v032_id);
|
||||
+
|
||||
+static struct i2c_driver mt9v032_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "mt9v032",
|
||||
+ },
|
||||
+ .probe = mt9v032_probe,
|
||||
+ .remove = mt9v032_remove,
|
||||
+ .id_table = mt9v032_id,
|
||||
+};
|
||||
+
|
||||
+static int __init mt9v032_init(void)
|
||||
+{
|
||||
+ return i2c_add_driver(&mt9v032_driver);
|
||||
+}
|
||||
+
|
||||
+static void __exit mt9v032_exit(void)
|
||||
+{
|
||||
+ i2c_del_driver(&mt9v032_driver);
|
||||
+}
|
||||
+
|
||||
+module_init(mt9v032_init);
|
||||
+module_exit(mt9v032_exit);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Aptina MT9V032 Camera driver");
|
||||
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
|
||||
+MODULE_LICENSE("GPL");
|
||||
diff --git a/include/media/mt9v032.h b/include/media/mt9v032.h
|
||||
new file mode 100644
|
||||
index 0000000..5e27f9b
|
||||
--- /dev/null
|
||||
+++ b/include/media/mt9v032.h
|
||||
@@ -0,0 +1,12 @@
|
||||
+#ifndef _MEDIA_MT9V032_H
|
||||
+#define _MEDIA_MT9V032_H
|
||||
+
|
||||
+struct v4l2_subdev;
|
||||
+
|
||||
+struct mt9v032_platform_data {
|
||||
+ unsigned int clk_pol:1;
|
||||
+
|
||||
+ void (*set_clock)(struct v4l2_subdev *subdev, unsigned int rate);
|
||||
+};
|
||||
+
|
||||
+#endif
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
From f662a8a2b9794121568903f5cc969e50eb151892 Mon Sep 17 00:00:00 2001
|
||||
From: Javier Martin <javier.martin@vista-silicon.com>
|
||||
Date: Mon, 30 May 2011 10:37:17 +0200
|
||||
Subject: [PATCH 3/3] Add support for mt9p031 (LI-5M03 module) in Beagleboard xM.
|
||||
|
||||
Since isp clocks have not been exposed yet, this patch
|
||||
includes a temporal solution for testing mt9p031 driver
|
||||
in Beagleboard xM.
|
||||
|
||||
Signed-off-by: Javier Martin <javier.martin@vista-silicon.com>
|
||||
---
|
||||
arch/arm/mach-omap2/Makefile | 1 +
|
||||
arch/arm/mach-omap2/board-omap3beagle-camera.c | 95 ++++++++++++++++++++++++
|
||||
arch/arm/mach-omap2/board-omap3beagle.c | 5 +
|
||||
3 files changed, 101 insertions(+), 0 deletions(-)
|
||||
create mode 100644 arch/arm/mach-omap2/board-omap3beagle-camera.c
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
|
||||
index 512b152..05cd983 100644
|
||||
--- a/arch/arm/mach-omap2/Makefile
|
||||
+++ b/arch/arm/mach-omap2/Makefile
|
||||
@@ -179,6 +179,7 @@ obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o \
|
||||
hsmmc.o
|
||||
obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o
|
||||
obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o \
|
||||
+ board-omap3beagle-camera.o \
|
||||
hsmmc.o
|
||||
obj-$(CONFIG_MACH_DEVKIT8000) += board-devkit8000.o \
|
||||
hsmmc.o
|
||||
diff --git a/arch/arm/mach-omap2/board-omap3beagle-camera.c b/arch/arm/mach-omap2/board-omap3beagle-camera.c
|
||||
new file mode 100644
|
||||
index 0000000..2632557
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-omap2/board-omap3beagle-camera.c
|
||||
@@ -0,0 +1,95 @@
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/regulator/machine.h>
|
||||
+
|
||||
+#include <plat/i2c.h>
|
||||
+
|
||||
+#include <media/mt9p031.h>
|
||||
+#include <asm/mach-types.h>
|
||||
+#include "devices.h"
|
||||
+#include "../../../drivers/media/video/omap3isp/isp.h"
|
||||
+
|
||||
+#define MT9P031_RESET_GPIO 98
|
||||
+#define MT9P031_XCLK ISP_XCLK_A
|
||||
+
|
||||
+static struct regulator *reg_1v8, *reg_2v8;
|
||||
+
|
||||
+static int beagle_cam_set_xclk(struct v4l2_subdev *subdev, int hz)
|
||||
+{
|
||||
+ struct isp_device *isp = v4l2_dev_to_isp_device(subdev->v4l2_dev);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = isp->platform_cb.set_xclk(isp, hz, MT9P031_XCLK);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int beagle_cam_reset(struct v4l2_subdev *subdev, int active)
|
||||
+{
|
||||
+ /* Set RESET_BAR to !active */
|
||||
+ gpio_set_value(MT9P031_RESET_GPIO, !active);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct mt9p031_platform_data beagle_mt9p031_platform_data = {
|
||||
+ .set_xclk = beagle_cam_set_xclk,
|
||||
+ .reset = beagle_cam_reset,
|
||||
+ .vdd_io = MT9P031_VDD_IO_1V8,
|
||||
+ .version = MT9P031_COLOR_VERSION,
|
||||
+};
|
||||
+
|
||||
+static struct i2c_board_info mt9p031_camera_i2c_device = {
|
||||
+ I2C_BOARD_INFO("mt9p031", 0x48),
|
||||
+ .platform_data = &beagle_mt9p031_platform_data,
|
||||
+};
|
||||
+
|
||||
+static struct isp_subdev_i2c_board_info mt9p031_camera_subdevs[] = {
|
||||
+ {
|
||||
+ .board_info = &mt9p031_camera_i2c_device,
|
||||
+ .i2c_adapter_id = 2,
|
||||
+ },
|
||||
+ { NULL, 0, },
|
||||
+};
|
||||
+
|
||||
+static struct isp_v4l2_subdevs_group beagle_camera_subdevs[] = {
|
||||
+ {
|
||||
+ .subdevs = mt9p031_camera_subdevs,
|
||||
+ .interface = ISP_INTERFACE_PARALLEL,
|
||||
+ .bus = {
|
||||
+ .parallel = {
|
||||
+ .data_lane_shift = 0,
|
||||
+ .clk_pol = 1,
|
||||
+ .bridge = ISPCTRL_PAR_BRIDGE_DISABLE,
|
||||
+ }
|
||||
+ },
|
||||
+ },
|
||||
+ { },
|
||||
+};
|
||||
+
|
||||
+static struct isp_platform_data beagle_isp_platform_data = {
|
||||
+ .subdevs = beagle_camera_subdevs,
|
||||
+};
|
||||
+
|
||||
+static int __init beagle_camera_init(void)
|
||||
+{
|
||||
+ if (!machine_is_omap3_beagle() || !cpu_is_omap3630())
|
||||
+ return 0;
|
||||
+
|
||||
+ reg_1v8 = regulator_get(NULL, "cam_1v8");
|
||||
+ if (IS_ERR(reg_1v8))
|
||||
+ pr_err("%s: cannot get cam_1v8 regulator\n", __func__);
|
||||
+ else
|
||||
+ regulator_enable(reg_1v8);
|
||||
+
|
||||
+ reg_2v8 = regulator_get(NULL, "cam_2v8");
|
||||
+ if (IS_ERR(reg_2v8))
|
||||
+ pr_err("%s: cannot get cam_2v8 regulator\n", __func__);
|
||||
+ else
|
||||
+ regulator_enable(reg_2v8);
|
||||
+
|
||||
+ omap_register_i2c_bus(2, 100, NULL, 0);
|
||||
+ gpio_request(MT9P031_RESET_GPIO, "cam_rst");
|
||||
+ gpio_direction_output(MT9P031_RESET_GPIO, 0);
|
||||
+ omap3_init_camera(&beagle_isp_platform_data);
|
||||
+ return 0;
|
||||
+}
|
||||
+late_initcall(beagle_camera_init);
|
||||
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
index 221bfda..dd6e31f 100644
|
||||
--- a/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
@@ -25,12 +25,16 @@
|
||||
#include <linux/input.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
#include <linux/opp.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/mm.h>
|
||||
+#include <linux/videodev2.h>
|
||||
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/mmc/host.h>
|
||||
|
||||
+#include <linux/gpio.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
|
||||
@@ -48,6 +52,7 @@
|
||||
#include <plat/nand.h>
|
||||
#include <plat/usb.h>
|
||||
#include <plat/omap_device.h>
|
||||
+#include <plat/i2c.h>
|
||||
|
||||
#include "mux.h"
|
||||
#include "hsmmc.h"
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
From 46be90d202c36db19e27c2991cbff401c6c3ee81 Mon Sep 17 00:00:00 2001
|
||||
From: Keshava Munegowda <Keshava_mgowda@ti.com>
|
||||
Date: Mon, 16 May 2011 14:24:58 +0530
|
||||
Subject: [PATCH 01/13] mfd: Fix omap usbhs crash when rmmoding ehci or ohci
|
||||
|
||||
The disabling of clocks and freeing GPIO are changed
|
||||
to fix the occurrence of the crash of rmmod of ehci and ohci
|
||||
drivers. The GPIOs should be freed after the spin locks are
|
||||
unlocked.
|
||||
|
||||
Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
|
||||
Acked-by: Felipe Balbi <balbi@ti.com>
|
||||
Cc: stable@kernel.org
|
||||
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
|
||||
---
|
||||
drivers/mfd/omap-usb-host.c | 27 +++++++++++++++++++--------
|
||||
1 files changed, 19 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
|
||||
index 3ab9ffa..55c5d47 100644
|
||||
--- a/drivers/mfd/omap-usb-host.c
|
||||
+++ b/drivers/mfd/omap-usb-host.c
|
||||
@@ -994,22 +994,33 @@ static void usbhs_disable(struct device *dev)
|
||||
dev_dbg(dev, "operation timed out\n");
|
||||
}
|
||||
|
||||
- if (pdata->ehci_data->phy_reset) {
|
||||
- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
|
||||
- gpio_free(pdata->ehci_data->reset_gpio_port[0]);
|
||||
-
|
||||
- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
|
||||
- gpio_free(pdata->ehci_data->reset_gpio_port[1]);
|
||||
+ if (is_omap_usbhs_rev2(omap)) {
|
||||
+ if (is_ehci_tll_mode(pdata->port_mode[0]))
|
||||
+ clk_enable(omap->usbtll_p1_fck);
|
||||
+ if (is_ehci_tll_mode(pdata->port_mode[1]))
|
||||
+ clk_enable(omap->usbtll_p2_fck);
|
||||
+ clk_disable(omap->utmi_p2_fck);
|
||||
+ clk_disable(omap->utmi_p1_fck);
|
||||
}
|
||||
|
||||
- clk_disable(omap->utmi_p2_fck);
|
||||
- clk_disable(omap->utmi_p1_fck);
|
||||
clk_disable(omap->usbtll_ick);
|
||||
clk_disable(omap->usbtll_fck);
|
||||
clk_disable(omap->usbhost_fs_fck);
|
||||
clk_disable(omap->usbhost_hs_fck);
|
||||
clk_disable(omap->usbhost_ick);
|
||||
|
||||
+ /* The gpio_free migh sleep; so unlock the spinlock */
|
||||
+ spin_unlock_irqrestore(&omap->lock, flags);
|
||||
+
|
||||
+ if (pdata->ehci_data->phy_reset) {
|
||||
+ if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
|
||||
+ gpio_free(pdata->ehci_data->reset_gpio_port[0]);
|
||||
+
|
||||
+ if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
|
||||
+ gpio_free(pdata->ehci_data->reset_gpio_port[1]);
|
||||
+ }
|
||||
+ return;
|
||||
+
|
||||
end_disble:
|
||||
spin_unlock_irqrestore(&omap->lock, flags);
|
||||
}
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
From 89a903aca8fda3dcf1a6f9a424247e772afdd44e Mon Sep 17 00:00:00 2001
|
||||
From: Axel Lin <axel.lin@gmail.com>
|
||||
Date: Sat, 14 May 2011 14:15:36 +0800
|
||||
Subject: [PATCH 02/13] mfd: Fix omap_usbhs_alloc_children error handling
|
||||
|
||||
1. Return proper error if omap_usbhs_alloc_child fails
|
||||
2. In the case of goto err_ehci, we should call platform_device_unregister(ehci)
|
||||
instead of platform_device_put(ehci) because we have already added the
|
||||
platform device to device hierarchy.
|
||||
|
||||
Signed-off-by: Axel Lin <axel.lin@gmail.com>
|
||||
Signed-off-by: Axel Lin <axel.lin@gmail.com>
|
||||
Tested-by: Keshava Munegowda <keshava_mgowda@ti.com>
|
||||
Acked-by: Felipe Balbi <balbi@ti.com>
|
||||
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
|
||||
---
|
||||
drivers/mfd/omap-usb-host.c | 4 +++-
|
||||
1 files changed, 3 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
|
||||
index 55c5d47..1717144 100644
|
||||
--- a/drivers/mfd/omap-usb-host.c
|
||||
+++ b/drivers/mfd/omap-usb-host.c
|
||||
@@ -281,6 +281,7 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev)
|
||||
|
||||
if (!ehci) {
|
||||
dev_err(dev, "omap_usbhs_alloc_child failed\n");
|
||||
+ ret = -ENOMEM;
|
||||
goto err_end;
|
||||
}
|
||||
|
||||
@@ -304,13 +305,14 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev)
|
||||
sizeof(*ohci_data), dev);
|
||||
if (!ohci) {
|
||||
dev_err(dev, "omap_usbhs_alloc_child failed\n");
|
||||
+ ret = -ENOMEM;
|
||||
goto err_ehci;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_ehci:
|
||||
- platform_device_put(ehci);
|
||||
+ platform_device_unregister(ehci);
|
||||
|
||||
err_end:
|
||||
return ret;
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
From edc881f9c4897fab11542cd5c36a33b288f702be Mon Sep 17 00:00:00 2001
|
||||
From: Keshava Munegowda <Keshava_mgowda@ti.com>
|
||||
Date: Sun, 22 May 2011 22:51:26 +0200
|
||||
Subject: [PATCH 03/13] mfd: Add omap-usbhs runtime PM support
|
||||
|
||||
The usbhs core driver does not enable/disable the interface and
|
||||
functional clocks; These clocks are handled by hwmod and runtime pm,
|
||||
hence insted of the clock enable/disable, the runtime pm APIS are
|
||||
used. however,the port clocks and tll clocks are handled
|
||||
by the usbhs core.
|
||||
|
||||
Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
|
||||
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
|
||||
---
|
||||
drivers/mfd/omap-usb-host.c | 131 +++----------------------------------------
|
||||
1 files changed, 9 insertions(+), 122 deletions(-)
|
||||
|
||||
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
|
||||
index 1717144..8552195 100644
|
||||
--- a/drivers/mfd/omap-usb-host.c
|
||||
+++ b/drivers/mfd/omap-usb-host.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <plat/usb.h>
|
||||
+#include <linux/pm_runtime.h>
|
||||
|
||||
#define USBHS_DRIVER_NAME "usbhs-omap"
|
||||
#define OMAP_EHCI_DEVICE "ehci-omap"
|
||||
@@ -146,9 +147,6 @@
|
||||
|
||||
|
||||
struct usbhs_hcd_omap {
|
||||
- struct clk *usbhost_ick;
|
||||
- struct clk *usbhost_hs_fck;
|
||||
- struct clk *usbhost_fs_fck;
|
||||
struct clk *xclk60mhsp1_ck;
|
||||
struct clk *xclk60mhsp2_ck;
|
||||
struct clk *utmi_p1_fck;
|
||||
@@ -158,8 +156,6 @@ struct usbhs_hcd_omap {
|
||||
struct clk *usbhost_p2_fck;
|
||||
struct clk *usbtll_p2_fck;
|
||||
struct clk *init_60m_fclk;
|
||||
- struct clk *usbtll_fck;
|
||||
- struct clk *usbtll_ick;
|
||||
|
||||
void __iomem *uhh_base;
|
||||
void __iomem *tll_base;
|
||||
@@ -353,46 +349,13 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
|
||||
omap->platdata.ehci_data = pdata->ehci_data;
|
||||
omap->platdata.ohci_data = pdata->ohci_data;
|
||||
|
||||
- omap->usbhost_ick = clk_get(dev, "usbhost_ick");
|
||||
- if (IS_ERR(omap->usbhost_ick)) {
|
||||
- ret = PTR_ERR(omap->usbhost_ick);
|
||||
- dev_err(dev, "usbhost_ick failed error:%d\n", ret);
|
||||
- goto err_end;
|
||||
- }
|
||||
-
|
||||
- omap->usbhost_hs_fck = clk_get(dev, "hs_fck");
|
||||
- if (IS_ERR(omap->usbhost_hs_fck)) {
|
||||
- ret = PTR_ERR(omap->usbhost_hs_fck);
|
||||
- dev_err(dev, "usbhost_hs_fck failed error:%d\n", ret);
|
||||
- goto err_usbhost_ick;
|
||||
- }
|
||||
-
|
||||
- omap->usbhost_fs_fck = clk_get(dev, "fs_fck");
|
||||
- if (IS_ERR(omap->usbhost_fs_fck)) {
|
||||
- ret = PTR_ERR(omap->usbhost_fs_fck);
|
||||
- dev_err(dev, "usbhost_fs_fck failed error:%d\n", ret);
|
||||
- goto err_usbhost_hs_fck;
|
||||
- }
|
||||
-
|
||||
- omap->usbtll_fck = clk_get(dev, "usbtll_fck");
|
||||
- if (IS_ERR(omap->usbtll_fck)) {
|
||||
- ret = PTR_ERR(omap->usbtll_fck);
|
||||
- dev_err(dev, "usbtll_fck failed error:%d\n", ret);
|
||||
- goto err_usbhost_fs_fck;
|
||||
- }
|
||||
-
|
||||
- omap->usbtll_ick = clk_get(dev, "usbtll_ick");
|
||||
- if (IS_ERR(omap->usbtll_ick)) {
|
||||
- ret = PTR_ERR(omap->usbtll_ick);
|
||||
- dev_err(dev, "usbtll_ick failed error:%d\n", ret);
|
||||
- goto err_usbtll_fck;
|
||||
- }
|
||||
+ pm_runtime_enable(&pdev->dev);
|
||||
|
||||
omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
|
||||
if (IS_ERR(omap->utmi_p1_fck)) {
|
||||
ret = PTR_ERR(omap->utmi_p1_fck);
|
||||
dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret);
|
||||
- goto err_usbtll_ick;
|
||||
+ goto err_end;
|
||||
}
|
||||
|
||||
omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck");
|
||||
@@ -522,22 +485,8 @@ err_xclk60mhsp1_ck:
|
||||
err_utmi_p1_fck:
|
||||
clk_put(omap->utmi_p1_fck);
|
||||
|
||||
-err_usbtll_ick:
|
||||
- clk_put(omap->usbtll_ick);
|
||||
-
|
||||
-err_usbtll_fck:
|
||||
- clk_put(omap->usbtll_fck);
|
||||
-
|
||||
-err_usbhost_fs_fck:
|
||||
- clk_put(omap->usbhost_fs_fck);
|
||||
-
|
||||
-err_usbhost_hs_fck:
|
||||
- clk_put(omap->usbhost_hs_fck);
|
||||
-
|
||||
-err_usbhost_ick:
|
||||
- clk_put(omap->usbhost_ick);
|
||||
-
|
||||
err_end:
|
||||
+ pm_runtime_disable(&pdev->dev);
|
||||
kfree(omap);
|
||||
|
||||
end_probe:
|
||||
@@ -571,11 +520,7 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev)
|
||||
clk_put(omap->utmi_p2_fck);
|
||||
clk_put(omap->xclk60mhsp1_ck);
|
||||
clk_put(omap->utmi_p1_fck);
|
||||
- clk_put(omap->usbtll_ick);
|
||||
- clk_put(omap->usbtll_fck);
|
||||
- clk_put(omap->usbhost_fs_fck);
|
||||
- clk_put(omap->usbhost_hs_fck);
|
||||
- clk_put(omap->usbhost_ick);
|
||||
+ pm_runtime_disable(&pdev->dev);
|
||||
kfree(omap);
|
||||
|
||||
return 0;
|
||||
@@ -695,7 +640,6 @@ static int usbhs_enable(struct device *dev)
|
||||
struct usbhs_omap_platform_data *pdata = &omap->platdata;
|
||||
unsigned long flags = 0;
|
||||
int ret = 0;
|
||||
- unsigned long timeout;
|
||||
unsigned reg;
|
||||
|
||||
dev_dbg(dev, "starting TI HSUSB Controller\n");
|
||||
@@ -708,11 +652,7 @@ static int usbhs_enable(struct device *dev)
|
||||
if (omap->count > 0)
|
||||
goto end_count;
|
||||
|
||||
- clk_enable(omap->usbhost_ick);
|
||||
- clk_enable(omap->usbhost_hs_fck);
|
||||
- clk_enable(omap->usbhost_fs_fck);
|
||||
- clk_enable(omap->usbtll_fck);
|
||||
- clk_enable(omap->usbtll_ick);
|
||||
+ pm_runtime_get_sync(dev);
|
||||
|
||||
if (pdata->ehci_data->phy_reset) {
|
||||
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) {
|
||||
@@ -736,50 +676,6 @@ static int usbhs_enable(struct device *dev)
|
||||
omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
|
||||
dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);
|
||||
|
||||
- /* perform TLL soft reset, and wait until reset is complete */
|
||||
- usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
|
||||
- OMAP_USBTLL_SYSCONFIG_SOFTRESET);
|
||||
-
|
||||
- /* Wait for TLL reset to complete */
|
||||
- timeout = jiffies + msecs_to_jiffies(1000);
|
||||
- while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
|
||||
- & OMAP_USBTLL_SYSSTATUS_RESETDONE)) {
|
||||
- cpu_relax();
|
||||
-
|
||||
- if (time_after(jiffies, timeout)) {
|
||||
- dev_dbg(dev, "operation timed out\n");
|
||||
- ret = -EINVAL;
|
||||
- goto err_tll;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- dev_dbg(dev, "TLL RESET DONE\n");
|
||||
-
|
||||
- /* (1<<3) = no idle mode only for initial debugging */
|
||||
- usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
|
||||
- OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
|
||||
- OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
|
||||
- OMAP_USBTLL_SYSCONFIG_AUTOIDLE);
|
||||
-
|
||||
- /* Put UHH in NoIdle/NoStandby mode */
|
||||
- reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG);
|
||||
- if (is_omap_usbhs_rev1(omap)) {
|
||||
- reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
|
||||
- | OMAP_UHH_SYSCONFIG_SIDLEMODE
|
||||
- | OMAP_UHH_SYSCONFIG_CACTIVITY
|
||||
- | OMAP_UHH_SYSCONFIG_MIDLEMODE);
|
||||
- reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
|
||||
-
|
||||
-
|
||||
- } else if (is_omap_usbhs_rev2(omap)) {
|
||||
- reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR;
|
||||
- reg |= OMAP4_UHH_SYSCONFIG_NOIDLE;
|
||||
- reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR;
|
||||
- reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY;
|
||||
- }
|
||||
-
|
||||
- usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
|
||||
-
|
||||
reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
|
||||
/* setup ULPI bypass and burst configurations */
|
||||
reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
|
||||
@@ -919,6 +815,8 @@ end_count:
|
||||
return 0;
|
||||
|
||||
err_tll:
|
||||
+ pm_runtime_put_sync(dev);
|
||||
+ spin_unlock_irqrestore(&omap->lock, flags);
|
||||
if (pdata->ehci_data->phy_reset) {
|
||||
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
|
||||
gpio_free(pdata->ehci_data->reset_gpio_port[0]);
|
||||
@@ -926,13 +824,6 @@ err_tll:
|
||||
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
|
||||
gpio_free(pdata->ehci_data->reset_gpio_port[1]);
|
||||
}
|
||||
-
|
||||
- clk_disable(omap->usbtll_ick);
|
||||
- clk_disable(omap->usbtll_fck);
|
||||
- clk_disable(omap->usbhost_fs_fck);
|
||||
- clk_disable(omap->usbhost_hs_fck);
|
||||
- clk_disable(omap->usbhost_ick);
|
||||
- spin_unlock_irqrestore(&omap->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1005,11 +896,7 @@ static void usbhs_disable(struct device *dev)
|
||||
clk_disable(omap->utmi_p1_fck);
|
||||
}
|
||||
|
||||
- clk_disable(omap->usbtll_ick);
|
||||
- clk_disable(omap->usbtll_fck);
|
||||
- clk_disable(omap->usbhost_fs_fck);
|
||||
- clk_disable(omap->usbhost_hs_fck);
|
||||
- clk_disable(omap->usbhost_ick);
|
||||
+ pm_runtime_put_sync(dev);
|
||||
|
||||
/* The gpio_free migh sleep; so unlock the spinlock */
|
||||
spin_unlock_irqrestore(&omap->lock, flags);
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,406 @@
|
||||
From 339b167f6f76707a2d6ae3a7c0b921b8278564af Mon Sep 17 00:00:00 2001
|
||||
From: Keshava Munegowda <Keshava_mgowda@ti.com>
|
||||
Date: Wed, 1 Jun 2011 11:02:49 -0700
|
||||
Subject: [PATCH 04/13] arm: omap: usb: ehci and ohci hwmod structures for omap3 and omap4
|
||||
|
||||
Following 2 hwmod strcuture are added:
|
||||
UHH hwmod of usbhs with uhh base address and
|
||||
EHCI , OHCI irq and base addresses.
|
||||
TLL hwmod of usbhs with the TLL base address and irq.
|
||||
|
||||
Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 184 ++++++++++++++++++++++++++++
|
||||
arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 153 +++++++++++++++++++++++
|
||||
2 files changed, 337 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
|
||||
index 909a84d..fe9a176 100644
|
||||
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
|
||||
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
|
||||
@@ -84,6 +84,8 @@ static struct omap_hwmod omap3xxx_mcbsp4_hwmod;
|
||||
static struct omap_hwmod omap3xxx_mcbsp5_hwmod;
|
||||
static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod;
|
||||
static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod;
|
||||
+static struct omap_hwmod omap34xx_usb_host_hs_hwmod;
|
||||
+static struct omap_hwmod omap34xx_usb_tll_hs_hwmod;
|
||||
|
||||
/* L3 -> L4_CORE interface */
|
||||
static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = {
|
||||
@@ -3574,6 +3576,185 @@ static struct omap_hwmod omap3xxx_mmc3_hwmod = {
|
||||
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * 'usb_host_hs' class
|
||||
+ * high-speed multi-port usb host controller
|
||||
+ */
|
||||
+static struct omap_hwmod_ocp_if omap34xx_usb_host_hs__l3_main_2 = {
|
||||
+ .master = &omap34xx_usb_host_hs_hwmod,
|
||||
+ .slave = &omap3xxx_l3_main_hwmod,
|
||||
+ .clk = "core_l3_ick",
|
||||
+ .user = OCP_USER_MPU,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_class_sysconfig omap34xx_usb_host_hs_sysc = {
|
||||
+ .rev_offs = 0x0000,
|
||||
+ .sysc_offs = 0x0010,
|
||||
+ .syss_offs = 0x0014,
|
||||
+ .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE),
|
||||
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
|
||||
+ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
|
||||
+ .sysc_fields = &omap_hwmod_sysc_type1,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_class omap34xx_usb_host_hs_hwmod_class = {
|
||||
+ .name = "usbhs_uhh",
|
||||
+ .sysc = &omap34xx_usb_host_hs_sysc,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if *omap34xx_usb_host_hs_masters[] = {
|
||||
+ &omap34xx_usb_host_hs__l3_main_2,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_irq_info omap34xx_usb_host_hs_irqs[] = {
|
||||
+ { .name = "ohci-irq", .irq = 76 },
|
||||
+ { .name = "ehci-irq", .irq = 77 },
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_addr_space omap34xx_usb_host_hs_addrs[] = {
|
||||
+ {
|
||||
+ .name = "uhh",
|
||||
+ .pa_start = 0x48064000,
|
||||
+ .pa_end = 0x480643ff,
|
||||
+ .flags = ADDR_TYPE_RT
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "ohci",
|
||||
+ .pa_start = 0x48064400,
|
||||
+ .pa_end = 0x480647FF,
|
||||
+ .flags = ADDR_MAP_ON_INIT
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "ehci",
|
||||
+ .pa_start = 0x48064800,
|
||||
+ .pa_end = 0x48064CFF,
|
||||
+ .flags = ADDR_MAP_ON_INIT
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if omap34xx_l4_cfg__usb_host_hs = {
|
||||
+ .master = &omap3xxx_l4_core_hwmod,
|
||||
+ .slave = &omap34xx_usb_host_hs_hwmod,
|
||||
+ .clk = "l4_ick",
|
||||
+ .addr = omap34xx_usb_host_hs_addrs,
|
||||
+ .addr_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_addrs),
|
||||
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if omap34xx_f128m_cfg__usb_host_hs = {
|
||||
+ .clk = "usbhost_120m_fck",
|
||||
+ .user = OCP_USER_MPU,
|
||||
+ .flags = OCPIF_SWSUP_IDLE,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if omap34xx_f48m_cfg__usb_host_hs = {
|
||||
+ .clk = "usbhost_48m_fck",
|
||||
+ .user = OCP_USER_MPU,
|
||||
+ .flags = OCPIF_SWSUP_IDLE,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if *omap34xx_usb_host_hs_slaves[] = {
|
||||
+ &omap34xx_l4_cfg__usb_host_hs,
|
||||
+ &omap34xx_f128m_cfg__usb_host_hs,
|
||||
+ &omap34xx_f48m_cfg__usb_host_hs,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod omap34xx_usb_host_hs_hwmod = {
|
||||
+ .name = "usbhs_uhh",
|
||||
+ .class = &omap34xx_usb_host_hs_hwmod_class,
|
||||
+ .mpu_irqs = omap34xx_usb_host_hs_irqs,
|
||||
+ .mpu_irqs_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_irqs),
|
||||
+ .main_clk = "usbhost_ick",
|
||||
+ .prcm = {
|
||||
+ .omap2 = {
|
||||
+ .module_offs = OMAP3430ES2_USBHOST_MOD,
|
||||
+ .prcm_reg_id = 1,
|
||||
+ .module_bit = 0,
|
||||
+ .idlest_reg_id = 1,
|
||||
+ .idlest_idle_bit = 1,
|
||||
+ .idlest_stdby_bit = 0,
|
||||
+ },
|
||||
+ },
|
||||
+ .slaves = omap34xx_usb_host_hs_slaves,
|
||||
+ .slaves_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_slaves),
|
||||
+ .masters = omap34xx_usb_host_hs_masters,
|
||||
+ .masters_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_masters),
|
||||
+ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
|
||||
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * 'usb_tll_hs' class
|
||||
+ * usb_tll_hs module is the adapter on the usb_host_hs ports
|
||||
+ */
|
||||
+static struct omap_hwmod_class_sysconfig omap34xx_usb_tll_hs_sysc = {
|
||||
+ .rev_offs = 0x0000,
|
||||
+ .sysc_offs = 0x0010,
|
||||
+ .syss_offs = 0x0014,
|
||||
+ .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE),
|
||||
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
|
||||
+ .sysc_fields = &omap_hwmod_sysc_type1,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_class omap34xx_usb_tll_hs_hwmod_class = {
|
||||
+ .name = "usbhs_tll",
|
||||
+ .sysc = &omap34xx_usb_tll_hs_sysc,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_irq_info omap34xx_usb_tll_hs_irqs[] = {
|
||||
+ { .name = "tll-irq", .irq = 78 },
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_addr_space omap34xx_usb_tll_hs_addrs[] = {
|
||||
+ {
|
||||
+ .name = "tll",
|
||||
+ .pa_start = 0x48062000,
|
||||
+ .pa_end = 0x48062fff,
|
||||
+ .flags = ADDR_TYPE_RT
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if omap34xx_f_cfg__usb_tll_hs = {
|
||||
+ .clk = "usbtll_fck",
|
||||
+ .user = OCP_USER_MPU,
|
||||
+ .flags = OCPIF_SWSUP_IDLE,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if omap34xx_l4_cfg__usb_tll_hs = {
|
||||
+ .master = &omap3xxx_l4_core_hwmod,
|
||||
+ .slave = &omap34xx_usb_tll_hs_hwmod,
|
||||
+ .clk = "l4_ick",
|
||||
+ .addr = omap34xx_usb_tll_hs_addrs,
|
||||
+ .addr_cnt = ARRAY_SIZE(omap34xx_usb_tll_hs_addrs),
|
||||
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if *omap34xx_usb_tll_hs_slaves[] = {
|
||||
+ &omap34xx_l4_cfg__usb_tll_hs,
|
||||
+ &omap34xx_f_cfg__usb_tll_hs,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod omap34xx_usb_tll_hs_hwmod = {
|
||||
+ .name = "usbhs_tll",
|
||||
+ .class = &omap34xx_usb_tll_hs_hwmod_class,
|
||||
+ .mpu_irqs = omap34xx_usb_tll_hs_irqs,
|
||||
+ .mpu_irqs_cnt = ARRAY_SIZE(omap34xx_usb_tll_hs_irqs),
|
||||
+ .main_clk = "usbtll_ick",
|
||||
+ .prcm = {
|
||||
+ .omap2 = {
|
||||
+ .module_offs = CORE_MOD,
|
||||
+ .prcm_reg_id = 3,
|
||||
+ .module_bit = 2,
|
||||
+ .idlest_reg_id = 3,
|
||||
+ .idlest_idle_bit = 2,
|
||||
+ },
|
||||
+ },
|
||||
+ .slaves = omap34xx_usb_tll_hs_slaves,
|
||||
+ .slaves_cnt = ARRAY_SIZE(omap34xx_usb_tll_hs_slaves),
|
||||
+ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
|
||||
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
|
||||
+};
|
||||
+
|
||||
static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
|
||||
&omap3xxx_l3_main_hwmod,
|
||||
&omap3xxx_l4_core_hwmod,
|
||||
@@ -3656,6 +3837,9 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
|
||||
/* usbotg for am35x */
|
||||
&am35xx_usbhsotg_hwmod,
|
||||
|
||||
+ &omap34xx_usb_host_hs_hwmod,
|
||||
+ &omap34xx_usb_tll_hs_hwmod,
|
||||
+
|
||||
NULL,
|
||||
};
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
|
||||
index abc548a..d7112b0 100644
|
||||
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
|
||||
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
|
||||
@@ -66,6 +66,8 @@ static struct omap_hwmod omap44xx_mmc2_hwmod;
|
||||
static struct omap_hwmod omap44xx_mpu_hwmod;
|
||||
static struct omap_hwmod omap44xx_mpu_private_hwmod;
|
||||
static struct omap_hwmod omap44xx_usb_otg_hs_hwmod;
|
||||
+static struct omap_hwmod omap44xx_usb_host_hs_hwmod;
|
||||
+static struct omap_hwmod omap44xx_usb_tll_hs_hwmod;
|
||||
|
||||
/*
|
||||
* Interconnects omap_hwmod structures
|
||||
@@ -5027,6 +5029,155 @@ static struct omap_hwmod omap44xx_wd_timer3_hwmod = {
|
||||
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * 'usb_host_hs' class
|
||||
+ * high-speed multi-port usb host controller
|
||||
+ */
|
||||
+static struct omap_hwmod_ocp_if omap44xx_usb_host_hs__l3_main_2 = {
|
||||
+ .master = &omap44xx_usb_host_hs_hwmod,
|
||||
+ .slave = &omap44xx_l3_main_2_hwmod,
|
||||
+ .clk = "l3_div_ck",
|
||||
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_class_sysconfig omap44xx_usb_host_hs_sysc = {
|
||||
+ .rev_offs = 0x0000,
|
||||
+ .sysc_offs = 0x0010,
|
||||
+ .syss_offs = 0x0014,
|
||||
+ .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE),
|
||||
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
|
||||
+ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
|
||||
+ .sysc_fields = &omap_hwmod_sysc_type2,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_class omap44xx_usb_host_hs_hwmod_class = {
|
||||
+ .name = "usbhs_uhh",
|
||||
+ .sysc = &omap44xx_usb_host_hs_sysc,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if *omap44xx_usb_host_hs_masters[] = {
|
||||
+ &omap44xx_usb_host_hs__l3_main_2,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_irq_info omap44xx_usb_host_hs_irqs[] = {
|
||||
+ { .name = "ohci-irq", .irq = 76 + OMAP44XX_IRQ_GIC_START },
|
||||
+ { .name = "ehci-irq", .irq = 77 + OMAP44XX_IRQ_GIC_START },
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_addr_space omap44xx_usb_host_hs_addrs[] = {
|
||||
+ {
|
||||
+ .name = "uhh",
|
||||
+ .pa_start = 0x4a064000,
|
||||
+ .pa_end = 0x4a0647ff,
|
||||
+ .flags = ADDR_TYPE_RT
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "ohci",
|
||||
+ .pa_start = 0x4A064800,
|
||||
+ .pa_end = 0x4A064BFF,
|
||||
+ .flags = ADDR_MAP_ON_INIT
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "ehci",
|
||||
+ .pa_start = 0x4A064C00,
|
||||
+ .pa_end = 0x4A064FFF,
|
||||
+ .flags = ADDR_MAP_ON_INIT
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_host_hs = {
|
||||
+ .master = &omap44xx_l4_cfg_hwmod,
|
||||
+ .slave = &omap44xx_usb_host_hs_hwmod,
|
||||
+ .clk = "l4_div_ck",
|
||||
+ .addr = omap44xx_usb_host_hs_addrs,
|
||||
+ .addr_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_addrs),
|
||||
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if *omap44xx_usb_host_hs_slaves[] = {
|
||||
+ &omap44xx_l4_cfg__usb_host_hs,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod omap44xx_usb_host_hs_hwmod = {
|
||||
+ .name = "usbhs_uhh",
|
||||
+ .class = &omap44xx_usb_host_hs_hwmod_class,
|
||||
+ .mpu_irqs = omap44xx_usb_host_hs_irqs,
|
||||
+ .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_irqs),
|
||||
+ .main_clk = "usb_host_hs_fck",
|
||||
+ .prcm = {
|
||||
+ .omap4 = {
|
||||
+ .clkctrl_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
|
||||
+ },
|
||||
+ },
|
||||
+ .slaves = omap44xx_usb_host_hs_slaves,
|
||||
+ .slaves_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_slaves),
|
||||
+ .masters = omap44xx_usb_host_hs_masters,
|
||||
+ .masters_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_masters),
|
||||
+ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
|
||||
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * 'usb_tll_hs' class
|
||||
+ * usb_tll_hs module is the adapter on the usb_host_hs ports
|
||||
+ */
|
||||
+static struct omap_hwmod_class_sysconfig omap44xx_usb_tll_hs_sysc = {
|
||||
+ .rev_offs = 0x0000,
|
||||
+ .sysc_offs = 0x0010,
|
||||
+ .syss_offs = 0x0014,
|
||||
+ .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE),
|
||||
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
|
||||
+ .sysc_fields = &omap_hwmod_sysc_type1,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_class omap44xx_usb_tll_hs_hwmod_class = {
|
||||
+ .name = "usbhs_tll",
|
||||
+ .sysc = &omap44xx_usb_tll_hs_sysc,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_irq_info omap44xx_usb_tll_hs_irqs[] = {
|
||||
+ { .name = "tll-irq", .irq = 78 + OMAP44XX_IRQ_GIC_START },
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_addr_space omap44xx_usb_tll_hs_addrs[] = {
|
||||
+ {
|
||||
+ .name = "tll",
|
||||
+ .pa_start = 0x4a062000,
|
||||
+ .pa_end = 0x4a063fff,
|
||||
+ .flags = ADDR_TYPE_RT
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_tll_hs = {
|
||||
+ .master = &omap44xx_l4_cfg_hwmod,
|
||||
+ .slave = &omap44xx_usb_tll_hs_hwmod,
|
||||
+ .clk = "l4_div_ck",
|
||||
+ .addr = omap44xx_usb_tll_hs_addrs,
|
||||
+ .addr_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_addrs),
|
||||
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if *omap44xx_usb_tll_hs_slaves[] = {
|
||||
+ &omap44xx_l4_cfg__usb_tll_hs,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod omap44xx_usb_tll_hs_hwmod = {
|
||||
+ .name = "usbhs_tll",
|
||||
+ .class = &omap44xx_usb_tll_hs_hwmod_class,
|
||||
+ .mpu_irqs = omap44xx_usb_tll_hs_irqs,
|
||||
+ .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_irqs),
|
||||
+ .main_clk = "usb_tll_hs_ick",
|
||||
+ .prcm = {
|
||||
+ .omap4 = {
|
||||
+ .clkctrl_reg = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
|
||||
+ },
|
||||
+ },
|
||||
+ .slaves = omap44xx_usb_tll_hs_slaves,
|
||||
+ .slaves_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_slaves),
|
||||
+ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
|
||||
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
|
||||
+};
|
||||
+
|
||||
static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
|
||||
|
||||
/* dmm class */
|
||||
@@ -5173,6 +5324,8 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
|
||||
&omap44xx_wd_timer2_hwmod,
|
||||
&omap44xx_wd_timer3_hwmod,
|
||||
|
||||
+ &omap44xx_usb_host_hs_hwmod,
|
||||
+ &omap44xx_usb_tll_hs_hwmod,
|
||||
NULL,
|
||||
};
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
From 70f5e1a0e6639710503a9ffb9008ddcd2bb3f06e Mon Sep 17 00:00:00 2001
|
||||
From: Keshava Munegowda <Keshava_mgowda@ti.com>
|
||||
Date: Wed, 1 Jun 2011 11:02:54 -0700
|
||||
Subject: [PATCH 05/13] arm: omap: usb: register hwmods of usbhs
|
||||
|
||||
The hwmod structure of uhh and tll are retrived
|
||||
and registered with omap device
|
||||
|
||||
Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/usb-host.c | 99 ++++++++++++++--------------------------
|
||||
1 files changed, 35 insertions(+), 64 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c
|
||||
index 89ae298..9d762c4 100644
|
||||
--- a/arch/arm/mach-omap2/usb-host.c
|
||||
+++ b/arch/arm/mach-omap2/usb-host.c
|
||||
@@ -28,51 +28,28 @@
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/irqs.h>
|
||||
#include <plat/usb.h>
|
||||
+#include <plat/omap_device.h>
|
||||
|
||||
#include "mux.h"
|
||||
|
||||
#ifdef CONFIG_MFD_OMAP_USB_HOST
|
||||
|
||||
-#define OMAP_USBHS_DEVICE "usbhs-omap"
|
||||
-
|
||||
-static struct resource usbhs_resources[] = {
|
||||
- {
|
||||
- .name = "uhh",
|
||||
- .flags = IORESOURCE_MEM,
|
||||
- },
|
||||
- {
|
||||
- .name = "tll",
|
||||
- .flags = IORESOURCE_MEM,
|
||||
- },
|
||||
- {
|
||||
- .name = "ehci",
|
||||
- .flags = IORESOURCE_MEM,
|
||||
- },
|
||||
- {
|
||||
- .name = "ehci-irq",
|
||||
- .flags = IORESOURCE_IRQ,
|
||||
- },
|
||||
- {
|
||||
- .name = "ohci",
|
||||
- .flags = IORESOURCE_MEM,
|
||||
- },
|
||||
- {
|
||||
- .name = "ohci-irq",
|
||||
- .flags = IORESOURCE_IRQ,
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-static struct platform_device usbhs_device = {
|
||||
- .name = OMAP_USBHS_DEVICE,
|
||||
- .id = 0,
|
||||
- .num_resources = ARRAY_SIZE(usbhs_resources),
|
||||
- .resource = usbhs_resources,
|
||||
-};
|
||||
+#define OMAP_USBHS_DEVICE "usbhs_omap"
|
||||
+#define USBHS_UHH_HWMODNAME "usbhs_uhh"
|
||||
+#define USBHS_TLL_HWMODNAME "usbhs_tll"
|
||||
|
||||
static struct usbhs_omap_platform_data usbhs_data;
|
||||
static struct ehci_hcd_omap_platform_data ehci_data;
|
||||
static struct ohci_hcd_omap_platform_data ohci_data;
|
||||
|
||||
+static struct omap_device_pm_latency omap_uhhtll_latency[] = {
|
||||
+ {
|
||||
+ .deactivate_func = omap_device_idle_hwmods,
|
||||
+ .activate_func = omap_device_enable_hwmods,
|
||||
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
/* MUX settings for EHCI pins */
|
||||
/*
|
||||
* setup_ehci_io_mux - initialize IO pad mux for USBHOST
|
||||
@@ -508,7 +485,10 @@ static void setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
|
||||
|
||||
void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
|
||||
{
|
||||
- int i;
|
||||
+ struct omap_hwmod *oh[2];
|
||||
+ struct omap_device *od;
|
||||
+ int bus_id = -1;
|
||||
+ int i;
|
||||
|
||||
for (i = 0; i < OMAP3_HS_USB_PORTS; i++) {
|
||||
usbhs_data.port_mode[i] = pdata->port_mode[i];
|
||||
@@ -523,44 +503,35 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
|
||||
usbhs_data.ohci_data = &ohci_data;
|
||||
|
||||
if (cpu_is_omap34xx()) {
|
||||
- usbhs_resources[0].start = OMAP34XX_UHH_CONFIG_BASE;
|
||||
- usbhs_resources[0].end = OMAP34XX_UHH_CONFIG_BASE + SZ_1K - 1;
|
||||
- usbhs_resources[1].start = OMAP34XX_USBTLL_BASE;
|
||||
- usbhs_resources[1].end = OMAP34XX_USBTLL_BASE + SZ_4K - 1;
|
||||
- usbhs_resources[2].start = OMAP34XX_EHCI_BASE;
|
||||
- usbhs_resources[2].end = OMAP34XX_EHCI_BASE + SZ_1K - 1;
|
||||
- usbhs_resources[3].start = INT_34XX_EHCI_IRQ;
|
||||
- usbhs_resources[4].start = OMAP34XX_OHCI_BASE;
|
||||
- usbhs_resources[4].end = OMAP34XX_OHCI_BASE + SZ_1K - 1;
|
||||
- usbhs_resources[5].start = INT_34XX_OHCI_IRQ;
|
||||
setup_ehci_io_mux(pdata->port_mode);
|
||||
setup_ohci_io_mux(pdata->port_mode);
|
||||
} else if (cpu_is_omap44xx()) {
|
||||
- usbhs_resources[0].start = OMAP44XX_UHH_CONFIG_BASE;
|
||||
- usbhs_resources[0].end = OMAP44XX_UHH_CONFIG_BASE + SZ_1K - 1;
|
||||
- usbhs_resources[1].start = OMAP44XX_USBTLL_BASE;
|
||||
- usbhs_resources[1].end = OMAP44XX_USBTLL_BASE + SZ_4K - 1;
|
||||
- usbhs_resources[2].start = OMAP44XX_HSUSB_EHCI_BASE;
|
||||
- usbhs_resources[2].end = OMAP44XX_HSUSB_EHCI_BASE + SZ_1K - 1;
|
||||
- usbhs_resources[3].start = OMAP44XX_IRQ_EHCI;
|
||||
- usbhs_resources[4].start = OMAP44XX_HSUSB_OHCI_BASE;
|
||||
- usbhs_resources[4].end = OMAP44XX_HSUSB_OHCI_BASE + SZ_1K - 1;
|
||||
- usbhs_resources[5].start = OMAP44XX_IRQ_OHCI;
|
||||
setup_4430ehci_io_mux(pdata->port_mode);
|
||||
setup_4430ohci_io_mux(pdata->port_mode);
|
||||
}
|
||||
|
||||
- if (platform_device_add_data(&usbhs_device,
|
||||
- &usbhs_data, sizeof(usbhs_data)) < 0) {
|
||||
- printk(KERN_ERR "USBHS platform_device_add_data failed\n");
|
||||
- goto init_end;
|
||||
+ oh[0] = omap_hwmod_lookup(USBHS_UHH_HWMODNAME);
|
||||
+ if (!oh[0]) {
|
||||
+ pr_err("Could not look up %s\n", USBHS_UHH_HWMODNAME);
|
||||
+ return;
|
||||
}
|
||||
|
||||
- if (platform_device_register(&usbhs_device) < 0)
|
||||
- printk(KERN_ERR "USBHS platform_device_register failed\n");
|
||||
+ oh[1] = omap_hwmod_lookup(USBHS_TLL_HWMODNAME);
|
||||
+ if (!oh[1]) {
|
||||
+ pr_err("Could not look up %s\n", USBHS_TLL_HWMODNAME);
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
-init_end:
|
||||
- return;
|
||||
+ od = omap_device_build_ss(OMAP_USBHS_DEVICE, bus_id, oh, 2,
|
||||
+ (void *)&usbhs_data, sizeof(usbhs_data),
|
||||
+ omap_uhhtll_latency,
|
||||
+ ARRAY_SIZE(omap_uhhtll_latency), false);
|
||||
+
|
||||
+ if (IS_ERR(od)) {
|
||||
+ pr_err("Could not build hwmod devices %s, %s\n",
|
||||
+ USBHS_UHH_HWMODNAME, USBHS_TLL_HWMODNAME);
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
|
||||
#else
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
From 64bc651bb56435e4cd86d2ebfa4f301abdbac6e5 Mon Sep 17 00:00:00 2001
|
||||
From: Keshava Munegowda <Keshava_mgowda@ti.com>
|
||||
Date: Wed, 1 Jun 2011 11:02:58 -0700
|
||||
Subject: [PATCH 06/13] arm: omap: usb: device name change for the clk names of usbhs
|
||||
|
||||
device name usbhs clocks are changed from
|
||||
usbhs-omap.0 to usbhs_omap; this is because
|
||||
in the hwmod registration the device name is set
|
||||
as usbhs_omap
|
||||
|
||||
Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/clock3xxx_data.c | 28 ++++++++++++++--------------
|
||||
arch/arm/mach-omap2/clock44xx_data.c | 10 +++++-----
|
||||
drivers/mfd/omap-usb-host.c | 2 +-
|
||||
3 files changed, 20 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
|
||||
index 75b119b..fabe482 100644
|
||||
--- a/arch/arm/mach-omap2/clock3xxx_data.c
|
||||
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
|
||||
@@ -3285,7 +3285,7 @@ static struct omap_clk omap3xxx_clks[] = {
|
||||
CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
CLK(NULL, "ts_fck", &ts_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
CLK(NULL, "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
- CLK("usbhs-omap.0", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
+ CLK("usbhs_omap", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
CLK("omap-mcbsp.1", "prcm_fck", &core_96m_fck, CK_3XXX),
|
||||
CLK("omap-mcbsp.5", "prcm_fck", &core_96m_fck, CK_3XXX),
|
||||
CLK(NULL, "core_96m_fck", &core_96m_fck, CK_3XXX),
|
||||
@@ -3321,7 +3321,7 @@ static struct omap_clk omap3xxx_clks[] = {
|
||||
CLK(NULL, "pka_ick", &pka_ick, CK_34XX | CK_36XX),
|
||||
CLK(NULL, "core_l4_ick", &core_l4_ick, CK_3XXX),
|
||||
CLK(NULL, "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
- CLK("usbhs-omap.0", "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
+ CLK("usbhs_omap", "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
CLK("omap_hsmmc.2", "ick", &mmchs3_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
CLK(NULL, "icr_ick", &icr_ick, CK_34XX | CK_36XX),
|
||||
CLK("omap-aes", "ick", &aes2_ick, CK_34XX | CK_36XX),
|
||||
@@ -3367,20 +3367,20 @@ static struct omap_clk omap3xxx_clks[] = {
|
||||
CLK(NULL, "cam_ick", &cam_ick, CK_34XX | CK_36XX),
|
||||
CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_34XX | CK_36XX),
|
||||
CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
- CLK("usbhs-omap.0", "hs_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
+ CLK("usbhs_omap", "hs_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
- CLK("usbhs-omap.0", "fs_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
+ CLK("usbhs_omap", "fs_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
- CLK("usbhs-omap.0", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
- CLK("usbhs-omap.0", "utmi_p1_gfclk", &dummy_ck, CK_3XXX),
|
||||
- CLK("usbhs-omap.0", "utmi_p2_gfclk", &dummy_ck, CK_3XXX),
|
||||
- CLK("usbhs-omap.0", "xclk60mhsp1_ck", &dummy_ck, CK_3XXX),
|
||||
- CLK("usbhs-omap.0", "xclk60mhsp2_ck", &dummy_ck, CK_3XXX),
|
||||
- CLK("usbhs-omap.0", "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX),
|
||||
- CLK("usbhs-omap.0", "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX),
|
||||
- CLK("usbhs-omap.0", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX),
|
||||
- CLK("usbhs-omap.0", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX),
|
||||
- CLK("usbhs-omap.0", "init_60m_fclk", &dummy_ck, CK_3XXX),
|
||||
+ CLK("usbhs_omap", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
+ CLK("usbhs_omap", "utmi_p1_gfclk", &dummy_ck, CK_3XXX),
|
||||
+ CLK("usbhs_omap", "utmi_p2_gfclk", &dummy_ck, CK_3XXX),
|
||||
+ CLK("usbhs_omap", "xclk60mhsp1_ck", &dummy_ck, CK_3XXX),
|
||||
+ CLK("usbhs_omap", "xclk60mhsp2_ck", &dummy_ck, CK_3XXX),
|
||||
+ CLK("usbhs_omap", "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX),
|
||||
+ CLK("usbhs_omap", "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX),
|
||||
+ CLK("usbhs_omap", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX),
|
||||
+ CLK("usbhs_omap", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX),
|
||||
+ CLK("usbhs_omap", "init_60m_fclk", &dummy_ck, CK_3XXX),
|
||||
CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2PLUS | CK_36XX),
|
||||
CLK(NULL, "gpt1_fck", &gpt1_fck, CK_3XXX),
|
||||
CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_3XXX),
|
||||
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
|
||||
index 8c96567..34e91eb 100644
|
||||
--- a/arch/arm/mach-omap2/clock44xx_data.c
|
||||
+++ b/arch/arm/mach-omap2/clock44xx_data.c
|
||||
@@ -3205,7 +3205,7 @@ static struct omap_clk omap44xx_clks[] = {
|
||||
CLK(NULL, "uart3_fck", &uart3_fck, CK_443X),
|
||||
CLK(NULL, "uart4_fck", &uart4_fck, CK_443X),
|
||||
CLK(NULL, "usb_host_fs_fck", &usb_host_fs_fck, CK_443X),
|
||||
- CLK("usbhs-omap.0", "fs_fck", &usb_host_fs_fck, CK_443X),
|
||||
+ CLK("usbhs_omap", "fs_fck", &usb_host_fs_fck, CK_443X),
|
||||
CLK(NULL, "utmi_p1_gfclk", &utmi_p1_gfclk, CK_443X),
|
||||
CLK(NULL, "usb_host_hs_utmi_p1_clk", &usb_host_hs_utmi_p1_clk, CK_443X),
|
||||
CLK(NULL, "utmi_p2_gfclk", &utmi_p2_gfclk, CK_443X),
|
||||
@@ -3217,8 +3217,8 @@ static struct omap_clk omap44xx_clks[] = {
|
||||
CLK(NULL, "usb_host_hs_hsic480m_p2_clk", &usb_host_hs_hsic480m_p2_clk, CK_443X),
|
||||
CLK(NULL, "usb_host_hs_func48mclk", &usb_host_hs_func48mclk, CK_443X),
|
||||
CLK(NULL, "usb_host_hs_fck", &usb_host_hs_fck, CK_443X),
|
||||
- CLK("usbhs-omap.0", "hs_fck", &usb_host_hs_fck, CK_443X),
|
||||
- CLK("usbhs-omap.0", "usbhost_ick", &dummy_ck, CK_443X),
|
||||
+ CLK("usbhs_omap", "hs_fck", &usb_host_hs_fck, CK_443X),
|
||||
+ CLK("usbhs_omap", "usbhost_ick", &dummy_ck, CK_443X),
|
||||
CLK(NULL, "otg_60m_gfclk", &otg_60m_gfclk, CK_443X),
|
||||
CLK(NULL, "usb_otg_hs_xclk", &usb_otg_hs_xclk, CK_443X),
|
||||
CLK("musb-omap2430", "ick", &usb_otg_hs_ick, CK_443X),
|
||||
@@ -3227,8 +3227,8 @@ static struct omap_clk omap44xx_clks[] = {
|
||||
CLK(NULL, "usb_tll_hs_usb_ch0_clk", &usb_tll_hs_usb_ch0_clk, CK_443X),
|
||||
CLK(NULL, "usb_tll_hs_usb_ch1_clk", &usb_tll_hs_usb_ch1_clk, CK_443X),
|
||||
CLK(NULL, "usb_tll_hs_ick", &usb_tll_hs_ick, CK_443X),
|
||||
- CLK("usbhs-omap.0", "usbtll_ick", &usb_tll_hs_ick, CK_443X),
|
||||
- CLK("usbhs-omap.0", "usbtll_fck", &dummy_ck, CK_443X),
|
||||
+ CLK("usbhs_omap", "usbtll_ick", &usb_tll_hs_ick, CK_443X),
|
||||
+ CLK("usbhs_omap", "usbtll_fck", &dummy_ck, CK_443X),
|
||||
CLK(NULL, "usim_ck", &usim_ck, CK_443X),
|
||||
CLK(NULL, "usim_fclk", &usim_fclk, CK_443X),
|
||||
CLK(NULL, "usim_fck", &usim_fck, CK_443X),
|
||||
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
|
||||
index 8552195..43de12a 100644
|
||||
--- a/drivers/mfd/omap-usb-host.c
|
||||
+++ b/drivers/mfd/omap-usb-host.c
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <plat/usb.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
-#define USBHS_DRIVER_NAME "usbhs-omap"
|
||||
+#define USBHS_DRIVER_NAME "usbhs_omap"
|
||||
#define OMAP_EHCI_DEVICE "ehci-omap"
|
||||
#define OMAP_OHCI_DEVICE "ohci-omap3"
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
From bf583f2924fd9b2f0356cbd0bbfd58c48d98ef15 Mon Sep 17 00:00:00 2001
|
||||
From: Keshava Munegowda <Keshava_mgowda@ti.com>
|
||||
Date: Wed, 1 Jun 2011 11:03:03 -0700
|
||||
Subject: [PATCH 07/13] mfd: global Suspend and resume support of ehci and ohci
|
||||
|
||||
The global suspend and resume functions for usbhs core driver
|
||||
are implemented.These routine are called when the global suspend
|
||||
and resume occurs. Before calling these functions, the
|
||||
bus suspend and resume of ehci and ohci drivers are called
|
||||
from runtime pm.
|
||||
|
||||
Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
|
||||
---
|
||||
drivers/mfd/omap-usb-host.c | 103 +++++++++++++++++++++++++++++++++++++++++++
|
||||
1 files changed, 103 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
|
||||
index 43de12a..32d19e2 100644
|
||||
--- a/drivers/mfd/omap-usb-host.c
|
||||
+++ b/drivers/mfd/omap-usb-host.c
|
||||
@@ -146,6 +146,10 @@
|
||||
#define is_ehci_hsic_mode(x) (x == OMAP_EHCI_PORT_MODE_HSIC)
|
||||
|
||||
|
||||
+/* USBHS state bits */
|
||||
+#define OMAP_USBHS_INIT 0
|
||||
+#define OMAP_USBHS_SUSPEND 4
|
||||
+
|
||||
struct usbhs_hcd_omap {
|
||||
struct clk *xclk60mhsp1_ck;
|
||||
struct clk *xclk60mhsp2_ck;
|
||||
@@ -165,6 +169,7 @@ struct usbhs_hcd_omap {
|
||||
u32 usbhs_rev;
|
||||
spinlock_t lock;
|
||||
int count;
|
||||
+ unsigned long state;
|
||||
};
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
@@ -809,6 +814,8 @@ static int usbhs_enable(struct device *dev)
|
||||
(pdata->ehci_data->reset_gpio_port[1], 1);
|
||||
}
|
||||
|
||||
+ set_bit(OMAP_USBHS_INIT, &omap->state);
|
||||
+
|
||||
end_count:
|
||||
omap->count++;
|
||||
spin_unlock_irqrestore(&omap->lock, flags);
|
||||
@@ -897,6 +904,7 @@ static void usbhs_disable(struct device *dev)
|
||||
}
|
||||
|
||||
pm_runtime_put_sync(dev);
|
||||
+ clear_bit(OMAP_USBHS_INIT, &omap->state);
|
||||
|
||||
/* The gpio_free migh sleep; so unlock the spinlock */
|
||||
spin_unlock_irqrestore(&omap->lock, flags);
|
||||
@@ -926,10 +934,105 @@ void omap_usbhs_disable(struct device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_usbhs_disable);
|
||||
|
||||
+#ifdef CONFIG_PM
|
||||
+
|
||||
+static int usbhs_resume(struct device *dev)
|
||||
+{
|
||||
+ struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
|
||||
+ struct usbhs_omap_platform_data *pdata = &omap->platdata;
|
||||
+ unsigned long flags = 0;
|
||||
+
|
||||
+ dev_dbg(dev, "Resuming TI HSUSB Controller\n");
|
||||
+
|
||||
+ if (!pdata) {
|
||||
+ dev_dbg(dev, "missing platform_data\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ spin_lock_irqsave(&omap->lock, flags);
|
||||
+
|
||||
+ if (!test_bit(OMAP_USBHS_INIT, &omap->state) ||
|
||||
+ !test_bit(OMAP_USBHS_SUSPEND, &omap->state))
|
||||
+ goto end_resume;
|
||||
+
|
||||
+ pm_runtime_get_sync(dev);
|
||||
+
|
||||
+ if (is_omap_usbhs_rev2(omap)) {
|
||||
+ if (is_ehci_tll_mode(pdata->port_mode[0])) {
|
||||
+ clk_enable(omap->usbhost_p1_fck);
|
||||
+ clk_enable(omap->usbtll_p1_fck);
|
||||
+ }
|
||||
+ if (is_ehci_tll_mode(pdata->port_mode[1])) {
|
||||
+ clk_enable(omap->usbhost_p2_fck);
|
||||
+ clk_enable(omap->usbtll_p2_fck);
|
||||
+ }
|
||||
+ clk_enable(omap->utmi_p1_fck);
|
||||
+ clk_enable(omap->utmi_p2_fck);
|
||||
+ }
|
||||
+ clear_bit(OMAP_USBHS_SUSPEND, &omap->state);
|
||||
+
|
||||
+end_resume:
|
||||
+ spin_unlock_irqrestore(&omap->lock, flags);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int usbhs_suspend(struct device *dev)
|
||||
+{
|
||||
+ struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
|
||||
+ struct usbhs_omap_platform_data *pdata = &omap->platdata;
|
||||
+ unsigned long flags = 0;
|
||||
+
|
||||
+ dev_dbg(dev, "Suspending TI HSUSB Controller\n");
|
||||
+
|
||||
+ if (!pdata) {
|
||||
+ dev_dbg(dev, "missing platform_data\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ spin_lock_irqsave(&omap->lock, flags);
|
||||
+
|
||||
+ if (!test_bit(OMAP_USBHS_INIT, &omap->state) ||
|
||||
+ test_bit(OMAP_USBHS_SUSPEND, &omap->state))
|
||||
+ goto end_suspend;
|
||||
+
|
||||
+ if (is_omap_usbhs_rev2(omap)) {
|
||||
+ if (is_ehci_tll_mode(pdata->port_mode[0])) {
|
||||
+ clk_disable(omap->usbhost_p1_fck);
|
||||
+ clk_disable(omap->usbtll_p1_fck);
|
||||
+ }
|
||||
+ if (is_ehci_tll_mode(pdata->port_mode[1])) {
|
||||
+ clk_disable(omap->usbhost_p2_fck);
|
||||
+ clk_disable(omap->usbtll_p2_fck);
|
||||
+ }
|
||||
+ clk_disable(omap->utmi_p2_fck);
|
||||
+ clk_disable(omap->utmi_p1_fck);
|
||||
+ }
|
||||
+
|
||||
+ set_bit(OMAP_USBHS_SUSPEND, &omap->state);
|
||||
+ pm_runtime_put_sync(dev);
|
||||
+
|
||||
+end_suspend:
|
||||
+ spin_unlock_irqrestore(&omap->lock, flags);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static const struct dev_pm_ops usbhsomap_dev_pm_ops = {
|
||||
+ .suspend = usbhs_suspend,
|
||||
+ .resume = usbhs_resume,
|
||||
+};
|
||||
+
|
||||
+#define USBHS_OMAP_DEV_PM_OPS (&usbhsomap_dev_pm_ops)
|
||||
+#else
|
||||
+#define USBHS_OMAP_DEV_PM_OPS NULL
|
||||
+#endif
|
||||
+
|
||||
static struct platform_driver usbhs_omap_driver = {
|
||||
.driver = {
|
||||
.name = (char *)usbhs_driver_name,
|
||||
.owner = THIS_MODULE,
|
||||
+ .pm = USBHS_OMAP_DEV_PM_OPS,
|
||||
},
|
||||
.remove = __exit_p(usbhs_omap_remove),
|
||||
};
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
From 1f2e639755b920398d6592775e0e31f7fb1ca955 Mon Sep 17 00:00:00 2001
|
||||
From: Lesly A M <leslyam@ti.com>
|
||||
Date: Wed, 1 Jun 2011 14:56:38 -0700
|
||||
Subject: [PATCH 08/13] MFD: TWL4030: Correct the warning print during script loading
|
||||
|
||||
Correcting the if condition check for printing the warning,
|
||||
if wakeup script is not updated before updating the sleep script.
|
||||
|
||||
Since the flag 'order' is set to '1' while updating the wakeup script for P1P2,
|
||||
the condition checking for printing the warning should be if(!order)
|
||||
(ie: print the warning if wakeup script is not updated before updating the sleep script)
|
||||
|
||||
Signed-off-by: Lesly A M <leslyam@ti.com>
|
||||
Cc: Nishanth Menon <nm@ti.com>
|
||||
Cc: David Derrick <dderrick@ti.com>
|
||||
Cc: Samuel Ortiz <sameo@linux.intel.com>
|
||||
---
|
||||
drivers/mfd/twl4030-power.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
|
||||
index 2c0d4d1..8373d79 100644
|
||||
--- a/drivers/mfd/twl4030-power.c
|
||||
+++ b/drivers/mfd/twl4030-power.c
|
||||
@@ -448,7 +448,7 @@ static int __init load_twl4030_script(struct twl4030_script *tscript,
|
||||
goto out;
|
||||
}
|
||||
if (tscript->flags & TWL4030_SLEEP_SCRIPT) {
|
||||
- if (order)
|
||||
+ if (!order)
|
||||
pr_warning("TWL4030: Bad order of scripts (sleep "\
|
||||
"script before wakeup) Leads to boot"\
|
||||
"failure on some boards\n");
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
From ea9acebfe2d3ca8fb3969eaf327665632142b85d Mon Sep 17 00:00:00 2001
|
||||
From: Lesly A M <leslyam@ti.com>
|
||||
Date: Wed, 1 Jun 2011 14:56:45 -0700
|
||||
Subject: [PATCH 09/13] MFD: TWL4030: Modifying the macro name Main_Ref to all caps
|
||||
|
||||
Modifying the macro name Main_Ref to all caps(MAIN_REF).
|
||||
|
||||
Suggested by Nishanth Menon <nm@ti.com>
|
||||
|
||||
Signed-off-by: Lesly A M <leslyam@ti.com>
|
||||
Cc: Nishanth Menon <nm@ti.com>
|
||||
Cc: David Derrick <dderrick@ti.com>
|
||||
Cc: Samuel Ortiz <sameo@linux.intel.com>
|
||||
---
|
||||
arch/arm/mach-omap2/board-rx51-peripherals.c | 2 +-
|
||||
drivers/mfd/twl4030-power.c | 2 +-
|
||||
include/linux/i2c/twl.h | 2 +-
|
||||
3 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
|
||||
index bbcb677..01ee0a1 100644
|
||||
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
|
||||
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
|
||||
@@ -730,7 +730,7 @@ static struct twl4030_resconfig twl4030_rconfig[] __initdata = {
|
||||
{ .resource = RES_RESET, .devgroup = -1,
|
||||
.type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1
|
||||
},
|
||||
- { .resource = RES_Main_Ref, .devgroup = -1,
|
||||
+ { .resource = RES_MAIN_REF, .devgroup = -1,
|
||||
.type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1
|
||||
},
|
||||
{ 0, 0},
|
||||
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
|
||||
index 8373d79..8162e43 100644
|
||||
--- a/drivers/mfd/twl4030-power.c
|
||||
+++ b/drivers/mfd/twl4030-power.c
|
||||
@@ -120,7 +120,7 @@ static u8 res_config_addrs[] = {
|
||||
[RES_HFCLKOUT] = 0x8b,
|
||||
[RES_32KCLKOUT] = 0x8e,
|
||||
[RES_RESET] = 0x91,
|
||||
- [RES_Main_Ref] = 0x94,
|
||||
+ [RES_MAIN_REF] = 0x94,
|
||||
};
|
||||
|
||||
static int __init twl4030_write_script_byte(u8 address, u8 byte)
|
||||
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
|
||||
index cbbf3b3..aee3a22 100644
|
||||
--- a/include/linux/i2c/twl.h
|
||||
+++ b/include/linux/i2c/twl.h
|
||||
@@ -502,7 +502,7 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot)
|
||||
#define RES_32KCLKOUT 26
|
||||
#define RES_RESET 27
|
||||
/* Power Reference */
|
||||
-#define RES_Main_Ref 28
|
||||
+#define RES_MAIN_REF 28
|
||||
|
||||
#define TOTAL_RESOURCES 28
|
||||
/*
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,705 @@
|
||||
From 0b29e1f61b85dd2d04f035088b70dc287d15b9f0 Mon Sep 17 00:00:00 2001
|
||||
From: Lesly A M <leslyam@ti.com>
|
||||
Date: Wed, 1 Jun 2011 14:56:49 -0700
|
||||
Subject: [PATCH 10/13] MFD: TWL4030: power scripts for OMAP3 boards
|
||||
|
||||
Power bus message sequence for TWL4030 to enter sleep/wakeup/warm_reset.
|
||||
|
||||
TWL4030 power scripts which can be used by different OMAP3 boards
|
||||
with the power companion chip (TWL4030 series).
|
||||
|
||||
The twl4030 generic script can be used by any board file to update
|
||||
the power data in twl4030_platform_data.
|
||||
|
||||
Since the TWL4030 power script has dependency with APIs in twl4030-power.c
|
||||
removing the __init for these APIs.
|
||||
|
||||
For more information please see:
|
||||
http://omapedia.org/wiki/TWL4030_power_scripts
|
||||
|
||||
Signed-off-by: Lesly A M <leslyam@ti.com>
|
||||
Cc: Nishanth Menon <nm@ti.com>
|
||||
Cc: David Derrick <dderrick@ti.com>
|
||||
Cc: Samuel Ortiz <sameo@linux.intel.com>
|
||||
---
|
||||
arch/arm/configs/omap2plus_defconfig | 1 +
|
||||
arch/arm/mach-omap2/devices.c | 15 ++
|
||||
drivers/mfd/Kconfig | 11 +
|
||||
drivers/mfd/Makefile | 1 +
|
||||
drivers/mfd/twl4030-power.c | 31 ++--
|
||||
drivers/mfd/twl4030-script-omap.c | 373 ++++++++++++++++++++++++++++++++++
|
||||
include/linux/i2c/twl.h | 41 ++++-
|
||||
7 files changed, 454 insertions(+), 19 deletions(-)
|
||||
create mode 100644 drivers/mfd/twl4030-script-omap.c
|
||||
|
||||
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
|
||||
index 076db52..d9b9858 100644
|
||||
--- a/arch/arm/configs/omap2plus_defconfig
|
||||
+++ b/arch/arm/configs/omap2plus_defconfig
|
||||
@@ -184,6 +184,7 @@ CONFIG_TWL4030_WATCHDOG=y
|
||||
CONFIG_MENELAUS=y
|
||||
CONFIG_TWL4030_CORE=y
|
||||
CONFIG_TWL4030_POWER=y
|
||||
+CONFIG_TWL4030_SCRIPT=m
|
||||
CONFIG_REGULATOR=y
|
||||
CONFIG_REGULATOR_TWL4030=y
|
||||
CONFIG_REGULATOR_TPS65023=y
|
||||
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
|
||||
index 7b85585..7653329 100644
|
||||
--- a/arch/arm/mach-omap2/devices.c
|
||||
+++ b/arch/arm/mach-omap2/devices.c
|
||||
@@ -329,6 +329,20 @@ static void omap_init_audio(void)
|
||||
static inline void omap_init_audio(void) {}
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_ARCH_OMAP3
|
||||
+static struct platform_device omap_twl4030_script = {
|
||||
+ .name = "twl4030_script",
|
||||
+ .id = -1,
|
||||
+};
|
||||
+
|
||||
+static void omap_init_twl4030_script(void)
|
||||
+{
|
||||
+ platform_device_register(&omap_twl4030_script);
|
||||
+}
|
||||
+#else
|
||||
+static inline void omap_init_twl4030_script(void) {}
|
||||
+#endif
|
||||
+
|
||||
#if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
|
||||
|
||||
#include <plat/mcspi.h>
|
||||
@@ -691,6 +705,7 @@ static int __init omap2_init_devices(void)
|
||||
omap_init_sham();
|
||||
omap_init_aes();
|
||||
omap_init_vout();
|
||||
+ omap_init_twl4030_script();
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
|
||||
index fe2370a..ea25d93 100644
|
||||
--- a/drivers/mfd/Kconfig
|
||||
+++ b/drivers/mfd/Kconfig
|
||||
@@ -204,6 +204,17 @@ config TWL4030_POWER
|
||||
and load scripts controlling which resources are switched off/on
|
||||
or reset when a sleep, wakeup or warm reset event occurs.
|
||||
|
||||
+config TWL4030_SCRIPT
|
||||
+ tristate "Support TWL4030 script for OMAP3 boards"
|
||||
+ depends on TWL4030_CORE && TWL4030_POWER
|
||||
+ help
|
||||
+ Say yes here if you want to use the twl4030 power scripts
|
||||
+ for OMAP3 boards. Power bus message sequence for
|
||||
+ TWL4030 to enter sleep/wakeup/warm_reset.
|
||||
+
|
||||
+ TWL4030 power scripts which can be used by different
|
||||
+ OMAP3 boards with the power companion chip (TWL4030 series).
|
||||
+
|
||||
config TWL4030_CODEC
|
||||
bool
|
||||
depends on TWL4030_CORE
|
||||
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
|
||||
index 419caa9..53ada21 100644
|
||||
--- a/drivers/mfd/Makefile
|
||||
+++ b/drivers/mfd/Makefile
|
||||
@@ -42,6 +42,7 @@ obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
|
||||
obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o
|
||||
obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o
|
||||
obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o
|
||||
+obj-$(CONFIG_TWL4030_SCRIPT) += twl4030-script-omap.o
|
||||
|
||||
obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o
|
||||
|
||||
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
|
||||
index 8162e43..91d5bc8 100644
|
||||
--- a/drivers/mfd/twl4030-power.c
|
||||
+++ b/drivers/mfd/twl4030-power.c
|
||||
@@ -123,7 +123,7 @@ static u8 res_config_addrs[] = {
|
||||
[RES_MAIN_REF] = 0x94,
|
||||
};
|
||||
|
||||
-static int __init twl4030_write_script_byte(u8 address, u8 byte)
|
||||
+static int twl4030_write_script_byte(u8 address, u8 byte)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -137,7 +137,7 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int __init twl4030_write_script_ins(u8 address, u16 pmb_message,
|
||||
+static int twl4030_write_script_ins(u8 address, u16 pmb_message,
|
||||
u8 delay, u8 next)
|
||||
{
|
||||
int err;
|
||||
@@ -157,7 +157,7 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int __init twl4030_write_script(u8 address, struct twl4030_ins *script,
|
||||
+static int twl4030_write_script(u8 address, struct twl4030_ins *script,
|
||||
int len)
|
||||
{
|
||||
int err;
|
||||
@@ -182,7 +182,7 @@ static int __init twl4030_write_script(u8 address, struct twl4030_ins *script,
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int __init twl4030_config_wakeup3_sequence(u8 address)
|
||||
+static int twl4030_config_wakeup3_sequence(u8 address)
|
||||
{
|
||||
int err;
|
||||
u8 data;
|
||||
@@ -207,7 +207,7 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int __init twl4030_config_wakeup12_sequence(u8 address)
|
||||
+static int twl4030_config_wakeup12_sequence(u8 address)
|
||||
{
|
||||
int err = 0;
|
||||
u8 data;
|
||||
@@ -261,7 +261,7 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int __init twl4030_config_sleep_sequence(u8 address)
|
||||
+static int twl4030_config_sleep_sequence(u8 address)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -275,7 +275,7 @@ static int __init twl4030_config_sleep_sequence(u8 address)
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int __init twl4030_config_warmreset_sequence(u8 address)
|
||||
+static int twl4030_config_warmreset_sequence(u8 address)
|
||||
{
|
||||
int err;
|
||||
u8 rd_data;
|
||||
@@ -323,7 +323,7 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig)
|
||||
+static int twl4030_configure_resource(struct twl4030_resconfig *rconfig)
|
||||
{
|
||||
int rconfig_addr;
|
||||
int err;
|
||||
@@ -415,7 +415,7 @@ static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int __init load_twl4030_script(struct twl4030_script *tscript,
|
||||
+static int load_twl4030_script(struct twl4030_script *tscript,
|
||||
u8 address)
|
||||
{
|
||||
int err;
|
||||
@@ -510,8 +510,9 @@ int twl4030_remove_script(u8 flags)
|
||||
|
||||
return err;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(twl4030_remove_script);
|
||||
|
||||
-void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
|
||||
+int twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
|
||||
{
|
||||
int err = 0;
|
||||
int i;
|
||||
@@ -529,7 +530,6 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
|
||||
TWL4030_PM_MASTER_PROTECT_KEY);
|
||||
if (err)
|
||||
goto unlock;
|
||||
-
|
||||
for (i = 0; i < twl4030_scripts->num; i++) {
|
||||
err = load_twl4030_script(twl4030_scripts->scripts[i], address);
|
||||
if (err)
|
||||
@@ -552,18 +552,19 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
|
||||
TWL4030_PM_MASTER_PROTECT_KEY);
|
||||
if (err)
|
||||
pr_err("TWL4030 Unable to relock registers\n");
|
||||
- return;
|
||||
+ return err;
|
||||
|
||||
unlock:
|
||||
if (err)
|
||||
pr_err("TWL4030 Unable to unlock registers\n");
|
||||
- return;
|
||||
+ return err;
|
||||
load:
|
||||
if (err)
|
||||
pr_err("TWL4030 failed to load scripts\n");
|
||||
- return;
|
||||
+ return err;
|
||||
resource:
|
||||
if (err)
|
||||
pr_err("TWL4030 failed to configure resource\n");
|
||||
- return;
|
||||
+ return err;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(twl4030_power_init);
|
||||
diff --git a/drivers/mfd/twl4030-script-omap.c b/drivers/mfd/twl4030-script-omap.c
|
||||
new file mode 100644
|
||||
index 0000000..867a442
|
||||
--- /dev/null
|
||||
+++ b/drivers/mfd/twl4030-script-omap.c
|
||||
@@ -0,0 +1,373 @@
|
||||
+/*
|
||||
+ * OMAP power script for PMIC TWL4030
|
||||
+ *
|
||||
+ * Author: Lesly A M <leslyam@ti.com>
|
||||
+ *
|
||||
+ * Copyright (C) 2010 Texas Instruments, Inc.
|
||||
+ * Lesly A M <leslyam@ti.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License version 2 as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#include <linux/i2c/twl.h>
|
||||
+
|
||||
+/*
|
||||
+ * power management signal connections for OMAP3430 with TWL5030
|
||||
+ *
|
||||
+ * TWL5030 OMAP3430
|
||||
+ * ______________________ _____________________
|
||||
+ * | | | |
|
||||
+ * | (P1) NSLEEP1|<----------|SYS_OFFMODE |
|
||||
+ * | NRESWARM|<----------|NWARMRESET |
|
||||
+ * | (P2) NSLEEP2|---| | |
|
||||
+ * | | === | |
|
||||
+ * | | - | |
|
||||
+ * | | | |
|
||||
+ * | VDD1 |---------->| VDD1 |
|
||||
+ * | VDD2 |---------->| VDD2 |
|
||||
+ * | VIO |---------->| VDDS |
|
||||
+ * ________ | VAUX1 | | |
|
||||
+ * | | | ... | | |
|
||||
+ * | ENABLE|<--------|CLKEN CLKREQ|<----------|SYS_CLKREQ |
|
||||
+ * | CLKOUT|-------->|HFCLKIN (P3) HFCLKOUT|---------->|XTALIN |
|
||||
+ * |________| |______________________| |_____________________|
|
||||
+ *
|
||||
+ *
|
||||
+ * Signal descriptions:
|
||||
+ *
|
||||
+ * SYS_OFFMODE - OMAP drives this signal low only when the OMAP is in the
|
||||
+ * OFF idle mode. It is driven high when a wake up event is detected.
|
||||
+ * This signal should control the P1 device group in the PMIC.
|
||||
+ *
|
||||
+ * SYS_CLKREQ - OMAP should drive this signal low when the OMAP goes into
|
||||
+ * any idle mode. This signal should control the P3 device group
|
||||
+ * in the PMIC. It is used to notify PMIC when XTALIN is no longer needed.
|
||||
+ *
|
||||
+ * NSLEEP1(P1) - When this signal goes low the P1 sleep sequence is executed
|
||||
+ * in the PMIC turning off certain resources. When this signal goes high
|
||||
+ * the P1 active sequence is executed turning back on certain resources.
|
||||
+ *
|
||||
+ * NSLEEP2(P2) - This signal controls the P2 device group of the PMIC.
|
||||
+ * It is not used in this setup and should be tied to ground.
|
||||
+ * This can be used for connecting a different processor or MODEM chip.
|
||||
+ *
|
||||
+ * CLKREQ(P3) - When this signal goes low the P3 sleep sequence is executed
|
||||
+ * in the PMIC turning off HFCLKOUT. When this signal goes high
|
||||
+ * the P3 active sequence is executed turning back on HFCLKOUT and other
|
||||
+ * resources.
|
||||
+ *
|
||||
+ * CLKEN - Enable signal for oscillator. Should only go low when OMAP is
|
||||
+ * in the OFF idle mode due to long oscillator startup times.
|
||||
+ *
|
||||
+ * HFCLKIN - Oscillator output clock into PMIC.
|
||||
+ *
|
||||
+ * HFCLKOUT - System clock output from PMIC to OMAP.
|
||||
+ *
|
||||
+ * XTALIN - OMAP system clock input(HFCLKOUT).
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * Recommended sleep and active sequences for TWL5030 when connected to OMAP3
|
||||
+ *
|
||||
+ * WARNING: If the board is using NSLEEP2(P2), should modify this script and
|
||||
+ * setuptime values accordingly.
|
||||
+ *
|
||||
+ * Chip Retention/Off (using i2c for scaling voltage):
|
||||
+ * When OMAP de-assert the SYS_CLKREQ signal, only HFCLKOUT is affected
|
||||
+ * since it is the only resource assigned to P3 only.
|
||||
+ *
|
||||
+ * Sysoff (using sys_off signal):
|
||||
+ * When OMAP de-assert the SYS_OFFMODE signal A2S(active to sleep sequence)
|
||||
+ * on the PMIC is executed. This will put resources of TYPE2=1 and TYPE2=2
|
||||
+ * into sleep. At this point only resources assigned to P1 only will be
|
||||
+ * affected (VDD1, VDD2 & VPLL1).
|
||||
+ *
|
||||
+ * Next the OMAP will lower SYS_CLKREQ which will allow the A2S sequence
|
||||
+ * in PMIC to execute again. This will put resources of TYPE2=1 and TYPE2=2
|
||||
+ * into sleep but will affect resources that are assigned to P3(HFCLKOUT)
|
||||
+ * only or assigned to P1 and P3.
|
||||
+ *
|
||||
+ * On wakeup event OMAP goes active and pulls the SYS_CLKREQ high,
|
||||
+ * which will execute the P3 S2A sequence on the PMIC. This will turn on
|
||||
+ * resources assigned to P3 or assigned to P1 and P3 and of TYPE2=2.
|
||||
+ *
|
||||
+ * Next the OMAP will wait the PRM_VOLTOFFSET time and then de-assert
|
||||
+ * the SYS_OFFMODE pin allowing the PMIC to execute the P1 S2A active
|
||||
+ * sequence. This will turn on resources assigned to P1 or assigned to
|
||||
+ * P1 and P3 and of TYPE2=1.
|
||||
+ *
|
||||
+ * Timing diagram for OMAP wakeup from OFFMODE using sys_off signal
|
||||
+ * _____________________________________________________________
|
||||
+ * OMAP active __/
|
||||
+ * |<--------------------PRM_CLKSETP-------------------->|
|
||||
+ * ______________________________________________________
|
||||
+ * SYS_CLKREQ _________/
|
||||
+ * ___________________________________________________
|
||||
+ * CLKEN ____________/
|
||||
+ *
|
||||
+ * HFCLKIN _______________________________________________/////////////////
|
||||
+ *
|
||||
+ * HFCLKOUT __________________________________________________//////////////
|
||||
+ * |<---PRM_VOLTOFFSET-->|
|
||||
+ * ________________________________
|
||||
+ * SYS_OFFMODE _______________________________/
|
||||
+ * |<--------PRM_VOLTSETUP2------->|
|
||||
+ * ___________
|
||||
+ * VPLL1 ____________________________________________________/
|
||||
+ * __
|
||||
+ * VDD1 _____________________________________________________________/
|
||||
+ * __
|
||||
+ * VDD2 _____________________________________________________________/
|
||||
+ *
|
||||
+ * Other resources which are not handled by this script should be
|
||||
+ * controlled by the respective drivers using them (VAUX1, VAUX2, VAUX3,
|
||||
+ * VAUX4, VMMC1, VMMC2, VPLL2, VSIM, VDAC, VUSB1V5, VUSB1V8 & VUSB3V1).
|
||||
+ *
|
||||
+ * More info:
|
||||
+ * http://omapedia.org/wiki/TWL4030_power_scripts
|
||||
+ */
|
||||
+
|
||||
+/**
|
||||
+ * DOC: Sleep to active sequence for P1/P2
|
||||
+ *
|
||||
+ * Sequence to control the TWL4030 Power resources,
|
||||
+ * when the system wakeup from sleep.
|
||||
+ * Executed upon P1_P2 transition for wakeup
|
||||
+ * (sys_offmode signal de-asserted on OMAP).
|
||||
+ */
|
||||
+static struct twl4030_ins wakeup_p12_seq[] __initdata = {
|
||||
+ /*
|
||||
+ * Broadcast message to put resources to active
|
||||
+ *
|
||||
+ * Since we are not using TYPE, resources which have TYPE2 configured
|
||||
+ * as 1 will be targeted (VPLL1, VDD1, VDD2, REGEN, NRES_PWRON, SYSEN).
|
||||
+ */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1,
|
||||
+ RES_STATE_ACTIVE), 2},
|
||||
+};
|
||||
+
|
||||
+static struct twl4030_script wakeup_p12_script __initdata = {
|
||||
+ .script = wakeup_p12_seq,
|
||||
+ .size = ARRAY_SIZE(wakeup_p12_seq),
|
||||
+ .flags = TWL4030_WAKEUP12_SCRIPT,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * DOC: Sleep to active sequence for P3
|
||||
+ *
|
||||
+ * Sequence to control the TWL4030 Power resources,
|
||||
+ * when the system wakeup from sleep.
|
||||
+ * Executed upon P3 transition for wakeup
|
||||
+ * (clkreq signal asserted on OMAP).
|
||||
+ */
|
||||
+static struct twl4030_ins wakeup_p3_seq[] __initdata = {
|
||||
+ /*
|
||||
+ * Broadcast message to put resources to active
|
||||
+ *
|
||||
+ * Since we are not using TYPE, resources which have TYPE2 configured
|
||||
+ * as 2 will be targeted
|
||||
+ * (VINTANA1, VINTANA2, VINTDIG, VIO, CLKEN, HFCLKOUT).
|
||||
+ */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
|
||||
+ RES_STATE_ACTIVE), 2},
|
||||
+};
|
||||
+
|
||||
+static struct twl4030_script wakeup_p3_script __initdata = {
|
||||
+ .script = wakeup_p3_seq,
|
||||
+ .size = ARRAY_SIZE(wakeup_p3_seq),
|
||||
+ .flags = TWL4030_WAKEUP3_SCRIPT,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * DOC: Active to sleep sequence for P1/P2/P3
|
||||
+ *
|
||||
+ * Sequence to control the TWL4030 Power resources,
|
||||
+ * when the system goes into sleep.
|
||||
+ * Executed upon P1_P2/P3 transition for sleep.
|
||||
+ * (sys_offmode signal asserted/clkreq de-asserted on OMAP).
|
||||
+ */
|
||||
+static struct twl4030_ins sleep_on_seq[] __initdata = {
|
||||
+ /* Broadcast message to put res to sleep (TYPE2 = 1, 2) */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1,
|
||||
+ RES_STATE_SLEEP), 2},
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
|
||||
+ RES_STATE_SLEEP), 2},
|
||||
+};
|
||||
+
|
||||
+static struct twl4030_script sleep_on_script __initdata = {
|
||||
+ .script = sleep_on_seq,
|
||||
+ .size = ARRAY_SIZE(sleep_on_seq),
|
||||
+ .flags = TWL4030_SLEEP_SCRIPT,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * DOC: Warm reset sequence
|
||||
+ *
|
||||
+ * Sequence to reset the TWL4030 Power resources,
|
||||
+ * when the system gets warm reset.
|
||||
+ * Executed upon warm reset signal.
|
||||
+ *
|
||||
+ * First the device is put in reset, then the system clock is requested to
|
||||
+ * the external oscillator, and default ON power reference and power providers
|
||||
+ * are enabled. Next some additional resources which are software controlled
|
||||
+ * are enabled. Finally sequence is ended by the release of TWL5030 reset.
|
||||
+ */
|
||||
+static struct twl4030_ins wrst_seq[] __initdata = {
|
||||
+ /*
|
||||
+ * As a workaround for OMAP Erratum (ID: i537 - OMAP HS devices are
|
||||
+ * not recovering from warm reset while in OFF mode)
|
||||
+ * NRESPWRON is toggled to force a power on reset condition to OMAP
|
||||
+ */
|
||||
+ /* Trun OFF NRES_PWRON */
|
||||
+ {MSG_SINGULAR(DEV_GRP_NULL, RES_NRES_PWRON, RES_STATE_OFF), 2},
|
||||
+ /* Reset twl4030 */
|
||||
+ {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_OFF), 2},
|
||||
+ /* Reset MAIN_REF */
|
||||
+ {MSG_SINGULAR(DEV_GRP_NULL, RES_MAIN_REF, RES_STATE_WRST), 2},
|
||||
+ /* Reset All type2_group2 */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
|
||||
+ RES_STATE_WRST), 2},
|
||||
+ /* Reset VUSB_3v1 */
|
||||
+ {MSG_SINGULAR(DEV_GRP_NULL, RES_VUSB_3V1, RES_STATE_WRST), 2},
|
||||
+ /* Reset All type2_group1 */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1,
|
||||
+ RES_STATE_WRST), 2},
|
||||
+ /* Reset the Reset & Contorl_signals */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_RC, RES_TYPE_ALL, RES_TYPE2_R0,
|
||||
+ RES_STATE_WRST), 2},
|
||||
+ /* Re-enable twl4030 */
|
||||
+ {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_ACTIVE), 2},
|
||||
+ /* Trun ON NRES_PWRON */
|
||||
+ {MSG_SINGULAR(DEV_GRP_NULL, RES_NRES_PWRON, RES_STATE_ACTIVE), 2},
|
||||
+};
|
||||
+
|
||||
+static struct twl4030_script wrst_script __initdata = {
|
||||
+ .script = wrst_seq,
|
||||
+ .size = ARRAY_SIZE(wrst_seq),
|
||||
+ .flags = TWL4030_WRST_SCRIPT,
|
||||
+};
|
||||
+
|
||||
+/* TWL4030 script for sleep, wakeup & warm_reset */
|
||||
+static struct twl4030_script *twl4030_scripts[] __initdata = {
|
||||
+ &wakeup_p12_script,
|
||||
+ &wakeup_p3_script,
|
||||
+ &sleep_on_script,
|
||||
+ &wrst_script,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * DOC: TWL4030 resource configuration
|
||||
+ *
|
||||
+ * Resource which are attached to P1 device group alone
|
||||
+ * will go to sleep state, when sys_off signal from OMAP is de-asserted.
|
||||
+ * (VPLL1, VDD1, VDD2)
|
||||
+ *
|
||||
+ * None of the resources are attached to P2 device group alone.
|
||||
+ * (WARNING: If MODEM or connectivity chip is connected to NSLEEP2 PIN on
|
||||
+ * TWL4030, should modify the resource configuration accordingly).
|
||||
+ *
|
||||
+ * Resource which are attached to P3 device group alone
|
||||
+ * will go to sleep state, when clk_req signal from OMAP is de-asserted.
|
||||
+ * (HFCLKOUT)
|
||||
+ *
|
||||
+ * Resource which are attached to more than one device group
|
||||
+ * will go to sleep state, when corresponding signals are de-asserted.
|
||||
+ * (VINTANA1, VINTANA2, VINTDIG, VIO, REGEN, NRESPWRON, CLKEN, SYSEN)
|
||||
+ *
|
||||
+ * REGEN is an output of the device which can be connected to slave power ICs
|
||||
+ * or external LDOs that power on before voltage for the IO interface (VIO).
|
||||
+ *
|
||||
+ * SYSEN is a bidirectional signal of the device that controls slave power ICs.
|
||||
+ * In master mode, the device sets SYSEN high to enable the slave power ICs.
|
||||
+ * In slave mode, when one of the power ICs drives the SYSEN signal low,
|
||||
+ * all devices of the platform stay in the wait-on state.
|
||||
+ *
|
||||
+ * Resource which are attached to none of the device group by default
|
||||
+ * will be in sleep state. These resource should be controlled by
|
||||
+ * the respective drivers using them.
|
||||
+ * Resource which are controlled by drivers are not modified here.
|
||||
+ * (VAUX1, VAUX2, VAUX3, VAUX4, VMMC1, VMMC2, VPLL2, VSIM, VDAC,
|
||||
+ * VUSB1V5, VUSB1V8, VUSB3V1)
|
||||
+ *
|
||||
+ * Resource using reset values.
|
||||
+ * (32KCLKOUT, TRITON_RESET, MAINREF)
|
||||
+ */
|
||||
+static struct twl4030_resconfig twl4030_rconfig[] __initdata = {
|
||||
+ { .resource = RES_VPLL1, .devgroup = DEV_GRP_P1, .type = 3,
|
||||
+ .type2 = 1, .remap_sleep = RES_STATE_OFF },
|
||||
+ { .resource = RES_VINTANA1, .devgroup = DEV_GRP_ALL, .type = 1,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_VINTANA2, .devgroup = DEV_GRP_ALL, .type = 0,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_VINTDIG, .devgroup = DEV_GRP_ALL, .type = 1,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_VIO, .devgroup = DEV_GRP_ALL, .type = 2,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_VDD1, .devgroup = DEV_GRP_P1,
|
||||
+ .type = 4, .type2 = 1, .remap_sleep = RES_STATE_OFF },
|
||||
+ { .resource = RES_VDD2, .devgroup = DEV_GRP_P1,
|
||||
+ .type = 3, .type2 = 1, .remap_sleep = RES_STATE_OFF },
|
||||
+ { .resource = RES_REGEN, .devgroup = DEV_GRP_ALL, .type = 2,
|
||||
+ .type2 = 1, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_NRES_PWRON, .devgroup = DEV_GRP_ALL, .type = 0,
|
||||
+ .type2 = 1, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_CLKEN, .devgroup = DEV_GRP_ALL, .type = 3,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_SYSEN, .devgroup = DEV_GRP_ALL, .type = 6,
|
||||
+ .type2 = 1, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_HFCLKOUT, .devgroup = DEV_GRP_P3,
|
||||
+ .type = 0, .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { 0, 0},
|
||||
+};
|
||||
+
|
||||
+struct twl4030_power_data twl4030_generic_script __initdata = {
|
||||
+ .scripts = twl4030_scripts,
|
||||
+ .num = ARRAY_SIZE(twl4030_scripts),
|
||||
+ .resource_config = twl4030_rconfig,
|
||||
+};
|
||||
+
|
||||
+static int __init twl4030_script_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ return twl4030_power_init(&twl4030_generic_script);
|
||||
+}
|
||||
+
|
||||
+static int twl4030_script_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ return twl4030_remove_script(TWL4030_SLEEP_SCRIPT |
|
||||
+ TWL4030_WAKEUP12_SCRIPT | TWL4030_WAKEUP3_SCRIPT |
|
||||
+ TWL4030_WRST_SCRIPT);
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver twl4030_script_driver = {
|
||||
+ .remove = twl4030_script_remove,
|
||||
+ .driver = {
|
||||
+ .name = "twl4030_script",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init twl4030_script_init(void)
|
||||
+{
|
||||
+ /* Register the TWL4030 script driver */
|
||||
+ return platform_driver_probe(&twl4030_script_driver,
|
||||
+ twl4030_script_probe);
|
||||
+}
|
||||
+
|
||||
+static void __exit twl4030_script_cleanup(void)
|
||||
+{
|
||||
+ /* Unregister TWL4030 script driver */
|
||||
+ platform_driver_unregister(&twl4030_script_driver);
|
||||
+}
|
||||
+
|
||||
+module_init(twl4030_script_init);
|
||||
+module_exit(twl4030_script_cleanup);
|
||||
+
|
||||
+MODULE_DESCRIPTION("OMAP TWL4030 script driver");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_AUTHOR("Texas Instruments Inc");
|
||||
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
|
||||
index aee3a22..f343974 100644
|
||||
--- a/include/linux/i2c/twl.h
|
||||
+++ b/include/linux/i2c/twl.h
|
||||
@@ -205,6 +205,12 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot)
|
||||
return -EIO;
|
||||
}
|
||||
#endif
|
||||
+
|
||||
+#ifdef CONFIG_TWL4030_POWER
|
||||
+extern struct twl4030_power_data twl4030_generic_script;
|
||||
+#else
|
||||
+#define twl4030_generic_script NULL;
|
||||
+#endif
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
@@ -437,9 +443,23 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot)
|
||||
|
||||
/* Power bus message definitions */
|
||||
|
||||
-/* The TWL4030/5030 splits its power-management resources (the various
|
||||
- * regulators, clock and reset lines) into 3 processor groups - P1, P2 and
|
||||
- * P3. These groups can then be configured to transition between sleep, wait-on
|
||||
+/*
|
||||
+ * The TWL4030/5030 splits its power-management resources (the various
|
||||
+ * regulators, clock and reset lines) into 3 processor groups - P1, P2 and P3.
|
||||
+ *
|
||||
+ * Resources attached to device group P1 is managed depending on the state of
|
||||
+ * NSLEEP1 pin of TWL4030, which is connected to sys_off signal from OMAP
|
||||
+ *
|
||||
+ * Resources attached to device group P2 is managed depending on the state of
|
||||
+ * NSLEEP2 pin of TWL4030, which is can be connected to a modem or
|
||||
+ * connectivity chip
|
||||
+ *
|
||||
+ * Resources attached to device group P3 is managed depending on the state of
|
||||
+ * CLKREQ pin of TWL4030, which is connected to clk request signal from OMAP
|
||||
+ *
|
||||
+ * If required these resources can be attached to combination of P1/P2/P3.
|
||||
+ *
|
||||
+ * These groups can then be configured to transition between sleep, wait-on
|
||||
* and active states by sending messages to the power bus. See Section 5.4.2
|
||||
* Power Resources of TWL4030 TRM
|
||||
*/
|
||||
@@ -449,7 +469,17 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot)
|
||||
#define DEV_GRP_P1 0x1 /* P1: all OMAP devices */
|
||||
#define DEV_GRP_P2 0x2 /* P2: all Modem devices */
|
||||
#define DEV_GRP_P3 0x4 /* P3: all peripheral devices */
|
||||
+#define DEV_GRP_ALL 0x7 /* P1/P2/P3: all devices */
|
||||
|
||||
+/*
|
||||
+ * The 27 power resources in TWL4030 is again divided into
|
||||
+ * analog resources:
|
||||
+ * Power Providers - LDO regulators, dc-to-dc regulators
|
||||
+ * Power Reference - analog reference
|
||||
+ *
|
||||
+ * and digital resources:
|
||||
+ * Reset & Clock - reset and clock signals.
|
||||
+ */
|
||||
/* Resource groups */
|
||||
#define RES_GRP_RES 0x0 /* Reserved */
|
||||
#define RES_GRP_PP 0x1 /* Power providers */
|
||||
@@ -461,7 +491,10 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot)
|
||||
#define RES_GRP_ALL 0x7 /* All resource groups */
|
||||
|
||||
#define RES_TYPE2_R0 0x0
|
||||
+#define RES_TYPE2_R1 0x1
|
||||
+#define RES_TYPE2_R2 0x2
|
||||
|
||||
+#define RES_TYPE_R0 0x0
|
||||
#define RES_TYPE_ALL 0x7
|
||||
|
||||
/* Resource states */
|
||||
@@ -636,7 +669,7 @@ struct twl4030_power_data {
|
||||
#define TWL4030_RESCONFIG_UNDEF ((u8)-1)
|
||||
};
|
||||
|
||||
-extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);
|
||||
+extern int twl4030_power_init(struct twl4030_power_data *triton2_scripts);
|
||||
extern int twl4030_remove_script(u8 flags);
|
||||
|
||||
struct twl4030_codec_audio_data {
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
From 3ceb224732230934aba7d082f3e2ca96c14a9ca0 Mon Sep 17 00:00:00 2001
|
||||
From: Lesly A M <leslyam@ti.com>
|
||||
Date: Wed, 1 Jun 2011 14:56:56 -0700
|
||||
Subject: [PATCH 11/13] MFD: TWL4030: TWL version checking
|
||||
|
||||
Added API to get the TWL5030 Si version from the IDCODE register.
|
||||
It is used for enabling the workaround for TWL erratum 27.
|
||||
|
||||
Signed-off-by: Lesly A M <leslyam@ti.com>
|
||||
Cc: Nishanth Menon <nm@ti.com>
|
||||
Cc: David Derrick <dderrick@ti.com>
|
||||
Cc: Samuel Ortiz <sameo@linux.intel.com>
|
||||
---
|
||||
drivers/mfd/twl-core.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/i2c/twl.h | 17 ++++++++++++-
|
||||
2 files changed, 78 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
|
||||
index 9096d7d..a60601d 100644
|
||||
--- a/drivers/mfd/twl-core.c
|
||||
+++ b/drivers/mfd/twl-core.c
|
||||
@@ -251,6 +251,9 @@
|
||||
/* is driver active, bound to a chip? */
|
||||
static bool inuse;
|
||||
|
||||
+/* TWL IDCODE Register value */
|
||||
+static u32 twl_idcode;
|
||||
+
|
||||
static unsigned int twl_id;
|
||||
unsigned int twl_rev(void)
|
||||
{
|
||||
@@ -509,6 +512,58 @@ EXPORT_SYMBOL(twl_i2c_read_u8);
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
+/**
|
||||
+ * twl_read_idcode_register - API to read the IDCODE register.
|
||||
+ *
|
||||
+ * Unlocks the IDCODE register and read the 32 bit value.
|
||||
+ */
|
||||
+static int twl_read_idcode_register(void)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ err = twl_i2c_write_u8(TWL4030_MODULE_INTBR, TWL_EEPROM_R_UNLOCK,
|
||||
+ REG_UNLOCK_TEST_REG);
|
||||
+ if (err) {
|
||||
+ pr_err("TWL4030 Unable to unlock IDCODE registers -%d\n", err);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ err = twl_i2c_read(TWL4030_MODULE_INTBR, (u8 *)(&twl_idcode),
|
||||
+ REG_IDCODE_7_0, 4);
|
||||
+ if (err) {
|
||||
+ pr_err("TWL4030: unable to read IDCODE -%d\n", err);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ err = twl_i2c_write_u8(TWL4030_MODULE_INTBR, 0x0, REG_UNLOCK_TEST_REG);
|
||||
+ if (err)
|
||||
+ pr_err("TWL4030 Unable to relock IDCODE registers -%d\n", err);
|
||||
+fail:
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * twl_get_type - API to get TWL Si type.
|
||||
+ *
|
||||
+ * Api to get the TWL Si type from IDCODE value.
|
||||
+ */
|
||||
+int twl_get_type(void)
|
||||
+{
|
||||
+ return TWL_SIL_TYPE(twl_idcode);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(twl_get_type);
|
||||
+
|
||||
+/**
|
||||
+ * twl_get_version - API to get TWL Si version.
|
||||
+ *
|
||||
+ * Api to get the TWL Si version from IDCODE value.
|
||||
+ */
|
||||
+int twl_get_version(void)
|
||||
+{
|
||||
+ return TWL_SIL_REV(twl_idcode);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(twl_get_version);
|
||||
+
|
||||
static struct device *
|
||||
add_numbered_child(unsigned chip, const char *name, int num,
|
||||
void *pdata, unsigned pdata_len,
|
||||
@@ -1071,6 +1126,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
unsigned i;
|
||||
struct twl4030_platform_data *pdata = client->dev.platform_data;
|
||||
u8 temp;
|
||||
+ int ret = 0;
|
||||
|
||||
if (!pdata) {
|
||||
dev_dbg(&client->dev, "no platform data?\n");
|
||||
@@ -1117,6 +1173,12 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
/* setup clock framework */
|
||||
clocks_init(&client->dev, pdata->clock);
|
||||
|
||||
+ /* read TWL IDCODE Register */
|
||||
+ if (twl_id == TWL4030_CLASS_ID) {
|
||||
+ ret = twl_read_idcode_register();
|
||||
+ WARN(ret < 0, "Error: reading twl_idcode register value\n");
|
||||
+ }
|
||||
+
|
||||
/* load power event scripts */
|
||||
if (twl_has_power() && pdata->power)
|
||||
twl4030_power_init(pdata->power);
|
||||
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
|
||||
index f343974..23ec058 100644
|
||||
--- a/include/linux/i2c/twl.h
|
||||
+++ b/include/linux/i2c/twl.h
|
||||
@@ -151,7 +151,12 @@
|
||||
#define MMC_PU (0x1 << 3)
|
||||
#define MMC_PD (0x1 << 2)
|
||||
|
||||
-
|
||||
+#define TWL_SIL_TYPE(rev) ((rev) & 0x00FFFFFF)
|
||||
+#define TWL_SIL_REV(rev) ((rev) >> 24)
|
||||
+#define TWL_SIL_5030 0x09002F
|
||||
+#define TWL5030_REV_1_0 0x00
|
||||
+#define TWL5030_REV_1_1 0x10
|
||||
+#define TWL5030_REV_1_2 0x30
|
||||
|
||||
#define TWL4030_CLASS_ID 0x4030
|
||||
#define TWL6030_CLASS_ID 0x6030
|
||||
@@ -181,6 +186,9 @@ int twl_i2c_read_u8(u8 mod_no, u8 *val, u8 reg);
|
||||
int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
|
||||
int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
|
||||
|
||||
+int twl_get_type(void);
|
||||
+int twl_get_version(void);
|
||||
+
|
||||
int twl6030_interrupt_unmask(u8 bit_mask, u8 offset);
|
||||
int twl6030_interrupt_mask(u8 bit_mask, u8 offset);
|
||||
|
||||
@@ -286,7 +294,12 @@ extern struct twl4030_power_data twl4030_generic_script;
|
||||
*(Use TWL_4030_MODULE_INTBR)
|
||||
*/
|
||||
|
||||
+#define REG_IDCODE_7_0 0x00
|
||||
+#define REG_IDCODE_15_8 0x01
|
||||
+#define REG_IDCODE_16_23 0x02
|
||||
+#define REG_IDCODE_31_24 0x03
|
||||
#define REG_GPPUPDCTR1 0x0F
|
||||
+#define REG_UNLOCK_TEST_REG 0x12
|
||||
|
||||
/*I2C1 and I2C4(SR) SDA/SCL pull-up control bits */
|
||||
|
||||
@@ -295,6 +308,8 @@ extern struct twl4030_power_data twl4030_generic_script;
|
||||
#define SR_I2C_SCL_CTRL_PU BIT(4)
|
||||
#define SR_I2C_SDA_CTRL_PU BIT(6)
|
||||
|
||||
+#define TWL_EEPROM_R_UNLOCK 0x49
|
||||
+
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,341 @@
|
||||
From 0bec9f7b20e7c61e0bab93195ec39cf94f1f8e25 Mon Sep 17 00:00:00 2001
|
||||
From: Lesly A M <leslyam@ti.com>
|
||||
Date: Wed, 1 Jun 2011 14:57:01 -0700
|
||||
Subject: [PATCH 12/13] MFD: TWL4030: workaround changes for Erratum 27
|
||||
|
||||
Workaround for TWL5030 Silicon Errata 27 & 28:
|
||||
27 - VDD1, VDD2, may have glitches when their output value is updated.
|
||||
28 - VDD1 and / or VDD2 DCDC clock may stop working when internal clock
|
||||
is switched from internal to external.
|
||||
|
||||
Erratum 27:
|
||||
If the DCDC regulators is running on their internal oscillator,
|
||||
negative glitches may occur on VDD1, VDD2 output when voltage is changed.
|
||||
The OMAP device may reboot if the VDD1 or VDD2 go below the
|
||||
core minimum operating voltage.
|
||||
|
||||
WORKAROUND
|
||||
Set up the TWL5030 DC-DC power supplies to use the HFCLKIN instead of
|
||||
the internal oscillator.
|
||||
|
||||
Erratum 28:
|
||||
VDD1/VDD2 clock system may hang during switching the clock source from
|
||||
internal oscillator to external. VDD1/VDD2 output voltages may collapse
|
||||
if clock stops.
|
||||
|
||||
WORKAROUND
|
||||
If HFCLK is disabled in OFFMODE, modify the sleep/wakeup sequence and
|
||||
setuptimes to make sure the switching will happen only when HFCLKIN is stable.
|
||||
Also use the TWL5030 watchdog to safeguard the first switching from
|
||||
internal oscillator to HFCLKIN during the TWL5030 init.
|
||||
|
||||
IMPACT
|
||||
power sequence is changed.
|
||||
sleep/wakeup time values will be changed.
|
||||
|
||||
The workaround changes are called from twl4030_power_init(), since we have to
|
||||
make some i2c_read calls to check the TWL4030 version & the i2c will not be
|
||||
initialized in the early stage.
|
||||
|
||||
This workaround is required for TWL5030 Silicon version less than ES1.2
|
||||
The power script & setup time changes are recommended by TI HW team.
|
||||
|
||||
For more information please see:
|
||||
http://omapedia.org/wiki/TWL4030_power_scripts
|
||||
|
||||
Changes taken from TWL4030 Erratum 27 workaround patch by Nishanth Menon.
|
||||
|
||||
Signed-off-by: Lesly A M <leslyam@ti.com>
|
||||
Cc: Nishanth Menon <nm@ti.com>
|
||||
Cc: David Derrick <dderrick@ti.com>
|
||||
Cc: Samuel Ortiz <sameo@linux.intel.com>
|
||||
---
|
||||
drivers/mfd/twl4030-power.c | 79 +++++++++++++++++++
|
||||
drivers/mfd/twl4030-script-omap.c | 150 +++++++++++++++++++++++++++++++++++++
|
||||
include/linux/i2c/twl.h | 1 +
|
||||
3 files changed, 230 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
|
||||
index 91d5bc8..8af3fe3 100644
|
||||
--- a/drivers/mfd/twl4030-power.c
|
||||
+++ b/drivers/mfd/twl4030-power.c
|
||||
@@ -63,6 +63,14 @@ static u8 twl4030_start_script_address = 0x2b;
|
||||
#define R_MEMORY_ADDRESS PHY_TO_OFF_PM_MASTER(0x59)
|
||||
#define R_MEMORY_DATA PHY_TO_OFF_PM_MASTER(0x5a)
|
||||
|
||||
+#define R_VDD1_OSC 0x5C
|
||||
+#define R_VDD2_OSC 0x6A
|
||||
+#define R_VIO_OSC 0x52
|
||||
+#define EXT_FS_CLK_EN BIT(6)
|
||||
+
|
||||
+#define R_WDT_CFG 0x03
|
||||
+#define WDT_WRK_TIMEOUT 0x03
|
||||
+
|
||||
/* resource configuration registers
|
||||
<RESOURCE>_DEV_GRP at address 'n+0'
|
||||
<RESOURCE>_TYPE at address 'n+1'
|
||||
@@ -512,6 +520,67 @@ int twl4030_remove_script(u8 flags)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(twl4030_remove_script);
|
||||
|
||||
+/**
|
||||
+ * twl_dcdc_use_hfclk - API to use HFCLK for TWL DCDCs
|
||||
+ *
|
||||
+ * TWL DCDCs switching to HFCLK instead of using internal RC oscillator.
|
||||
+ */
|
||||
+static int twl_dcdc_use_hfclk(void)
|
||||
+{
|
||||
+ u8 val;
|
||||
+ u8 smps_osc_reg[] = {R_VDD1_OSC, R_VDD2_OSC, R_VIO_OSC};
|
||||
+ int i;
|
||||
+ int err;
|
||||
+
|
||||
+ for (i = 0; i < sizeof(smps_osc_reg); i++) {
|
||||
+ err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &val,
|
||||
+ smps_osc_reg[i]);
|
||||
+ val |= EXT_FS_CLK_EN;
|
||||
+ err |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, val,
|
||||
+ smps_osc_reg[i]);
|
||||
+ }
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * twl_erratum27_workaround - Workaround for TWL5030 Silicon Erratum 27
|
||||
+ * 27 - VDD1, VDD2, may have glitches when their output value is updated.
|
||||
+ * 28 - VDD1 and / or VDD2 DCDC clock may stop working when internal clock is
|
||||
+ * switched from internal to external.
|
||||
+ *
|
||||
+ * Workaround requires the TWL DCDCs to use HFCLK instead of
|
||||
+ * internal oscillator. Also enable TWL watchdog before switching the osc
|
||||
+ * to recover if the VDD1/VDD2 stop working.
|
||||
+ */
|
||||
+static void twl_erratum27_workaround(void)
|
||||
+{
|
||||
+ u8 wdt_counter_val = 0;
|
||||
+ int err;
|
||||
+
|
||||
+ /* Setup the twl wdt to take care of borderline failure case */
|
||||
+ err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &wdt_counter_val,
|
||||
+ R_WDT_CFG);
|
||||
+ err |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, WDT_WRK_TIMEOUT,
|
||||
+ R_WDT_CFG);
|
||||
+
|
||||
+ /* TWL DCDC switching to HFCLK */
|
||||
+ err |= twl_dcdc_use_hfclk();
|
||||
+
|
||||
+ /* restore the original value */
|
||||
+ err |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, wdt_counter_val,
|
||||
+ R_WDT_CFG);
|
||||
+ if (err)
|
||||
+ pr_warning("TWL4030: workaround setup failed!\n");
|
||||
+}
|
||||
+
|
||||
+static bool is_twl5030_erratum27wa_required(void)
|
||||
+{
|
||||
+ if (twl_get_type() == TWL_SIL_5030)
|
||||
+ return (twl_get_version() < TWL5030_REV_1_2);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
|
||||
{
|
||||
int err = 0;
|
||||
@@ -530,6 +599,16 @@ int twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
|
||||
TWL4030_PM_MASTER_PROTECT_KEY);
|
||||
if (err)
|
||||
goto unlock;
|
||||
+
|
||||
+ /* Applying TWL5030 Erratum 27 WA based on Si revision &
|
||||
+ * flag updated from board file*/
|
||||
+ if (is_twl5030_erratum27wa_required()) {
|
||||
+ pr_info("TWL5030: Enabling workaround for Si Erratum 27\n");
|
||||
+ twl_erratum27_workaround();
|
||||
+ if (twl4030_scripts->twl5030_erratum27wa_script)
|
||||
+ twl4030_scripts->twl5030_erratum27wa_script();
|
||||
+ }
|
||||
+
|
||||
for (i = 0; i < twl4030_scripts->num; i++) {
|
||||
err = load_twl4030_script(twl4030_scripts->scripts[i], address);
|
||||
if (err)
|
||||
diff --git a/drivers/mfd/twl4030-script-omap.c b/drivers/mfd/twl4030-script-omap.c
|
||||
index 867a442..ff93fd2 100644
|
||||
--- a/drivers/mfd/twl4030-script-omap.c
|
||||
+++ b/drivers/mfd/twl4030-script-omap.c
|
||||
@@ -326,10 +326,160 @@ static struct twl4030_resconfig twl4030_rconfig[] __initdata = {
|
||||
{ 0, 0},
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * Sleep and active sequences with changes for TWL5030 Erratum 27 workaround
|
||||
+ *
|
||||
+ * Sysoff (using sys_off signal):
|
||||
+ * When SYS_CLKREQ goes low during retention no resources will be affected
|
||||
+ * since no resources are assigned to P3 only.
|
||||
+ *
|
||||
+ * Since all resources are assigned to P1 and P3 then all resources
|
||||
+ * will be affected on the falling edge of P3 (SYS_CLKREQ).
|
||||
+ * When OMAP lower the SYS_CLKREQ signal PMIC will execute the
|
||||
+ * A2S sequence in which HFCLKOUT is dissabled first and
|
||||
+ * after 488.32 usec(PRM_VOLTOFFSET) resources assigned to P1 and P3
|
||||
+ * and of TYPE2=1 are put to sleep
|
||||
+ * (VDD1, VDD2, VPLL1, REGEN, NRESPWRON & SYSEN).
|
||||
+ * Again after a 61.04 usec resources assigned to P1 and P3
|
||||
+ * and of TYPE2=2 are put to sleep
|
||||
+ * (VINTANA1, VINTANA2, VINTDIG, VIO & CLKEN).
|
||||
+ *
|
||||
+ * On wakeup event OMAP goes active and pulls the SYS_CLKREQ high,
|
||||
+ * and will execute the S2A sequence which is same for P1_P2 & P3.
|
||||
+ * This will turn on all resources of TYPE2=2 to go to the active state.
|
||||
+ * Three dummy broadcast messages are added to get a delay of ~10 ms
|
||||
+ * before enabling the HFCLKOUT resource. And after a 30.52 usec
|
||||
+ * all resources of TYPE2=1 are put to the active state.
|
||||
+ *
|
||||
+ * This 10ms delay can be reduced if the oscillator is having less
|
||||
+ * stabilization time. A should be taken care if it needs more time
|
||||
+ * for stabilization.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+/**
|
||||
+ * DOC: Sleep to Active sequence for P1/P2/P3
|
||||
+ *
|
||||
+ * The wakeup sequence is adjusted to do the VDD1/VDD2 voltage ramp-up
|
||||
+ * only after HFCLKIN is stabilized and the HFCLKOUT is enabled.
|
||||
+ */
|
||||
+static struct twl4030_ins wakeup_seq_erratum27[] __initdata = {
|
||||
+ /*
|
||||
+ * Broadcast message to put res(TYPE2 = 2) to active.
|
||||
+ * Wait for ~10 mS (ramp-up time for OSC on the board)
|
||||
+ * after HFCLKIN is enabled
|
||||
+ */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
|
||||
+ RES_STATE_ACTIVE), 55},
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
|
||||
+ RES_STATE_ACTIVE), 55},
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
|
||||
+ RES_STATE_ACTIVE), 54},
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
|
||||
+ RES_STATE_ACTIVE), 1},
|
||||
+ /* Singular message to enable HCLKOUT after HFCLKIN is stabilized */
|
||||
+ {MSG_SINGULAR(DEV_GRP_NULL, RES_HFCLKOUT, RES_STATE_ACTIVE), 1},
|
||||
+ /*
|
||||
+ * Broadcast message to put res(TYPE2 = 1) to active.
|
||||
+ * VDD1/VDD2 ramp-up after HFCLKIN is stable and HFCLKOUT is enabled.
|
||||
+ */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1,
|
||||
+ RES_STATE_ACTIVE), 2},
|
||||
+};
|
||||
+
|
||||
+static struct twl4030_script wakeup_script_erratum27 __initdata = {
|
||||
+ .script = wakeup_seq_erratum27,
|
||||
+ .size = ARRAY_SIZE(wakeup_seq_erratum27),
|
||||
+ .flags = TWL4030_WAKEUP12_SCRIPT | TWL4030_WAKEUP3_SCRIPT,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * DOC: Active to Sleep sequence for P1/P2/P3
|
||||
+ *
|
||||
+ * The sleep sequence is adjusted to do the switching of VDD1/VDD2/VIO OSC from
|
||||
+ * HFCLKIN to internal oscillator when the HFCLKIN is stable.
|
||||
+ */
|
||||
+static struct twl4030_ins sleep_on_seq_erratum27[] __initdata = {
|
||||
+ /*
|
||||
+ * Singular message to disable HCLKOUT.
|
||||
+ * Wait for ~488.32 uS to do the switching of VDD1/VDD2/VIO OSC from
|
||||
+ * HFCLKIN to internal oscillator before disabling HFCLKIN.
|
||||
+ */
|
||||
+ {MSG_SINGULAR(DEV_GRP_NULL, RES_HFCLKOUT, RES_STATE_SLEEP), 20},
|
||||
+ /* Broadcast message to put res(TYPE2 = 1) to sleep */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1,
|
||||
+ RES_STATE_SLEEP), 2},
|
||||
+ /* Broadcast message to put res(TYPE2 = 2) to sleep, disable HFCLKIN */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
|
||||
+ RES_STATE_SLEEP), 2},
|
||||
+};
|
||||
+
|
||||
+static struct twl4030_script sleep_on_script_erratum27 __initdata = {
|
||||
+ .script = sleep_on_seq_erratum27,
|
||||
+ .size = ARRAY_SIZE(sleep_on_seq_erratum27),
|
||||
+ .flags = TWL4030_SLEEP_SCRIPT,
|
||||
+};
|
||||
+
|
||||
+/* TWL4030 script for sleep, wakeup & warm_reset */
|
||||
+static struct twl4030_script *twl4030_scripts_erratum27[] __initdata = {
|
||||
+ &wakeup_script_erratum27,
|
||||
+ &sleep_on_script_erratum27,
|
||||
+ &wrst_script,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * DOC: TWL4030 resource configuration
|
||||
+ *
|
||||
+ * VDD1/VDD2/VPLL are assigned to P1 and P3, to have better control
|
||||
+ * during OFFMODE. HFCLKOUT is assigned to P1 and P3 (*p2) to turn off
|
||||
+ * only during OFFMODE.
|
||||
+ * (*P2 is included if the platform uses it for modem/some other processor)
|
||||
+ */
|
||||
+static struct twl4030_resconfig twl4030_rconfig_erratum27[] __initdata = {
|
||||
+ { .resource = RES_VPLL1, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
|
||||
+ .type = 3, .type2 = 1, .remap_sleep = RES_STATE_OFF },
|
||||
+ { .resource = RES_VINTANA1, .devgroup = DEV_GRP_ALL, .type = 1,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_VINTANA2, .devgroup = DEV_GRP_ALL, .type = 0,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_VINTDIG, .devgroup = DEV_GRP_ALL, .type = 1,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_VIO, .devgroup = DEV_GRP_ALL, .type = 2,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_VDD1, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
|
||||
+ .type = 4, .type2 = 1, .remap_sleep = RES_STATE_OFF },
|
||||
+ { .resource = RES_VDD2, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
|
||||
+ .type = 3, .type2 = 1, .remap_sleep = RES_STATE_OFF },
|
||||
+ { .resource = RES_REGEN, .devgroup = DEV_GRP_ALL, .type = 2,
|
||||
+ .type2 = 1, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_NRES_PWRON, .devgroup = DEV_GRP_ALL, .type = 0,
|
||||
+ .type2 = 1, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_CLKEN, .devgroup = DEV_GRP_ALL, .type = 3,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_SYSEN, .devgroup = DEV_GRP_ALL, .type = 6,
|
||||
+ .type2 = 1, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_HFCLKOUT, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
|
||||
+ .type = 0, .type2 = 1, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { 0, 0},
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * twl5030_script_erratum27() - API to modify TWL4030 script
|
||||
+ *
|
||||
+ * Updating the TWL4030 script & resource configuration
|
||||
+ */
|
||||
+static void __init twl5030_script_erratum27(void)
|
||||
+{
|
||||
+ twl4030_generic_script.scripts = twl4030_scripts_erratum27;
|
||||
+ twl4030_generic_script.num = ARRAY_SIZE(twl4030_scripts_erratum27);
|
||||
+ twl4030_generic_script.resource_config = twl4030_rconfig_erratum27;
|
||||
+}
|
||||
+
|
||||
struct twl4030_power_data twl4030_generic_script __initdata = {
|
||||
.scripts = twl4030_scripts,
|
||||
.num = ARRAY_SIZE(twl4030_scripts),
|
||||
.resource_config = twl4030_rconfig,
|
||||
+ .twl5030_erratum27wa_script = twl5030_script_erratum27,
|
||||
};
|
||||
|
||||
static int __init twl4030_script_probe(struct platform_device *pdev)
|
||||
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
|
||||
index 23ec058..10cb6e2 100644
|
||||
--- a/include/linux/i2c/twl.h
|
||||
+++ b/include/linux/i2c/twl.h
|
||||
@@ -681,6 +681,7 @@ struct twl4030_power_data {
|
||||
struct twl4030_script **scripts;
|
||||
unsigned num;
|
||||
struct twl4030_resconfig *resource_config;
|
||||
+ void (*twl5030_erratum27wa_script)(void);
|
||||
#define TWL4030_RESCONFIG_UNDEF ((u8)-1)
|
||||
};
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
From bf171753a162d07753208c6bcfae8ca1e5c94af3 Mon Sep 17 00:00:00 2001
|
||||
From: Lesly A M <leslyam@ti.com>
|
||||
Date: Wed, 1 Jun 2011 14:57:05 -0700
|
||||
Subject: [PATCH 13/13] MFD: TWL4030: optimizing resource configuration
|
||||
|
||||
Skip the i2c register writes in twl4030_configure_resource() if the new value
|
||||
is same as the old value, for devgrp/type/remap regs.
|
||||
|
||||
Suggested by David Derrick <dderrick@ti.com>
|
||||
|
||||
Signed-off-by: Lesly A M <leslyam@ti.com>
|
||||
Cc: Nishanth Menon <nm@ti.com>
|
||||
Cc: David Derrick <dderrick@ti.com>
|
||||
Cc: Samuel Ortiz <sameo@linux.intel.com>
|
||||
---
|
||||
drivers/mfd/twl4030-power.c | 126 ++++++++++++++++++++++++------------------
|
||||
1 files changed, 72 insertions(+), 54 deletions(-)
|
||||
|
||||
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
|
||||
index 8af3fe3..d82632f 100644
|
||||
--- a/drivers/mfd/twl4030-power.c
|
||||
+++ b/drivers/mfd/twl4030-power.c
|
||||
@@ -335,9 +335,9 @@ static int twl4030_configure_resource(struct twl4030_resconfig *rconfig)
|
||||
{
|
||||
int rconfig_addr;
|
||||
int err;
|
||||
- u8 type;
|
||||
- u8 grp;
|
||||
- u8 remap;
|
||||
+ u8 type, type_value;
|
||||
+ u8 grp, grp_value;
|
||||
+ u8 remap, remap_value;
|
||||
|
||||
if (rconfig->resource > TOTAL_RESOURCES) {
|
||||
pr_err("TWL4030 Resource %d does not exist\n",
|
||||
@@ -348,76 +348,94 @@ static int twl4030_configure_resource(struct twl4030_resconfig *rconfig)
|
||||
rconfig_addr = res_config_addrs[rconfig->resource];
|
||||
|
||||
/* Set resource group */
|
||||
- err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &grp,
|
||||
+ if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) {
|
||||
+ err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &grp,
|
||||
rconfig_addr + DEV_GRP_OFFSET);
|
||||
- if (err) {
|
||||
- pr_err("TWL4030 Resource %d group could not be read\n",
|
||||
- rconfig->resource);
|
||||
- return err;
|
||||
- }
|
||||
+ if (err) {
|
||||
+ pr_err("TWL4030 Resource %d group could not be read\n",
|
||||
+ rconfig->resource);
|
||||
+ return err;
|
||||
+ }
|
||||
|
||||
- if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) {
|
||||
- grp &= ~DEV_GRP_MASK;
|
||||
- grp |= rconfig->devgroup << DEV_GRP_SHIFT;
|
||||
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
|
||||
+ grp_value = (grp & DEV_GRP_MASK) >> DEV_GRP_SHIFT;
|
||||
+
|
||||
+ if (rconfig->devgroup != grp_value) {
|
||||
+ grp &= ~DEV_GRP_MASK;
|
||||
+ grp |= rconfig->devgroup << DEV_GRP_SHIFT;
|
||||
+ err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
|
||||
grp, rconfig_addr + DEV_GRP_OFFSET);
|
||||
- if (err < 0) {
|
||||
- pr_err("TWL4030 failed to program devgroup\n");
|
||||
- return err;
|
||||
+ if (err < 0) {
|
||||
+ pr_err("TWL4030 failed to program devgroup\n");
|
||||
+ return err;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
/* Set resource types */
|
||||
- err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &type,
|
||||
+ if ((rconfig->type != TWL4030_RESCONFIG_UNDEF) ||
|
||||
+ (rconfig->type2 != TWL4030_RESCONFIG_UNDEF)) {
|
||||
+
|
||||
+ err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &type,
|
||||
rconfig_addr + TYPE_OFFSET);
|
||||
- if (err < 0) {
|
||||
- pr_err("TWL4030 Resource %d type could not be read\n",
|
||||
- rconfig->resource);
|
||||
- return err;
|
||||
- }
|
||||
+ if (err < 0) {
|
||||
+ pr_err("TWL4030 Resource %d type could not be read\n",
|
||||
+ rconfig->resource);
|
||||
+ return err;
|
||||
+ }
|
||||
|
||||
- if (rconfig->type != TWL4030_RESCONFIG_UNDEF) {
|
||||
- type &= ~TYPE_MASK;
|
||||
- type |= rconfig->type << TYPE_SHIFT;
|
||||
- }
|
||||
+ type_value = type;
|
||||
|
||||
- if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) {
|
||||
- type &= ~TYPE2_MASK;
|
||||
- type |= rconfig->type2 << TYPE2_SHIFT;
|
||||
- }
|
||||
+ if (rconfig->type != TWL4030_RESCONFIG_UNDEF) {
|
||||
+ type &= ~TYPE_MASK;
|
||||
+ type |= rconfig->type << TYPE_SHIFT;
|
||||
+ }
|
||||
|
||||
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
|
||||
+ if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) {
|
||||
+ type &= ~TYPE2_MASK;
|
||||
+ type |= rconfig->type2 << TYPE2_SHIFT;
|
||||
+ }
|
||||
+
|
||||
+ if (type != type_value) {
|
||||
+ err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
|
||||
type, rconfig_addr + TYPE_OFFSET);
|
||||
- if (err < 0) {
|
||||
- pr_err("TWL4030 failed to program resource type\n");
|
||||
- return err;
|
||||
+ if (err < 0) {
|
||||
+ pr_err("TWL4030 failed to program resource type\n");
|
||||
+ return err;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Set remap states */
|
||||
- err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &remap,
|
||||
+ if ((rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) ||
|
||||
+ (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF)) {
|
||||
+ err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &remap,
|
||||
rconfig_addr + REMAP_OFFSET);
|
||||
- if (err < 0) {
|
||||
- pr_err("TWL4030 Resource %d remap could not be read\n",
|
||||
- rconfig->resource);
|
||||
- return err;
|
||||
- }
|
||||
+ if (err < 0) {
|
||||
+ pr_err("TWL4030 Resource %d remap could not be read\n",
|
||||
+ rconfig->resource);
|
||||
+ return err;
|
||||
+ }
|
||||
|
||||
- if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) {
|
||||
- remap &= ~OFF_STATE_MASK;
|
||||
- remap |= rconfig->remap_off << OFF_STATE_SHIFT;
|
||||
- }
|
||||
+ remap_value = remap;
|
||||
|
||||
- if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) {
|
||||
- remap &= ~SLEEP_STATE_MASK;
|
||||
- remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT;
|
||||
- }
|
||||
+ if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) {
|
||||
+ remap &= ~OFF_STATE_MASK;
|
||||
+ remap |= rconfig->remap_off << OFF_STATE_SHIFT;
|
||||
+ }
|
||||
|
||||
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
|
||||
- remap,
|
||||
- rconfig_addr + REMAP_OFFSET);
|
||||
- if (err < 0) {
|
||||
- pr_err("TWL4030 failed to program remap\n");
|
||||
- return err;
|
||||
+ if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) {
|
||||
+ remap &= ~SLEEP_STATE_MASK;
|
||||
+ remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT;
|
||||
+ }
|
||||
+
|
||||
+ if (remap != remap_value) {
|
||||
+ err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
|
||||
+ remap, rconfig_addr + REMAP_OFFSET);
|
||||
+ if (err < 0) {
|
||||
+ pr_err("TWL4030 failed to program remap\n");
|
||||
+ return err;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
return 0;
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
From 2adb339e4988632379971febe5696f21d05c71f2 Mon Sep 17 00:00:00 2001
|
||||
From: Anand Gadiyar <gadiyar@ti.com>
|
||||
Date: Tue, 19 Jul 2011 01:52:14 -0700
|
||||
Subject: [PATCH] usb: musb: Enable DMA mode1 RX for USB-Mass-Storage
|
||||
|
||||
This patch enables the DMA mode1 RX support.
|
||||
This feature is enabled based on the short_not_ok flag passed from
|
||||
gadget drivers.
|
||||
|
||||
This will result in a thruput performance gain of around
|
||||
40% for USB mass-storage/mtp use cases.
|
||||
|
||||
Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
|
||||
Signed-off-by: Moiz Sonasath <m-sonasath@ti.com>
|
||||
Tested-by: Vikram Pandita <vikram.pandita@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
drivers/usb/musb/musb_gadget.c | 68 ++++++++++++++++++++++++---------------
|
||||
1 files changed, 42 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
|
||||
index f47c201..ca32c63 100644
|
||||
--- a/drivers/usb/musb/musb_gadget.c
|
||||
+++ b/drivers/usb/musb/musb_gadget.c
|
||||
@@ -630,6 +630,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
|
||||
u16 len;
|
||||
u16 csr = musb_readw(epio, MUSB_RXCSR);
|
||||
struct musb_hw_ep *hw_ep = &musb->endpoints[epnum];
|
||||
+ u8 use_mode_1;
|
||||
|
||||
if (hw_ep->is_shared_fifo)
|
||||
musb_ep = &hw_ep->ep_in;
|
||||
@@ -679,6 +680,18 @@ static void rxstate(struct musb *musb, struct musb_request *req)
|
||||
|
||||
if (csr & MUSB_RXCSR_RXPKTRDY) {
|
||||
len = musb_readw(epio, MUSB_RXCOUNT);
|
||||
+
|
||||
+ /*
|
||||
+ * Enable Mode 1 for RX transfers only for mass-storage
|
||||
+ * use-case, based on short_not_ok flag which is set only
|
||||
+ * from file_storage and f_mass_storage drivers
|
||||
+ */
|
||||
+
|
||||
+ if (request->short_not_ok && len == musb_ep->packet_sz)
|
||||
+ use_mode_1 = 1;
|
||||
+ else
|
||||
+ use_mode_1 = 0;
|
||||
+
|
||||
if (request->actual < request->length) {
|
||||
#ifdef CONFIG_USB_INVENTRA_DMA
|
||||
if (is_buffer_mapped(req)) {
|
||||
@@ -710,37 +723,40 @@ static void rxstate(struct musb *musb, struct musb_request *req)
|
||||
* then becomes usable as a runtime "use mode 1" hint...
|
||||
*/
|
||||
|
||||
- csr |= MUSB_RXCSR_DMAENAB;
|
||||
-#ifdef USE_MODE1
|
||||
- csr |= MUSB_RXCSR_AUTOCLEAR;
|
||||
- /* csr |= MUSB_RXCSR_DMAMODE; */
|
||||
-
|
||||
- /* this special sequence (enabling and then
|
||||
- * disabling MUSB_RXCSR_DMAMODE) is required
|
||||
- * to get DMAReq to activate
|
||||
- */
|
||||
- musb_writew(epio, MUSB_RXCSR,
|
||||
- csr | MUSB_RXCSR_DMAMODE);
|
||||
-#else
|
||||
- if (!musb_ep->hb_mult &&
|
||||
- musb_ep->hw_ep->rx_double_buffered)
|
||||
+ /* Experimental: Mode1 works with mass storage use cases */
|
||||
+ if (use_mode_1) {
|
||||
csr |= MUSB_RXCSR_AUTOCLEAR;
|
||||
-#endif
|
||||
- musb_writew(epio, MUSB_RXCSR, csr);
|
||||
+ musb_writew(epio, MUSB_RXCSR, csr);
|
||||
+ csr |= MUSB_RXCSR_DMAENAB;
|
||||
+ musb_writew(epio, MUSB_RXCSR, csr);
|
||||
+
|
||||
+ /* this special sequence (enabling and then
|
||||
+ * disabling MUSB_RXCSR_DMAMODE) is required
|
||||
+ * to get DMAReq to activate
|
||||
+ */
|
||||
+ musb_writew(epio, MUSB_RXCSR,
|
||||
+ csr | MUSB_RXCSR_DMAMODE);
|
||||
+ musb_writew(epio, MUSB_RXCSR, csr);
|
||||
+
|
||||
+ } else {
|
||||
+ if (!musb_ep->hb_mult &&
|
||||
+ musb_ep->hw_ep->rx_double_buffered)
|
||||
+ csr |= MUSB_RXCSR_AUTOCLEAR;
|
||||
+ csr |= MUSB_RXCSR_DMAENAB;
|
||||
+ musb_writew(epio, MUSB_RXCSR, csr);
|
||||
+ }
|
||||
|
||||
if (request->actual < request->length) {
|
||||
int transfer_size = 0;
|
||||
-#ifdef USE_MODE1
|
||||
- transfer_size = min(request->length - request->actual,
|
||||
- channel->max_len);
|
||||
-#else
|
||||
- transfer_size = min(request->length - request->actual,
|
||||
- (unsigned)len);
|
||||
-#endif
|
||||
- if (transfer_size <= musb_ep->packet_sz)
|
||||
- musb_ep->dma->desired_mode = 0;
|
||||
- else
|
||||
+ if (use_mode_1) {
|
||||
+ transfer_size = min(request->length - request->actual,
|
||||
+ channel->max_len);
|
||||
musb_ep->dma->desired_mode = 1;
|
||||
+ } else {
|
||||
+ transfer_size = min(request->length - request->actual,
|
||||
+ (unsigned)len);
|
||||
+ musb_ep->dma->desired_mode = 0;
|
||||
+ }
|
||||
|
||||
use_dma = c->channel_program(
|
||||
channel,
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
|
||||
index c541093..c4744e1 100644
|
||||
--- a/fs/nfs/nfsroot.c
|
||||
+++ b/fs/nfs/nfsroot.c
|
||||
@@ -87,7 +87,7 @@
|
||||
#define NFS_ROOT "/tftpboot/%s"
|
||||
|
||||
/* Default NFSROOT mount options. */
|
||||
-#define NFS_DEF_OPTIONS "udp"
|
||||
+#define NFS_DEF_OPTIONS "vers=2,udp,rsize=4096,wsize=4096"
|
||||
|
||||
/* Parameters passed from the kernel command line */
|
||||
static char nfs_root_parms[256] __initdata = "";
|
||||
@@ -0,0 +1,38 @@
|
||||
From 38dd5aadc86725f6018d23679e9daa60ca0a8319 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Thu, 12 May 2011 07:59:52 -0500
|
||||
Subject: [PATCH 1/6] OMAP2+: cpufreq: free up table on exit
|
||||
|
||||
freq_table allocated by opp_init_cpufreq_table in omap_cpu_init
|
||||
needs to be freed in omap_cpu_exit.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 3 +++
|
||||
1 files changed, 3 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index d53ce23..e38ebb8 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/opp.h>
|
||||
+#include <linux/slab.h>
|
||||
#include <linux/cpu.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
@@ -216,6 +217,8 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
static int omap_cpu_exit(struct cpufreq_policy *policy)
|
||||
{
|
||||
clk_exit_cpufreq_table(&freq_table);
|
||||
+ kfree(freq_table);
|
||||
+ freq_table = NULL;
|
||||
clk_put(mpu_clk);
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
From 5febdc0482e545c2a598f035c5e03931e0c3c808 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Thu, 12 May 2011 08:14:41 -0500
|
||||
Subject: [PATCH 2/6] OMAP2+: cpufreq: handle invalid cpufreq table
|
||||
|
||||
Handle the case when cpufreq_frequency_table_cpuinfo fails. freq_table
|
||||
that we passed failed the internal test of cpufreq generic driver,
|
||||
so we should'nt be using the freq_table as such. Instead, warn and
|
||||
fallback to clock functions for validation and operation.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 12 ++++++++++--
|
||||
1 files changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index e38ebb8..6e3666a 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -182,10 +182,18 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
|
||||
if (freq_table) {
|
||||
result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
- if (!result)
|
||||
+ if (!result) {
|
||||
cpufreq_frequency_table_get_attr(freq_table,
|
||||
policy->cpu);
|
||||
- } else {
|
||||
+ } else {
|
||||
+ WARN(true, "%s: fallback to clk_round(freq_table=%d)\n",
|
||||
+ __func__, result);
|
||||
+ kfree(freq_table);
|
||||
+ freq_table = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!freq_table) {
|
||||
policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
|
||||
policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
|
||||
VERY_HI_RATE) / 1000;
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
From aef7e862873e6125159a18d22a2e37b1fbab2153 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Thu, 12 May 2011 16:27:45 -0700
|
||||
Subject: [PATCH 3/6] OMAP2+: cpufreq: minor comment cleanup
|
||||
|
||||
this should probably get squashed in..
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 6 ++++--
|
||||
1 files changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index 6e3666a..45f1e9e 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -84,8 +84,10 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
if (is_smp() && (num_online_cpus() < NR_CPUS))
|
||||
return ret;
|
||||
|
||||
- /* Ensure desired rate is within allowed range. Some govenors
|
||||
- * (ondemand) will just pass target_freq=0 to get the minimum. */
|
||||
+ /*
|
||||
+ * Ensure desired rate is within allowed range. Some govenors
|
||||
+ * (ondemand) will just pass target_freq=0 to get the minimum.
|
||||
+ */
|
||||
if (target_freq < policy->min)
|
||||
target_freq = policy->min;
|
||||
if (target_freq > policy->max)
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
From f231980dbd0f05229f2020e59b7242872576416f Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Fri, 13 May 2011 05:34:35 -0700
|
||||
Subject: [PATCH 4/6] OMAP2: cpufreq: use clk_init_cpufreq_table if OPPs not available
|
||||
|
||||
OMAP2 does not use OPP tables at the moment for DVFS. Currently,
|
||||
we depend on opp table initialization to give us the freq_table,
|
||||
which makes sense for OMAP3+. for OMAP2, we should be using
|
||||
clk_init_cpufreq_table - so if the opp based frequency table
|
||||
initilization fails, fall back to clk_init_cpufreq_table to give
|
||||
us the table.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 9 ++++++++-
|
||||
1 files changed, 8 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index 45f1e9e..854f4b3 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -180,7 +180,13 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
pr_warning("%s: unable to get the mpu device\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
- opp_init_cpufreq_table(mpu_dev, &freq_table);
|
||||
+
|
||||
+ /*
|
||||
+ * if we dont get cpufreq table using opp, use traditional omap2 lookup
|
||||
+ * as a fallback
|
||||
+ */
|
||||
+ if (opp_init_cpufreq_table(mpu_dev, &freq_table))
|
||||
+ clk_init_cpufreq_table(&freq_table);
|
||||
|
||||
if (freq_table) {
|
||||
result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
@@ -188,6 +194,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
cpufreq_frequency_table_get_attr(freq_table,
|
||||
policy->cpu);
|
||||
} else {
|
||||
+ clk_exit_cpufreq_table(&freq_table);
|
||||
WARN(true, "%s: fallback to clk_round(freq_table=%d)\n",
|
||||
__func__, result);
|
||||
kfree(freq_table);
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
From 272d76bcb22b9509ccc1b59d3a62e3930d902d17 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Fri, 13 May 2011 05:43:49 -0700
|
||||
Subject: [PATCH 5/6] OMAP2+: cpufreq: use cpufreq_frequency_table_target
|
||||
|
||||
Use cpufreq_frequency_table_target for finding the proper target
|
||||
instead of seeing if the frequency requested is divisible alone.
|
||||
if we have a frequency table, we should restrict ourselves to
|
||||
selecting the "approved" frequencies alone and only in the case
|
||||
where the frequency table is not available should we attempt at
|
||||
closest roundable clock frequency.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 38 ++++++++++++++++++++++--------
|
||||
1 files changed, 28 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index 854f4b3..d0b4f97 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -77,24 +77,42 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
{
|
||||
- int i, ret = 0;
|
||||
+ unsigned int i;
|
||||
+ int ret = 0;
|
||||
struct cpufreq_freqs freqs;
|
||||
|
||||
/* Changes not allowed until all CPUs are online */
|
||||
if (is_smp() && (num_online_cpus() < NR_CPUS))
|
||||
return ret;
|
||||
|
||||
- /*
|
||||
- * Ensure desired rate is within allowed range. Some govenors
|
||||
- * (ondemand) will just pass target_freq=0 to get the minimum.
|
||||
- */
|
||||
- if (target_freq < policy->min)
|
||||
- target_freq = policy->min;
|
||||
- if (target_freq > policy->max)
|
||||
- target_freq = policy->max;
|
||||
+ if (freq_table) {
|
||||
+ ret = cpufreq_frequency_table_target(policy, freq_table,
|
||||
+ target_freq, relation, &i);
|
||||
+ if (ret) {
|
||||
+ pr_debug("%s: cpu%d: no freq match for %d(ret=%d)\n",
|
||||
+ __func__, policy->cpu, target_freq, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ freqs.new = freq_table[i].frequency;
|
||||
+ } else {
|
||||
+ /*
|
||||
+ * Ensure desired rate is within allowed range. Some govenors
|
||||
+ * (ondemand) will just pass target_freq=0 to get the minimum.
|
||||
+ */
|
||||
+ if (target_freq < policy->min)
|
||||
+ target_freq = policy->min;
|
||||
+ if (target_freq > policy->max)
|
||||
+ target_freq = policy->max;
|
||||
+
|
||||
+ freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
|
||||
+ }
|
||||
+ if (!freqs.new) {
|
||||
+ pr_err("%s: cpu%d: no match for freq %d\n", __func__,
|
||||
+ policy->cpu, target_freq);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
freqs.old = omap_getspeed(policy->cpu);
|
||||
- freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
|
||||
freqs.cpu = policy->cpu;
|
||||
|
||||
if (freqs.old == freqs.new)
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
From 42a384af80e07534913d9002ec8d9caf5d4d305c Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Wed, 18 May 2011 01:48:23 -0500
|
||||
Subject: [PATCH 6/6] OMAP2+: cpufreq: fix freq_table leak
|
||||
|
||||
Since we have two cpus the cpuinit call for cpu1 causes
|
||||
freq_table of cpu0 to be overwritten. instead, we maintain
|
||||
a counter to keep track of cpus who use the cpufreq table
|
||||
allocate it once(one freq table for all CPUs) and free them
|
||||
once the last user is done with it.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 33 ++++++++++++++++++++++++------
|
||||
1 files changed, 26 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index d0b4f97..fc3d0fb 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -42,6 +42,9 @@
|
||||
#define VERY_HI_RATE 900000000
|
||||
|
||||
static struct cpufreq_frequency_table *freq_table;
|
||||
+static int freq_table_users;
|
||||
+static DEFINE_MUTEX(freq_table_lock);
|
||||
+
|
||||
static struct clk *mpu_clk;
|
||||
|
||||
static int omap_verify_speed(struct cpufreq_policy *policy)
|
||||
@@ -172,6 +175,18 @@ skip_lpj:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static void freq_table_free(void)
|
||||
+{
|
||||
+ if (!freq_table_users)
|
||||
+ return;
|
||||
+ freq_table_users--;
|
||||
+ if (freq_table_users)
|
||||
+ return;
|
||||
+ clk_exit_cpufreq_table(&freq_table);
|
||||
+ kfree(freq_table);
|
||||
+ freq_table = NULL;
|
||||
+}
|
||||
+
|
||||
static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
int result = 0;
|
||||
@@ -199,14 +214,18 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+ mutex_lock(&freq_table_lock);
|
||||
/*
|
||||
* if we dont get cpufreq table using opp, use traditional omap2 lookup
|
||||
* as a fallback
|
||||
*/
|
||||
- if (opp_init_cpufreq_table(mpu_dev, &freq_table))
|
||||
- clk_init_cpufreq_table(&freq_table);
|
||||
+ if (!freq_table) {
|
||||
+ if (opp_init_cpufreq_table(mpu_dev, &freq_table))
|
||||
+ clk_init_cpufreq_table(&freq_table);
|
||||
+ }
|
||||
|
||||
if (freq_table) {
|
||||
+ freq_table_users++;
|
||||
result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
if (!result) {
|
||||
cpufreq_frequency_table_get_attr(freq_table,
|
||||
@@ -215,10 +234,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
clk_exit_cpufreq_table(&freq_table);
|
||||
WARN(true, "%s: fallback to clk_round(freq_table=%d)\n",
|
||||
__func__, result);
|
||||
- kfree(freq_table);
|
||||
- freq_table = NULL;
|
||||
+ freq_table_free();
|
||||
}
|
||||
}
|
||||
+ mutex_unlock(&freq_table_lock);
|
||||
|
||||
if (!freq_table) {
|
||||
policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
|
||||
@@ -251,9 +270,9 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
|
||||
static int omap_cpu_exit(struct cpufreq_policy *policy)
|
||||
{
|
||||
- clk_exit_cpufreq_table(&freq_table);
|
||||
- kfree(freq_table);
|
||||
- freq_table = NULL;
|
||||
+ mutex_lock(&freq_table_lock);
|
||||
+ freq_table_free();
|
||||
+ mutex_unlock(&freq_table_lock);
|
||||
clk_put(mpu_clk);
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
From 8726f3a7218b72a1003904a24bb000b3e4f9b4d1 Mon Sep 17 00:00:00 2001
|
||||
From: Mike Turquette <mturquette@ti.com>
|
||||
Date: Tue, 17 May 2011 09:35:54 -0500
|
||||
Subject: [PATCH 1/2] cpufreq: helpers for walking the frequency table
|
||||
|
||||
Two new functions for getting the next higher and next lower frequencies
|
||||
in the cpufreq table, based upon a frequency supplied in kHz.
|
||||
|
||||
This is useful for cpufreq governors that do not target frequencies
|
||||
based upon a percentage or a pre-determined value, but instead access
|
||||
the cpufreq table directly.
|
||||
|
||||
Signed-off-by: Mike Turquette <mturquette@ti.com>
|
||||
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
drivers/cpufreq/freq_table.c | 73 ++++++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/cpufreq.h | 9 +++++
|
||||
2 files changed, 82 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
|
||||
index 0543221..11a307b 100644
|
||||
--- a/drivers/cpufreq/freq_table.c
|
||||
+++ b/drivers/cpufreq/freq_table.c
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/cpufreq.h>
|
||||
+#include <linux/err.h>
|
||||
|
||||
#define dprintk(msg...) \
|
||||
cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "freq-table", msg)
|
||||
@@ -174,6 +175,78 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
|
||||
|
||||
+int cpufreq_frequency_table_next_lowest(struct cpufreq_policy *policy,
|
||||
+ struct cpufreq_frequency_table *table, int *index)
|
||||
+{
|
||||
+ unsigned int cur_freq;
|
||||
+ unsigned int next_lowest_freq;
|
||||
+ int optimal_index = -1;
|
||||
+ int i = 0;
|
||||
+
|
||||
+ if (!policy || IS_ERR(policy) || !table || IS_ERR(table) ||
|
||||
+ !index || IS_ERR(index))
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ cur_freq = policy->cur;
|
||||
+ next_lowest_freq = policy->min;
|
||||
+
|
||||
+ /* we're at the lowest frequency in the table already, bail out */
|
||||
+ if (cur_freq == policy->min)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* walk the list, find closest freq to cur_freq that is below it */
|
||||
+ while(table[i].frequency != CPUFREQ_TABLE_END) {
|
||||
+ if (table[i].frequency < cur_freq &&
|
||||
+ table[i].frequency >= next_lowest_freq) {
|
||||
+ next_lowest_freq = table[i].frequency;
|
||||
+ optimal_index = table[i].index;
|
||||
+ }
|
||||
+
|
||||
+ i++;
|
||||
+ }
|
||||
+
|
||||
+ *index = optimal_index;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_next_lowest);
|
||||
+
|
||||
+int cpufreq_frequency_table_next_highest(struct cpufreq_policy *policy,
|
||||
+ struct cpufreq_frequency_table *table, int *index)
|
||||
+{
|
||||
+ unsigned int cur_freq;
|
||||
+ unsigned int next_higher_freq;
|
||||
+ int optimal_index = -1;
|
||||
+ int i = 0;
|
||||
+
|
||||
+ if (!policy || IS_ERR(policy) || !table || IS_ERR(table) ||
|
||||
+ !index || IS_ERR(index))
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ cur_freq = policy->cur;
|
||||
+ next_higher_freq = policy->max;
|
||||
+
|
||||
+ /* we're at the highest frequency in the table already, bail out */
|
||||
+ if (cur_freq == policy->max)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* walk the list, find closest freq to cur_freq that is above it */
|
||||
+ while(table[i].frequency != CPUFREQ_TABLE_END) {
|
||||
+ if (table[i].frequency > cur_freq &&
|
||||
+ table[i].frequency <= next_higher_freq) {
|
||||
+ next_higher_freq = table[i].frequency;
|
||||
+ optimal_index = table[i].index;
|
||||
+ }
|
||||
+
|
||||
+ i++;
|
||||
+ }
|
||||
+
|
||||
+ *index = optimal_index;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_next_highest);
|
||||
+
|
||||
static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table);
|
||||
/**
|
||||
* show_available_freqs - show available frequencies for the specified CPU
|
||||
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
|
||||
index 9343dd3..a38fca8 100644
|
||||
--- a/include/linux/cpufreq.h
|
||||
+++ b/include/linux/cpufreq.h
|
||||
@@ -396,6 +396,15 @@ void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
|
||||
|
||||
void cpufreq_frequency_table_put_attr(unsigned int cpu);
|
||||
|
||||
+/* the following are for use in governors, or anywhere else */
|
||||
+extern int cpufreq_frequency_table_next_lowest(struct cpufreq_policy *policy,
|
||||
+ struct cpufreq_frequency_table *table,
|
||||
+ int *index);
|
||||
+
|
||||
+extern int cpufreq_frequency_table_next_highest(struct cpufreq_policy *policy,
|
||||
+ struct cpufreq_frequency_table *table,
|
||||
+ int *index);
|
||||
+
|
||||
|
||||
/*********************************************************************
|
||||
* UNIFIED DEBUG HELPERS *
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,879 @@
|
||||
From e4c777d8314d7925e4895f00b3a7ebd64a4d830b Mon Sep 17 00:00:00 2001
|
||||
From: Mike Turquette <mturquette@ti.com>
|
||||
Date: Tue, 17 May 2011 09:43:09 -0500
|
||||
Subject: [PATCH 2/2] cpufreq: introduce hotplug governor
|
||||
|
||||
The "hotplug" governor scales CPU frequency based on load, similar to
|
||||
"ondemand". It scales up to the highest frequency when "up_threshold"
|
||||
is crossed and scales down one frequency at a time when "down_threshold"
|
||||
is crossed. Unlike those governors, target frequencies are determined
|
||||
by directly accessing the CPUfreq frequency table, instead of taking
|
||||
some percentage of maximum available frequency.
|
||||
|
||||
The key difference in the "hotplug" governor is that it will disable
|
||||
auxillary CPUs when the system is very idle, and enable them again once
|
||||
the system becomes busy. This is achieved by averaging load over
|
||||
multiple sampling periods; if CPUs were online or offlined based on a
|
||||
single sampling period then thrashing will occur.
|
||||
|
||||
Sysfs entries exist for "hotplug_in_sampling_periods" and for
|
||||
"hotplug_out_sampling_periods" which determine how many consecutive
|
||||
periods get averaged to determine if auxillery CPUs should be onlined or
|
||||
offlined. Defaults are 5 periods and 20 periods respectively.
|
||||
Otherwise the standard sysfs entries you might find for "ondemand" and
|
||||
"conservative" governors are there.
|
||||
|
||||
To use this governor it is assumed that your CPUfreq driver has
|
||||
populated the CPUfreq table, CONFIG_NO_HZ is enabled and
|
||||
CONFIG_HOTPLUG_CPU is enabled.
|
||||
|
||||
Changes in V2:
|
||||
Corrected default sampling periods
|
||||
Optimized load history array resizing
|
||||
Maintain load history when resizing array
|
||||
Add locking to dbs_check_cpu
|
||||
Switch from enable_nonboot_cpus to cpu_up
|
||||
Switch from disable_nonboot_cpus to down_cpu
|
||||
Fix some printks
|
||||
Coding style around for-loops
|
||||
|
||||
Signed-off-by: Mike Turquette <mturquette@ti.com>
|
||||
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
Documentation/cpu-freq/governors.txt | 28 ++
|
||||
drivers/cpufreq/Kconfig | 33 ++
|
||||
drivers/cpufreq/Makefile | 1 +
|
||||
drivers/cpufreq/cpufreq_hotplug.c | 705 ++++++++++++++++++++++++++++++++++
|
||||
include/linux/cpufreq.h | 3 +
|
||||
5 files changed, 770 insertions(+), 0 deletions(-)
|
||||
create mode 100644 drivers/cpufreq/cpufreq_hotplug.c
|
||||
|
||||
diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
|
||||
index e74d0a2..c2e3d3d 100644
|
||||
--- a/Documentation/cpu-freq/governors.txt
|
||||
+++ b/Documentation/cpu-freq/governors.txt
|
||||
@@ -193,6 +193,34 @@ governor but for the opposite direction. For example when set to its
|
||||
default value of '20' it means that if the CPU usage needs to be below
|
||||
20% between samples to have the frequency decreased.
|
||||
|
||||
+
|
||||
+2.6 Hotplug
|
||||
+-----------
|
||||
+
|
||||
+The CPUfreq governor "hotplug" operates similary to "ondemand" and
|
||||
+"conservative". It's decisions are based primarily on CPU load. Like
|
||||
+"ondemand" the "hotplug" governor will ramp up to the highest frequency
|
||||
+once the run-time tunable "up_threshold" parameter is crossed. Like
|
||||
+"conservative", the "hotplug" governor exports a "down_threshold"
|
||||
+parameter that is also tunable at run-time. When the "down_threshold"
|
||||
+is crossed the CPU transitions to the next lowest frequency in the
|
||||
+CPUfreq frequency table instead of decrementing the frequency based on a
|
||||
+percentage of maximum load.
|
||||
+
|
||||
+The main reason "hotplug" governor exists is for architectures requiring
|
||||
+that only the master CPU be online in order to hit low-power states
|
||||
+(C-states). OMAP4 is one such example of this. The "hotplug" governor
|
||||
+is also helpful in reducing thermal output in devices with tight thermal
|
||||
+constraints.
|
||||
+
|
||||
+Auxillary CPUs are onlined/offline based on CPU load, but the decision
|
||||
+to do so is made after averaging several sampling windows. This is to
|
||||
+reduce CPU hotplug "thrashing", which can be caused by normal system
|
||||
+entropy and leads to lots of spurious plug-in and plug-out transitions.
|
||||
+The number of sampling periods averaged together is tunable via the
|
||||
+"hotplug_in_sampling_periods" and "hotplug_out_sampling_periods"
|
||||
+run-time tunable parameters.
|
||||
+
|
||||
3. The Governor Interface in the CPUfreq Core
|
||||
=============================================
|
||||
|
||||
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
|
||||
index ca8ee80..c716a0e 100644
|
||||
--- a/drivers/cpufreq/Kconfig
|
||||
+++ b/drivers/cpufreq/Kconfig
|
||||
@@ -110,6 +110,19 @@ config CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
|
||||
Be aware that not all cpufreq drivers support the conservative
|
||||
governor. If unsure have a look at the help section of the
|
||||
driver. Fallback governor will be the performance governor.
|
||||
+
|
||||
+config CPU_FREQ_DEFAULT_GOV_HOTPLUG
|
||||
+ bool "hotplug"
|
||||
+ select CPU_FREQ_GOV_HOTPLUG
|
||||
+ select CPU_FREQ_GOV_PERFORMANCE
|
||||
+ help
|
||||
+ Use the CPUFreq governor 'hotplug' as default. This allows you
|
||||
+ to get a full dynamic frequency capable system with CPU
|
||||
+ hotplug support by simply loading your cpufreq low-level
|
||||
+ hardware driver. Be aware that not all cpufreq drivers
|
||||
+ support the hotplug governor. If unsure have a look at
|
||||
+ the help section of the driver. Fallback governor will be the
|
||||
+ performance governor.
|
||||
endchoice
|
||||
|
||||
config CPU_FREQ_GOV_PERFORMANCE
|
||||
@@ -190,4 +203,24 @@ config CPU_FREQ_GOV_CONSERVATIVE
|
||||
|
||||
If in doubt, say N.
|
||||
|
||||
+config CPU_FREQ_GOV_HOTPLUG
|
||||
+ tristate "'hotplug' cpufreq governor"
|
||||
+ depends on CPU_FREQ && NO_HZ && HOTPLUG_CPU
|
||||
+ help
|
||||
+ 'hotplug' - this driver mimics the frequency scaling behavior
|
||||
+ in 'ondemand', but with several key differences. First is
|
||||
+ that frequency transitions use the CPUFreq table directly,
|
||||
+ instead of incrementing in a percentage of the maximum
|
||||
+ available frequency. Second 'hotplug' will offline auxillary
|
||||
+ CPUs when the system is idle, and online those CPUs once the
|
||||
+ system becomes busy again. This last feature is needed for
|
||||
+ architectures which transition to low power states when only
|
||||
+ the "master" CPU is online, or for thermally constrained
|
||||
+ devices.
|
||||
+
|
||||
+ If you don't have one of these architectures or devices, use
|
||||
+ 'ondemand' instead.
|
||||
+
|
||||
+ If in doubt, say N.
|
||||
+
|
||||
endif # CPU_FREQ
|
||||
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
|
||||
index 71fc3b4..05d564c 100644
|
||||
--- a/drivers/cpufreq/Makefile
|
||||
+++ b/drivers/cpufreq/Makefile
|
||||
@@ -9,6 +9,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o
|
||||
obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o
|
||||
obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o
|
||||
obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o
|
||||
+obj-$(CONFIG_CPU_FREQ_GOV_HOTPLUG) += cpufreq_hotplug.o
|
||||
|
||||
# CPUfreq cross-arch helpers
|
||||
obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o
|
||||
diff --git a/drivers/cpufreq/cpufreq_hotplug.c b/drivers/cpufreq/cpufreq_hotplug.c
|
||||
new file mode 100644
|
||||
index 0000000..85aa6d2
|
||||
--- /dev/null
|
||||
+++ b/drivers/cpufreq/cpufreq_hotplug.c
|
||||
@@ -0,0 +1,705 @@
|
||||
+/*
|
||||
+ * CPUFreq hotplug governor
|
||||
+ *
|
||||
+ * Copyright (C) 2010 Texas Instruments, Inc.
|
||||
+ * Mike Turquette <mturquette@ti.com>
|
||||
+ * Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
+ *
|
||||
+ * Based on ondemand governor
|
||||
+ * Copyright (C) 2001 Russell King
|
||||
+ * (C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>,
|
||||
+ * Jun Nakajima <jun.nakajima@intel.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License version 2 as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/cpufreq.h>
|
||||
+#include <linux/cpu.h>
|
||||
+#include <linux/jiffies.h>
|
||||
+#include <linux/kernel_stat.h>
|
||||
+#include <linux/mutex.h>
|
||||
+#include <linux/hrtimer.h>
|
||||
+#include <linux/tick.h>
|
||||
+#include <linux/ktime.h>
|
||||
+#include <linux/sched.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/slab.h>
|
||||
+
|
||||
+/* greater than 80% avg load across online CPUs increases frequency */
|
||||
+#define DEFAULT_UP_FREQ_MIN_LOAD (80)
|
||||
+
|
||||
+/* less than 20% avg load across online CPUs decreases frequency */
|
||||
+#define DEFAULT_DOWN_FREQ_MAX_LOAD (20)
|
||||
+
|
||||
+/* default sampling period (uSec) is bogus; 10x ondemand's default for x86 */
|
||||
+#define DEFAULT_SAMPLING_PERIOD (100000)
|
||||
+
|
||||
+/* default number of sampling periods to average before hotplug-in decision */
|
||||
+#define DEFAULT_HOTPLUG_IN_SAMPLING_PERIODS (5)
|
||||
+
|
||||
+/* default number of sampling periods to average before hotplug-out decision */
|
||||
+#define DEFAULT_HOTPLUG_OUT_SAMPLING_PERIODS (20)
|
||||
+
|
||||
+static void do_dbs_timer(struct work_struct *work);
|
||||
+static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
|
||||
+ unsigned int event);
|
||||
+
|
||||
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_HOTPLUG
|
||||
+static
|
||||
+#endif
|
||||
+struct cpufreq_governor cpufreq_gov_hotplug = {
|
||||
+ .name = "hotplug",
|
||||
+ .governor = cpufreq_governor_dbs,
|
||||
+ .owner = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+struct cpu_dbs_info_s {
|
||||
+ cputime64_t prev_cpu_idle;
|
||||
+ cputime64_t prev_cpu_wall;
|
||||
+ cputime64_t prev_cpu_nice;
|
||||
+ struct cpufreq_policy *cur_policy;
|
||||
+ struct delayed_work work;
|
||||
+ struct cpufreq_frequency_table *freq_table;
|
||||
+ int cpu;
|
||||
+ /*
|
||||
+ * percpu mutex that serializes governor limit change with
|
||||
+ * do_dbs_timer invocation. We do not want do_dbs_timer to run
|
||||
+ * when user is changing the governor or limits.
|
||||
+ */
|
||||
+ struct mutex timer_mutex;
|
||||
+};
|
||||
+static DEFINE_PER_CPU(struct cpu_dbs_info_s, hp_cpu_dbs_info);
|
||||
+
|
||||
+static unsigned int dbs_enable; /* number of CPUs using this policy */
|
||||
+
|
||||
+/*
|
||||
+ * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on
|
||||
+ * different CPUs. It protects dbs_enable in governor start/stop.
|
||||
+ */
|
||||
+static DEFINE_MUTEX(dbs_mutex);
|
||||
+
|
||||
+static struct workqueue_struct *khotplug_wq;
|
||||
+
|
||||
+static struct dbs_tuners {
|
||||
+ unsigned int sampling_rate;
|
||||
+ unsigned int up_threshold;
|
||||
+ unsigned int down_threshold;
|
||||
+ unsigned int hotplug_in_sampling_periods;
|
||||
+ unsigned int hotplug_out_sampling_periods;
|
||||
+ unsigned int hotplug_load_index;
|
||||
+ unsigned int *hotplug_load_history;
|
||||
+ unsigned int ignore_nice;
|
||||
+ unsigned int io_is_busy;
|
||||
+} dbs_tuners_ins = {
|
||||
+ .sampling_rate = DEFAULT_SAMPLING_PERIOD,
|
||||
+ .up_threshold = DEFAULT_UP_FREQ_MIN_LOAD,
|
||||
+ .down_threshold = DEFAULT_DOWN_FREQ_MAX_LOAD,
|
||||
+ .hotplug_in_sampling_periods = DEFAULT_HOTPLUG_IN_SAMPLING_PERIODS,
|
||||
+ .hotplug_out_sampling_periods = DEFAULT_HOTPLUG_OUT_SAMPLING_PERIODS,
|
||||
+ .hotplug_load_index = 0,
|
||||
+ .ignore_nice = 0,
|
||||
+ .io_is_busy = 0,
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * A corner case exists when switching io_is_busy at run-time: comparing idle
|
||||
+ * times from a non-io_is_busy period to an io_is_busy period (or vice-versa)
|
||||
+ * will misrepresent the actual change in system idleness. We ignore this
|
||||
+ * corner case: enabling io_is_busy might cause freq increase and disabling
|
||||
+ * might cause freq decrease, which probably matches the original intent.
|
||||
+ */
|
||||
+static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
|
||||
+{
|
||||
+ u64 idle_time;
|
||||
+ u64 iowait_time;
|
||||
+
|
||||
+ /* cpufreq-hotplug always assumes CONFIG_NO_HZ */
|
||||
+ idle_time = get_cpu_idle_time_us(cpu, wall);
|
||||
+
|
||||
+ /* add time spent doing I/O to idle time */
|
||||
+ if (dbs_tuners_ins.io_is_busy) {
|
||||
+ iowait_time = get_cpu_iowait_time_us(cpu, wall);
|
||||
+ /* cpufreq-hotplug always assumes CONFIG_NO_HZ */
|
||||
+ if (iowait_time != -1ULL && idle_time >= iowait_time)
|
||||
+ idle_time -= iowait_time;
|
||||
+ }
|
||||
+
|
||||
+ return idle_time;
|
||||
+}
|
||||
+
|
||||
+/************************** sysfs interface ************************/
|
||||
+
|
||||
+/* XXX look at global sysfs macros in cpufreq.h, can those be used here? */
|
||||
+
|
||||
+/* cpufreq_hotplug Governor Tunables */
|
||||
+#define show_one(file_name, object) \
|
||||
+static ssize_t show_##file_name \
|
||||
+(struct kobject *kobj, struct attribute *attr, char *buf) \
|
||||
+{ \
|
||||
+ return sprintf(buf, "%u\n", dbs_tuners_ins.object); \
|
||||
+}
|
||||
+show_one(sampling_rate, sampling_rate);
|
||||
+show_one(up_threshold, up_threshold);
|
||||
+show_one(down_threshold, down_threshold);
|
||||
+show_one(hotplug_in_sampling_periods, hotplug_in_sampling_periods);
|
||||
+show_one(hotplug_out_sampling_periods, hotplug_out_sampling_periods);
|
||||
+show_one(ignore_nice_load, ignore_nice);
|
||||
+show_one(io_is_busy, io_is_busy);
|
||||
+
|
||||
+static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
|
||||
+ const char *buf, size_t count)
|
||||
+{
|
||||
+ unsigned int input;
|
||||
+ int ret;
|
||||
+ ret = sscanf(buf, "%u", &input);
|
||||
+ if (ret != 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mutex_lock(&dbs_mutex);
|
||||
+ dbs_tuners_ins.sampling_rate = input;
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
|
||||
+ const char *buf, size_t count)
|
||||
+{
|
||||
+ unsigned int input;
|
||||
+ int ret;
|
||||
+ ret = sscanf(buf, "%u", &input);
|
||||
+
|
||||
+ if (ret != 1 || input <= dbs_tuners_ins.down_threshold) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ mutex_lock(&dbs_mutex);
|
||||
+ dbs_tuners_ins.up_threshold = input;
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static ssize_t store_down_threshold(struct kobject *a, struct attribute *b,
|
||||
+ const char *buf, size_t count)
|
||||
+{
|
||||
+ unsigned int input;
|
||||
+ int ret;
|
||||
+ ret = sscanf(buf, "%u", &input);
|
||||
+
|
||||
+ if (ret != 1 || input >= dbs_tuners_ins.up_threshold) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ mutex_lock(&dbs_mutex);
|
||||
+ dbs_tuners_ins.down_threshold = input;
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static ssize_t store_hotplug_in_sampling_periods(struct kobject *a,
|
||||
+ struct attribute *b, const char *buf, size_t count)
|
||||
+{
|
||||
+ unsigned int input;
|
||||
+ unsigned int *temp;
|
||||
+ unsigned int max_windows;
|
||||
+ int ret;
|
||||
+ ret = sscanf(buf, "%u", &input);
|
||||
+
|
||||
+ if (ret != 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* already using this value, bail out */
|
||||
+ if (input == dbs_tuners_ins.hotplug_in_sampling_periods)
|
||||
+ return count;
|
||||
+
|
||||
+ mutex_lock(&dbs_mutex);
|
||||
+ ret = count;
|
||||
+ max_windows = max(dbs_tuners_ins.hotplug_in_sampling_periods,
|
||||
+ dbs_tuners_ins.hotplug_out_sampling_periods);
|
||||
+
|
||||
+ /* no need to resize array */
|
||||
+ if (input <= max_windows) {
|
||||
+ dbs_tuners_ins.hotplug_in_sampling_periods = input;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* resize array */
|
||||
+ temp = kmalloc((sizeof(unsigned int) * input), GFP_KERNEL);
|
||||
+
|
||||
+ if (!temp || IS_ERR(temp)) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(temp, dbs_tuners_ins.hotplug_load_history,
|
||||
+ (max_windows * sizeof(unsigned int)));
|
||||
+ kfree(dbs_tuners_ins.hotplug_load_history);
|
||||
+
|
||||
+ /* replace old buffer, old number of sampling periods & old index */
|
||||
+ dbs_tuners_ins.hotplug_load_history = temp;
|
||||
+ dbs_tuners_ins.hotplug_in_sampling_periods = input;
|
||||
+ dbs_tuners_ins.hotplug_load_index = max_windows;
|
||||
+out:
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static ssize_t store_hotplug_out_sampling_periods(struct kobject *a,
|
||||
+ struct attribute *b, const char *buf, size_t count)
|
||||
+{
|
||||
+ unsigned int input;
|
||||
+ unsigned int *temp;
|
||||
+ unsigned int max_windows;
|
||||
+ int ret;
|
||||
+ ret = sscanf(buf, "%u", &input);
|
||||
+
|
||||
+ if (ret != 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* already using this value, bail out */
|
||||
+ if (input == dbs_tuners_ins.hotplug_out_sampling_periods)
|
||||
+ return count;
|
||||
+
|
||||
+ mutex_lock(&dbs_mutex);
|
||||
+ ret = count;
|
||||
+ max_windows = max(dbs_tuners_ins.hotplug_in_sampling_periods,
|
||||
+ dbs_tuners_ins.hotplug_out_sampling_periods);
|
||||
+
|
||||
+ /* no need to resize array */
|
||||
+ if (input <= max_windows) {
|
||||
+ dbs_tuners_ins.hotplug_out_sampling_periods = input;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* resize array */
|
||||
+ temp = kmalloc((sizeof(unsigned int) * input), GFP_KERNEL);
|
||||
+
|
||||
+ if (!temp || IS_ERR(temp)) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(temp, dbs_tuners_ins.hotplug_load_history,
|
||||
+ (max_windows * sizeof(unsigned int)));
|
||||
+ kfree(dbs_tuners_ins.hotplug_load_history);
|
||||
+
|
||||
+ /* replace old buffer, old number of sampling periods & old index */
|
||||
+ dbs_tuners_ins.hotplug_load_history = temp;
|
||||
+ dbs_tuners_ins.hotplug_out_sampling_periods = input;
|
||||
+ dbs_tuners_ins.hotplug_load_index = max_windows;
|
||||
+out:
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
|
||||
+ const char *buf, size_t count)
|
||||
+{
|
||||
+ unsigned int input;
|
||||
+ int ret;
|
||||
+
|
||||
+ unsigned int j;
|
||||
+
|
||||
+ ret = sscanf(buf, "%u", &input);
|
||||
+ if (ret != 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (input > 1)
|
||||
+ input = 1;
|
||||
+
|
||||
+ mutex_lock(&dbs_mutex);
|
||||
+ if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+ return count;
|
||||
+ }
|
||||
+ dbs_tuners_ins.ignore_nice = input;
|
||||
+
|
||||
+ /* we need to re-evaluate prev_cpu_idle */
|
||||
+ for_each_online_cpu(j) {
|
||||
+ struct cpu_dbs_info_s *dbs_info;
|
||||
+ dbs_info = &per_cpu(hp_cpu_dbs_info, j);
|
||||
+ dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
|
||||
+ &dbs_info->prev_cpu_wall);
|
||||
+ if (dbs_tuners_ins.ignore_nice)
|
||||
+ dbs_info->prev_cpu_nice = kstat_cpu(j).cpustat.nice;
|
||||
+
|
||||
+ }
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b,
|
||||
+ const char *buf, size_t count)
|
||||
+{
|
||||
+ unsigned int input;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = sscanf(buf, "%u", &input);
|
||||
+ if (ret != 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mutex_lock(&dbs_mutex);
|
||||
+ dbs_tuners_ins.io_is_busy = !!input;
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+define_one_global_rw(sampling_rate);
|
||||
+define_one_global_rw(up_threshold);
|
||||
+define_one_global_rw(down_threshold);
|
||||
+define_one_global_rw(hotplug_in_sampling_periods);
|
||||
+define_one_global_rw(hotplug_out_sampling_periods);
|
||||
+define_one_global_rw(ignore_nice_load);
|
||||
+define_one_global_rw(io_is_busy);
|
||||
+
|
||||
+static struct attribute *dbs_attributes[] = {
|
||||
+ &sampling_rate.attr,
|
||||
+ &up_threshold.attr,
|
||||
+ &down_threshold.attr,
|
||||
+ &hotplug_in_sampling_periods.attr,
|
||||
+ &hotplug_out_sampling_periods.attr,
|
||||
+ &ignore_nice_load.attr,
|
||||
+ &io_is_busy.attr,
|
||||
+ NULL
|
||||
+};
|
||||
+
|
||||
+static struct attribute_group dbs_attr_group = {
|
||||
+ .attrs = dbs_attributes,
|
||||
+ .name = "hotplug",
|
||||
+};
|
||||
+
|
||||
+/************************** sysfs end ************************/
|
||||
+
|
||||
+static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
|
||||
+{
|
||||
+ /* combined load of all enabled CPUs */
|
||||
+ unsigned int total_load = 0;
|
||||
+ /* single largest CPU load */
|
||||
+ unsigned int max_load = 0;
|
||||
+ /* average load across all enabled CPUs */
|
||||
+ unsigned int avg_load = 0;
|
||||
+ /* average load across multiple sampling periods for hotplug events */
|
||||
+ unsigned int hotplug_in_avg_load = 0;
|
||||
+ unsigned int hotplug_out_avg_load = 0;
|
||||
+ /* number of sampling periods averaged for hotplug decisions */
|
||||
+ unsigned int periods;
|
||||
+
|
||||
+ struct cpufreq_policy *policy;
|
||||
+ unsigned int index = 0;
|
||||
+ unsigned int i, j;
|
||||
+
|
||||
+ policy = this_dbs_info->cur_policy;
|
||||
+
|
||||
+ /*
|
||||
+ * cpu load accounting
|
||||
+ * get highest load, total load and average load across all CPUs
|
||||
+ */
|
||||
+ for_each_cpu(j, policy->cpus) {
|
||||
+ unsigned int load;
|
||||
+ unsigned int idle_time, wall_time;
|
||||
+ cputime64_t cur_wall_time, cur_idle_time;
|
||||
+ struct cpu_dbs_info_s *j_dbs_info;
|
||||
+
|
||||
+ j_dbs_info = &per_cpu(hp_cpu_dbs_info, j);
|
||||
+
|
||||
+ /* update both cur_idle_time and cur_wall_time */
|
||||
+ cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
|
||||
+
|
||||
+ /* how much wall time has passed since last iteration? */
|
||||
+ wall_time = (unsigned int) cputime64_sub(cur_wall_time,
|
||||
+ j_dbs_info->prev_cpu_wall);
|
||||
+ j_dbs_info->prev_cpu_wall = cur_wall_time;
|
||||
+
|
||||
+ /* how much idle time has passed since last iteration? */
|
||||
+ idle_time = (unsigned int) cputime64_sub(cur_idle_time,
|
||||
+ j_dbs_info->prev_cpu_idle);
|
||||
+ j_dbs_info->prev_cpu_idle = cur_idle_time;
|
||||
+
|
||||
+ if (unlikely(!wall_time || wall_time < idle_time))
|
||||
+ continue;
|
||||
+
|
||||
+ /* load is the percentage of time not spent in idle */
|
||||
+ load = 100 * (wall_time - idle_time) / wall_time;
|
||||
+
|
||||
+ /* keep track of combined load across all CPUs */
|
||||
+ total_load += load;
|
||||
+
|
||||
+ /* keep track of highest single load across all CPUs */
|
||||
+ if (load > max_load)
|
||||
+ max_load = load;
|
||||
+ }
|
||||
+
|
||||
+ /* calculate the average load across all related CPUs */
|
||||
+ avg_load = total_load / num_online_cpus();
|
||||
+
|
||||
+
|
||||
+ /*
|
||||
+ * hotplug load accounting
|
||||
+ * average load over multiple sampling periods
|
||||
+ */
|
||||
+
|
||||
+ /* how many sampling periods do we use for hotplug decisions? */
|
||||
+ periods = max(dbs_tuners_ins.hotplug_in_sampling_periods,
|
||||
+ dbs_tuners_ins.hotplug_out_sampling_periods);
|
||||
+
|
||||
+ /* store avg_load in the circular buffer */
|
||||
+ dbs_tuners_ins.hotplug_load_history[dbs_tuners_ins.hotplug_load_index]
|
||||
+ = avg_load;
|
||||
+
|
||||
+ /* compute average load across in & out sampling periods */
|
||||
+ for (i = 0, j = dbs_tuners_ins.hotplug_load_index;
|
||||
+ i < periods; i++, j--) {
|
||||
+ if (i < dbs_tuners_ins.hotplug_in_sampling_periods)
|
||||
+ hotplug_in_avg_load +=
|
||||
+ dbs_tuners_ins.hotplug_load_history[j];
|
||||
+ if (i < dbs_tuners_ins.hotplug_out_sampling_periods)
|
||||
+ hotplug_out_avg_load +=
|
||||
+ dbs_tuners_ins.hotplug_load_history[j];
|
||||
+
|
||||
+ if (j == 0)
|
||||
+ j = periods;
|
||||
+ }
|
||||
+
|
||||
+ hotplug_in_avg_load = hotplug_in_avg_load /
|
||||
+ dbs_tuners_ins.hotplug_in_sampling_periods;
|
||||
+
|
||||
+ hotplug_out_avg_load = hotplug_out_avg_load /
|
||||
+ dbs_tuners_ins.hotplug_out_sampling_periods;
|
||||
+
|
||||
+ /* return to first element if we're at the circular buffer's end */
|
||||
+ if (++dbs_tuners_ins.hotplug_load_index == periods)
|
||||
+ dbs_tuners_ins.hotplug_load_index = 0;
|
||||
+
|
||||
+ /* check for frequency increase */
|
||||
+ if (avg_load > dbs_tuners_ins.up_threshold) {
|
||||
+ /* should we enable auxillary CPUs? */
|
||||
+ if (num_online_cpus() < 2 && hotplug_in_avg_load >
|
||||
+ dbs_tuners_ins.up_threshold) {
|
||||
+ /* hotplug with cpufreq is nasty
|
||||
+ * a call to cpufreq_governor_dbs may cause a lockup.
|
||||
+ * wq is not running here so its safe.
|
||||
+ */
|
||||
+ mutex_unlock(&this_dbs_info->timer_mutex);
|
||||
+ cpu_up(1);
|
||||
+ mutex_lock(&this_dbs_info->timer_mutex);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* increase to highest frequency supported */
|
||||
+ if (policy->cur < policy->max)
|
||||
+ __cpufreq_driver_target(policy, policy->max,
|
||||
+ CPUFREQ_RELATION_H);
|
||||
+
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* check for frequency decrease */
|
||||
+ if (avg_load < dbs_tuners_ins.down_threshold) {
|
||||
+ /* are we at the minimum frequency already? */
|
||||
+ if (policy->cur == policy->min) {
|
||||
+ /* should we disable auxillary CPUs? */
|
||||
+ if (num_online_cpus() > 1 && hotplug_out_avg_load <
|
||||
+ dbs_tuners_ins.down_threshold) {
|
||||
+ mutex_unlock(&this_dbs_info->timer_mutex);
|
||||
+ cpu_down(1);
|
||||
+ mutex_lock(&this_dbs_info->timer_mutex);
|
||||
+ }
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* bump down to the next lowest frequency in the table */
|
||||
+ if (cpufreq_frequency_table_next_lowest(policy,
|
||||
+ this_dbs_info->freq_table, &index)) {
|
||||
+ pr_err("%s: failed to get next lowest frequency\n",
|
||||
+ __func__);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ __cpufreq_driver_target(policy,
|
||||
+ this_dbs_info->freq_table[index].frequency,
|
||||
+ CPUFREQ_RELATION_L);
|
||||
+ }
|
||||
+out:
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static void do_dbs_timer(struct work_struct *work)
|
||||
+{
|
||||
+ struct cpu_dbs_info_s *dbs_info =
|
||||
+ container_of(work, struct cpu_dbs_info_s, work.work);
|
||||
+ unsigned int cpu = dbs_info->cpu;
|
||||
+
|
||||
+ /* We want all related CPUs to do sampling nearly on same jiffy */
|
||||
+ int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
|
||||
+
|
||||
+ mutex_lock(&dbs_info->timer_mutex);
|
||||
+ dbs_check_cpu(dbs_info);
|
||||
+ queue_delayed_work_on(cpu, khotplug_wq, &dbs_info->work, delay);
|
||||
+ mutex_unlock(&dbs_info->timer_mutex);
|
||||
+}
|
||||
+
|
||||
+static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
|
||||
+{
|
||||
+ /* We want all related CPUs to do sampling nearly on same jiffy */
|
||||
+ int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
|
||||
+ delay -= jiffies % delay;
|
||||
+
|
||||
+ INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer);
|
||||
+ queue_delayed_work_on(dbs_info->cpu, khotplug_wq, &dbs_info->work,
|
||||
+ delay);
|
||||
+}
|
||||
+
|
||||
+static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
|
||||
+{
|
||||
+ cancel_delayed_work_sync(&dbs_info->work);
|
||||
+}
|
||||
+
|
||||
+static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
|
||||
+ unsigned int event)
|
||||
+{
|
||||
+ unsigned int cpu = policy->cpu;
|
||||
+ struct cpu_dbs_info_s *this_dbs_info;
|
||||
+ unsigned int i, j, max_periods;
|
||||
+ int rc;
|
||||
+
|
||||
+ this_dbs_info = &per_cpu(hp_cpu_dbs_info, cpu);
|
||||
+
|
||||
+ switch (event) {
|
||||
+ case CPUFREQ_GOV_START:
|
||||
+ if ((!cpu_online(cpu)) || (!policy->cur))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mutex_lock(&dbs_mutex);
|
||||
+ dbs_enable++;
|
||||
+ for_each_cpu(j, policy->cpus) {
|
||||
+ struct cpu_dbs_info_s *j_dbs_info;
|
||||
+ j_dbs_info = &per_cpu(hp_cpu_dbs_info, j);
|
||||
+ j_dbs_info->cur_policy = policy;
|
||||
+
|
||||
+ j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
|
||||
+ &j_dbs_info->prev_cpu_wall);
|
||||
+ if (dbs_tuners_ins.ignore_nice) {
|
||||
+ j_dbs_info->prev_cpu_nice =
|
||||
+ kstat_cpu(j).cpustat.nice;
|
||||
+ }
|
||||
+
|
||||
+ max_periods = max(DEFAULT_HOTPLUG_IN_SAMPLING_PERIODS,
|
||||
+ DEFAULT_HOTPLUG_OUT_SAMPLING_PERIODS);
|
||||
+ dbs_tuners_ins.hotplug_load_history = kmalloc(
|
||||
+ (sizeof(unsigned int) * max_periods),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!dbs_tuners_ins.hotplug_load_history) {
|
||||
+ WARN_ON(1);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ for (i = 0; i < max_periods; i++)
|
||||
+ dbs_tuners_ins.hotplug_load_history[i] = 50;
|
||||
+ }
|
||||
+ this_dbs_info->cpu = cpu;
|
||||
+ this_dbs_info->freq_table = cpufreq_frequency_get_table(cpu);
|
||||
+ /*
|
||||
+ * Start the timerschedule work, when this governor
|
||||
+ * is used for first time
|
||||
+ */
|
||||
+ if (dbs_enable == 1) {
|
||||
+ rc = sysfs_create_group(cpufreq_global_kobject,
|
||||
+ &dbs_attr_group);
|
||||
+ if (rc) {
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+ return rc;
|
||||
+ }
|
||||
+ }
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+
|
||||
+ mutex_init(&this_dbs_info->timer_mutex);
|
||||
+ dbs_timer_init(this_dbs_info);
|
||||
+ break;
|
||||
+
|
||||
+ case CPUFREQ_GOV_STOP:
|
||||
+ dbs_timer_exit(this_dbs_info);
|
||||
+
|
||||
+ mutex_lock(&dbs_mutex);
|
||||
+ mutex_destroy(&this_dbs_info->timer_mutex);
|
||||
+ dbs_enable--;
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+ if (!dbs_enable)
|
||||
+ sysfs_remove_group(cpufreq_global_kobject,
|
||||
+ &dbs_attr_group);
|
||||
+ kfree(dbs_tuners_ins.hotplug_load_history);
|
||||
+ /*
|
||||
+ * XXX BIG CAVEAT: Stopping the governor with CPU1 offline
|
||||
+ * will result in it remaining offline until the user onlines
|
||||
+ * it again. It is up to the user to do this (for now).
|
||||
+ */
|
||||
+ break;
|
||||
+
|
||||
+ case CPUFREQ_GOV_LIMITS:
|
||||
+ mutex_lock(&this_dbs_info->timer_mutex);
|
||||
+ if (policy->max < this_dbs_info->cur_policy->cur)
|
||||
+ __cpufreq_driver_target(this_dbs_info->cur_policy,
|
||||
+ policy->max, CPUFREQ_RELATION_H);
|
||||
+ else if (policy->min > this_dbs_info->cur_policy->cur)
|
||||
+ __cpufreq_driver_target(this_dbs_info->cur_policy,
|
||||
+ policy->min, CPUFREQ_RELATION_L);
|
||||
+ mutex_unlock(&this_dbs_info->timer_mutex);
|
||||
+ break;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int __init cpufreq_gov_dbs_init(void)
|
||||
+{
|
||||
+ int err;
|
||||
+ cputime64_t wall;
|
||||
+ u64 idle_time;
|
||||
+ int cpu = get_cpu();
|
||||
+
|
||||
+ idle_time = get_cpu_idle_time_us(cpu, &wall);
|
||||
+ put_cpu();
|
||||
+ if (idle_time != -1ULL) {
|
||||
+ dbs_tuners_ins.up_threshold = DEFAULT_UP_FREQ_MIN_LOAD;
|
||||
+ } else {
|
||||
+ pr_err("cpufreq-hotplug: %s: assumes CONFIG_NO_HZ\n",
|
||||
+ __func__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ khotplug_wq = create_workqueue("khotplug");
|
||||
+ if (!khotplug_wq) {
|
||||
+ pr_err("Creation of khotplug failed\n");
|
||||
+ return -EFAULT;
|
||||
+ }
|
||||
+ err = cpufreq_register_governor(&cpufreq_gov_hotplug);
|
||||
+ if (err)
|
||||
+ destroy_workqueue(khotplug_wq);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static void __exit cpufreq_gov_dbs_exit(void)
|
||||
+{
|
||||
+ cpufreq_unregister_governor(&cpufreq_gov_hotplug);
|
||||
+ destroy_workqueue(khotplug_wq);
|
||||
+}
|
||||
+
|
||||
+MODULE_AUTHOR("Mike Turquette <mturquette@ti.com>");
|
||||
+MODULE_DESCRIPTION("'cpufreq_hotplug' - cpufreq governor for dynamic frequency scaling and CPU hotplugging");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+
|
||||
+#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_HOTPLUG
|
||||
+fs_initcall(cpufreq_gov_dbs_init);
|
||||
+#else
|
||||
+module_init(cpufreq_gov_dbs_init);
|
||||
+#endif
|
||||
+module_exit(cpufreq_gov_dbs_exit);
|
||||
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
|
||||
index a38fca8..6cbc3df 100644
|
||||
--- a/include/linux/cpufreq.h
|
||||
+++ b/include/linux/cpufreq.h
|
||||
@@ -355,6 +355,9 @@ extern struct cpufreq_governor cpufreq_gov_ondemand;
|
||||
#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE)
|
||||
extern struct cpufreq_governor cpufreq_gov_conservative;
|
||||
#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_conservative)
|
||||
+#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_HOTPLUG)
|
||||
+extern struct cpufreq_governor cpufreq_gov_hotplug;
|
||||
+#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_hotplug)
|
||||
#endif
|
||||
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
From 33668b07abd5e66a263cc8b4b88587646f38bed0 Mon Sep 17 00:00:00 2001
|
||||
From: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
|
||||
Date: Wed, 11 Aug 2010 17:02:43 -0700
|
||||
Subject: [PATCH 1/8] OMAP: CPUfreq: ensure driver initializes after cpufreq framework and governors
|
||||
|
||||
Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
---
|
||||
arch/arm/plat-omap/cpu-omap.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
|
||||
index da4f68d..cd09d4b 100644
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ b/arch/arm/plat-omap/cpu-omap.c
|
||||
@@ -160,7 +160,7 @@ static int __init omap_cpufreq_init(void)
|
||||
return cpufreq_register_driver(&omap_driver);
|
||||
}
|
||||
|
||||
-arch_initcall(omap_cpufreq_init);
|
||||
+late_initcall(omap_cpufreq_init);
|
||||
|
||||
/*
|
||||
* if ever we want to remove this, upon cleanup call:
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
From e89b1544450fb8410a44004e48d6b330bc39f0ce Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
Date: Wed, 11 Aug 2010 17:05:38 -0700
|
||||
Subject: [PATCH 2/8] OMAP: CPUfreq: ensure policy is fully initialized
|
||||
|
||||
Ensure policy min/max/cur values are initialized when OMAP
|
||||
CPUfreq driver starts.
|
||||
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
---
|
||||
arch/arm/plat-omap/cpu-omap.c | 4 ++++
|
||||
1 files changed, 4 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
|
||||
index cd09d4b..1b36664 100644
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ b/arch/arm/plat-omap/cpu-omap.c
|
||||
@@ -126,6 +126,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
VERY_HI_RATE) / 1000;
|
||||
}
|
||||
|
||||
+ policy->min = policy->cpuinfo.min_freq;
|
||||
+ policy->max = policy->cpuinfo.max_freq;
|
||||
+ policy->cur = omap_getspeed(0);
|
||||
+
|
||||
/* FIXME: what's the actual transition time? */
|
||||
policy->cpuinfo.transition_latency = 300 * 1000;
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
From 948b868e4a83b054e8a58362238bc6cd61c0aeab Mon Sep 17 00:00:00 2001
|
||||
From: Rajendra Nayak <rnayak@ti.com>
|
||||
Date: Mon, 10 Nov 2008 17:00:25 +0530
|
||||
Subject: [PATCH 3/8] OMAP3 PM: CPUFreq driver for OMAP3
|
||||
|
||||
CPUFreq driver for OMAP3
|
||||
|
||||
With additional fixes and cleanups from Tero Kristo:
|
||||
- Fix rate calculation bug in omap3_select_table_rate
|
||||
- Refreshed DVFS VDD1 control against latest clock fw
|
||||
|
||||
Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
|
||||
OMAP3: PM: CPUFreq: Fix omap_getspeed.
|
||||
|
||||
Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
|
||||
|
||||
Make sure omap cpufreq driver initializes after cpufreq framework and governors
|
||||
|
||||
Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
|
||||
|
||||
merge: CPUFreq: remove obsolete funcs
|
||||
|
||||
OMAP3 clock: Update cpufreq driver
|
||||
|
||||
This patch removes all refrences to virtual clock
|
||||
nodes in CPUFreq driver.
|
||||
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
|
||||
Signed-off-by: Jean Pihet <jpihet@mvista.com>
|
||||
|
||||
PM: Prevent direct cpufreq scaling during initialization
|
||||
|
||||
It is seen that the OMAP specific cpufreq initialization code tries to
|
||||
scale the MPU frequency to the highest possible without taking care of
|
||||
the voltage level. On power on reset the power IC does not provide the
|
||||
necessary voltage for the highest available MPU frequency (that would
|
||||
satisfy all Si families). This potentially is an window of opportunity
|
||||
for things to go wrong.
|
||||
|
||||
Signed-off-by: Romit Dasgupta <romit@ti.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
|
||||
OMAP3: PM: enable 600MHz (overdrive) OPP
|
||||
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
|
||||
omap3: introduce cpufreq
|
||||
|
||||
OMAP OPP layer functions now have dependencies of CONFIG_CPU_FREQ only.
|
||||
|
||||
With this patch, omap opp layer now has its compilation flags
|
||||
bound to CONFIG_CPU_FREQ. Also its code has been removed from pm34xx.c.
|
||||
|
||||
A new file has been created to contain cpu freq code related to
|
||||
OMAP3: cpufreq34xx.c
|
||||
|
||||
OMAP34xx and OMAP36xx family OPPs are made available
|
||||
|
||||
Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
|
||||
Signed-off-by: Paul Walmsley <paul@pwsan.com>
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Vishwanath BS <vishwanath.bs@ti.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
Signed-off-by: Romit Dasgupta <romit@ti.com>
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
|
||||
omap3: cpufreq: allow default opp table init
|
||||
|
||||
For board files which choose to override the defaults, the existing
|
||||
mechanism will work, for boards that would like to work with defaults,
|
||||
allow init_common_hw to call init_opp_table to initialize if not
|
||||
already initialized. this will allow all omap boards which have opp
|
||||
tables predefined for a silicon to use the same.
|
||||
|
||||
Originally reported for overo:
|
||||
http://marc.info/?t=127265269400004&r=1&w=2
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Reported-by: Peter Tseng <tsenpet09@gmail.com>
|
||||
Cc: Cliff Brake <cliff.brake@gmail.com>
|
||||
Cc: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
|
||||
OMAP2: update OPP data to be device based
|
||||
|
||||
Cc: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
|
||||
OMAP3: CPUfreq: update to device-based OPP API
|
||||
|
||||
Update usage of OPP API to use new device-based API. This requires
|
||||
getting the 'struct device' for the MPU and using that with the OPP
|
||||
API.
|
||||
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
|
||||
omap3: opp: make independent of cpufreq
|
||||
|
||||
Make opp3xx data which is registered with the opp layer
|
||||
dependent purely on CONFIG_PM as opp layer and pm.c users
|
||||
are CONFIG_PM dependent not cpufreq dependent.
|
||||
so we rename the data definition to opp3xxx_data.c (inline with what
|
||||
we have for omap2), also move the build definition to be under
|
||||
the existing CONFIG_PM build instead of CPUFREQ.
|
||||
|
||||
Cc: Eduardo Valentin <eduardo.valentin@nokia.com>
|
||||
Cc: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
Cc: Paul Walmsley <paul@pwsan.com>
|
||||
Cc: Rajendra Nayak <rnayak@ti.com>
|
||||
Cc: Sanjeev Premi <premi@ti.com>
|
||||
Cc: Thara Gopinath <thara@ti.com>
|
||||
Cc: Tony Lindgren <tony@atomide.com>
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/clock.h | 14 +++++++++++++-
|
||||
arch/arm/mach-omap2/clock34xx.c | 2 ++
|
||||
arch/arm/plat-omap/cpu-omap.c | 34 +++++++++++++++++++++++++++++++---
|
||||
3 files changed, 46 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
|
||||
index e10ff2b..0a07e50 100644
|
||||
--- a/arch/arm/mach-omap2/clock.h
|
||||
+++ b/arch/arm/mach-omap2/clock.h
|
||||
@@ -141,7 +141,9 @@ extern const struct clksel_rate gpt_sys_rates[];
|
||||
extern const struct clksel_rate gfx_l3_rates[];
|
||||
extern const struct clksel_rate dsp_ick_rates[];
|
||||
|
||||
-#if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_CPU_FREQ)
|
||||
+#ifdef CONFIG_CPU_FREQ
|
||||
+
|
||||
+#ifdef CONFIG_ARCH_OMAP2
|
||||
extern void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
|
||||
extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
|
||||
#else
|
||||
@@ -149,6 +151,16 @@ extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
|
||||
#define omap2_clk_exit_cpufreq_table 0
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_ARCH_OMAP3
|
||||
+extern void omap3_clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
|
||||
+extern void omap3_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
|
||||
+#else
|
||||
+#define omap3_clk_init_cpufreq_table 0
|
||||
+#define omap3_clk_exit_cpufreq_table 0
|
||||
+#endif
|
||||
+
|
||||
+#endif /* CONFIG_CPU_FREQ */
|
||||
+
|
||||
extern const struct clkops clkops_omap2_iclk_dflt_wait;
|
||||
extern const struct clkops clkops_omap2_iclk_dflt;
|
||||
extern const struct clkops clkops_omap2_iclk_idle_only;
|
||||
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
|
||||
index 1fc96b9..119e135 100644
|
||||
--- a/arch/arm/mach-omap2/clock34xx.c
|
||||
+++ b/arch/arm/mach-omap2/clock34xx.c
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/cpufreq.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
|
||||
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
|
||||
index 1b36664..f0f9430 100644
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ b/arch/arm/plat-omap/cpu-omap.c
|
||||
@@ -8,6 +8,10 @@
|
||||
*
|
||||
* Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
|
||||
*
|
||||
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
|
||||
+ * Updated to support OMAP3
|
||||
+ * Rajendra Nayak <rnayak@ti.com>
|
||||
+ *
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
@@ -26,12 +30,19 @@
|
||||
#include <plat/clock.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
+#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
+#include <plat/omap-pm.h>
|
||||
+#include <plat/opp.h>
|
||||
+#endif
|
||||
+
|
||||
#define VERY_HI_RATE 900000000
|
||||
|
||||
static struct cpufreq_frequency_table *freq_table;
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP1
|
||||
#define MPU_CLK "mpu"
|
||||
+#elif CONFIG_ARCH_OMAP3
|
||||
+#define MPU_CLK "arm_fck"
|
||||
#else
|
||||
#define MPU_CLK "virt_prcm_set"
|
||||
#endif
|
||||
@@ -73,7 +84,13 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
{
|
||||
+#ifdef CONFIG_ARCH_OMAP1
|
||||
struct cpufreq_freqs freqs;
|
||||
+#endif
|
||||
+#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
+ unsigned long freq;
|
||||
+ struct device *mpu_dev = omap2_get_mpuss_device();
|
||||
+#endif
|
||||
int ret = 0;
|
||||
|
||||
/* Ensure desired rate is within allowed range. Some govenors
|
||||
@@ -83,13 +100,13 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
if (target_freq > policy->max)
|
||||
target_freq = policy->max;
|
||||
|
||||
+#ifdef CONFIG_ARCH_OMAP1
|
||||
freqs.old = omap_getspeed(0);
|
||||
freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
|
||||
freqs.cpu = 0;
|
||||
|
||||
if (freqs.old == freqs.new)
|
||||
return ret;
|
||||
-
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
#ifdef CONFIG_CPU_FREQ_DEBUG
|
||||
printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n",
|
||||
@@ -97,7 +114,11 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
#endif
|
||||
ret = clk_set_rate(mpu_clk, freqs.new * 1000);
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
-
|
||||
+#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
+ freq = target_freq * 1000;
|
||||
+ if (opp_find_freq_ceil(mpu_dev, &freq))
|
||||
+ omap_pm_cpu_set_freq(freq);
|
||||
+#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -114,7 +135,14 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
|
||||
policy->cur = policy->min = policy->max = omap_getspeed(0);
|
||||
|
||||
- clk_init_cpufreq_table(&freq_table);
|
||||
+ if (!cpu_is_omap34xx()) {
|
||||
+ clk_init_cpufreq_table(&freq_table);
|
||||
+ } else {
|
||||
+ struct device *mpu_dev = omap2_get_mpuss_device();
|
||||
+
|
||||
+ opp_init_cpufreq_table(mpu_dev, &freq_table);
|
||||
+ }
|
||||
+
|
||||
if (freq_table) {
|
||||
result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
if (!result)
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
From 86227f1eb341e571163464cb0a412ed2179f2541 Mon Sep 17 00:00:00 2001
|
||||
From: Silesh C V <silesh@ti.com>
|
||||
Date: Wed, 29 Sep 2010 14:52:54 +0530
|
||||
Subject: [PATCH 4/8] OMAP: PM: CPUFREQ: Fix conditional compilation
|
||||
|
||||
Fix conditional compilation. A conditional expresiion
|
||||
should follow "#elif", in this case #elif clause should
|
||||
check whether CONFIG_ARCH_OMAP3 is defined or not
|
||||
(ie. defined(CONFIG_ARCH_OMAP3)) rather than checking for
|
||||
the value of the macro.
|
||||
|
||||
Signed-off-by: Silesh C V <silesh@ti.com>
|
||||
---
|
||||
arch/arm/plat-omap/cpu-omap.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
|
||||
index f0f9430..c3ac065 100644
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ b/arch/arm/plat-omap/cpu-omap.c
|
||||
@@ -41,7 +41,7 @@ static struct cpufreq_frequency_table *freq_table;
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP1
|
||||
#define MPU_CLK "mpu"
|
||||
-#elif CONFIG_ARCH_OMAP3
|
||||
+#elif defined(CONFIG_ARCH_OMAP3)
|
||||
#define MPU_CLK "arm_fck"
|
||||
#else
|
||||
#define MPU_CLK "virt_prcm_set"
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
From 4764137dd613362656726a15cb8184724aeb99bb Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
Date: Tue, 16 Nov 2010 11:48:41 -0800
|
||||
Subject: [PATCH 5/8] cpufreq: fixup after new OPP layer merged
|
||||
|
||||
---
|
||||
arch/arm/plat-omap/cpu-omap.c | 3 ++-
|
||||
1 files changed, 2 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
|
||||
index c3ac065..9cd2709 100644
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ b/arch/arm/plat-omap/cpu-omap.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
+#include <linux/opp.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <plat/clock.h>
|
||||
@@ -32,7 +33,7 @@
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
#include <plat/omap-pm.h>
|
||||
-#include <plat/opp.h>
|
||||
+#include <plat/common.h>
|
||||
#endif
|
||||
|
||||
#define VERY_HI_RATE 900000000
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,669 @@
|
||||
From e16548716c5cbc3c9885d05f1654d83d5411a3a7 Mon Sep 17 00:00:00 2001
|
||||
From: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Date: Mon, 14 Mar 2011 17:08:48 +0530
|
||||
Subject: [PATCH 6/8] OMAP: cpufreq: Split OMAP1 and OMAP2PLUS CPUfreq drivers.
|
||||
|
||||
This patch is an attempt to cleanup the #ifdeferry in the
|
||||
omap CPUfreq drivers.
|
||||
|
||||
The split betwenn OMAP1 and OMAP2PLUS is logical because
|
||||
- OMAP1 doesn't support opp layer.
|
||||
- OMAP1 build is seperate from omap2plus.
|
||||
|
||||
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Cc: Kevin Hilman <khilman@ti.com>
|
||||
Cc: Vishwanath BS <vishwanath.bs@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap1/Makefile | 3 +
|
||||
arch/arm/mach-omap1/omap1-cpufreq.c | 176 ++++++++++++++++++++++++++
|
||||
arch/arm/mach-omap2/Makefile | 3 +
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 201 ++++++++++++++++++++++++++++++
|
||||
arch/arm/plat-omap/Makefile | 1 -
|
||||
arch/arm/plat-omap/cpu-omap.c | 204 -------------------------------
|
||||
6 files changed, 383 insertions(+), 205 deletions(-)
|
||||
create mode 100644 arch/arm/mach-omap1/omap1-cpufreq.c
|
||||
create mode 100644 arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
delete mode 100644 arch/arm/plat-omap/cpu-omap.c
|
||||
|
||||
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
|
||||
index af98117..e5082b0 100644
|
||||
--- a/arch/arm/mach-omap1/Makefile
|
||||
+++ b/arch/arm/mach-omap1/Makefile
|
||||
@@ -10,6 +10,9 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
|
||||
|
||||
obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o
|
||||
|
||||
+# CPUFREQ driver
|
||||
+obj-$(CONFIG_CPU_FREQ) += omap1-cpufreq.o
|
||||
+
|
||||
# Power Management
|
||||
obj-$(CONFIG_PM) += pm.o sleep.o pm_bus.o
|
||||
|
||||
diff --git a/arch/arm/mach-omap1/omap1-cpufreq.c b/arch/arm/mach-omap1/omap1-cpufreq.c
|
||||
new file mode 100644
|
||||
index 0000000..682cdc8
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-omap1/omap1-cpufreq.c
|
||||
@@ -0,0 +1,176 @@
|
||||
+/*
|
||||
+ * OMAP1 cpufreq driver
|
||||
+ *
|
||||
+ * CPU frequency scaling for OMAP
|
||||
+ *
|
||||
+ * Copyright (C) 2005 Nokia Corporation
|
||||
+ * Written by Tony Lindgren <tony@atomide.com>
|
||||
+ *
|
||||
+ * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
|
||||
+ *
|
||||
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
|
||||
+ * Updated to support OMAP3
|
||||
+ * Rajendra Nayak <rnayak@ti.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License version 2 as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/sched.h>
|
||||
+#include <linux/cpufreq.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/opp.h>
|
||||
+
|
||||
+#include <asm/system.h>
|
||||
+
|
||||
+#include <plat/clock.h>
|
||||
+#include <plat/omap-pm.h>
|
||||
+
|
||||
+#include <mach/hardware.h>
|
||||
+
|
||||
+#define VERY_HI_RATE 900000000
|
||||
+
|
||||
+static struct cpufreq_frequency_table *freq_table;
|
||||
+static struct clk *mpu_clk;
|
||||
+
|
||||
+static int omap_verify_speed(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ if (freq_table)
|
||||
+ return cpufreq_frequency_table_verify(policy, freq_table);
|
||||
+
|
||||
+ if (policy->cpu)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
+ policy->cpuinfo.max_freq);
|
||||
+
|
||||
+ policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000;
|
||||
+ policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000;
|
||||
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
+ policy->cpuinfo.max_freq);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static unsigned int omap_getspeed(unsigned int cpu)
|
||||
+{
|
||||
+ unsigned long rate;
|
||||
+
|
||||
+ if (cpu)
|
||||
+ return 0;
|
||||
+
|
||||
+ rate = clk_get_rate(mpu_clk) / 1000;
|
||||
+ return rate;
|
||||
+}
|
||||
+
|
||||
+static int omap_target(struct cpufreq_policy *policy,
|
||||
+ unsigned int target_freq,
|
||||
+ unsigned int relation)
|
||||
+{
|
||||
+ struct cpufreq_freqs freqs;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ /* Ensure desired rate is within allowed range. Some govenors
|
||||
+ * (ondemand) will just pass target_freq=0 to get the minimum. */
|
||||
+ if (target_freq < policy->min)
|
||||
+ target_freq = policy->min;
|
||||
+ if (target_freq > policy->max)
|
||||
+ target_freq = policy->max;
|
||||
+
|
||||
+ freqs.old = omap_getspeed(0);
|
||||
+ freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
|
||||
+ freqs.cpu = 0;
|
||||
+
|
||||
+ if (freqs.old == freqs.new)
|
||||
+ return ret;
|
||||
+
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
+
|
||||
+#ifdef CONFIG_CPU_FREQ_DEBUG
|
||||
+ pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
|
||||
+#endif
|
||||
+ ret = clk_set_rate(mpu_clk, freqs.new * 1000);
|
||||
+
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int __init omap_cpu_init(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ int result = 0;
|
||||
+
|
||||
+ mpu_clk = clk_get(NULL, "mpu");
|
||||
+ if (IS_ERR(mpu_clk))
|
||||
+ return PTR_ERR(mpu_clk);
|
||||
+
|
||||
+ if (policy->cpu != 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ policy->cur = policy->min = policy->max = omap_getspeed(0);
|
||||
+
|
||||
+ clk_init_cpufreq_table(&freq_table);
|
||||
+
|
||||
+ if (freq_table) {
|
||||
+ result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
+ if (!result)
|
||||
+ cpufreq_frequency_table_get_attr(freq_table,
|
||||
+ policy->cpu);
|
||||
+ } else {
|
||||
+ policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
|
||||
+ policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
|
||||
+ VERY_HI_RATE) / 1000;
|
||||
+ }
|
||||
+
|
||||
+ policy->min = policy->cpuinfo.min_freq;
|
||||
+ policy->max = policy->cpuinfo.max_freq;
|
||||
+ policy->cur = omap_getspeed(0);
|
||||
+
|
||||
+ /* FIXME: what's the actual transition time? */
|
||||
+ policy->cpuinfo.transition_latency = 300 * 1000;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int omap_cpu_exit(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ clk_exit_cpufreq_table(&freq_table);
|
||||
+ clk_put(mpu_clk);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct freq_attr *omap_cpufreq_attr[] = {
|
||||
+ &cpufreq_freq_attr_scaling_available_freqs,
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static struct cpufreq_driver omap_driver = {
|
||||
+ .flags = CPUFREQ_STICKY,
|
||||
+ .verify = omap_verify_speed,
|
||||
+ .target = omap_target,
|
||||
+ .get = omap_getspeed,
|
||||
+ .init = omap_cpu_init,
|
||||
+ .exit = omap_cpu_exit,
|
||||
+ .name = "omap1",
|
||||
+ .attr = omap_cpufreq_attr,
|
||||
+};
|
||||
+
|
||||
+static int __init omap_cpufreq_init(void)
|
||||
+{
|
||||
+ return cpufreq_register_driver(&omap_driver);
|
||||
+}
|
||||
+
|
||||
+static void __exit omap_cpufreq_exit(void)
|
||||
+{
|
||||
+ cpufreq_unregister_driver(&omap_driver);
|
||||
+}
|
||||
+
|
||||
+MODULE_DESCRIPTION("cpufreq driver for OMAP1 SOCs");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+module_init(omap_cpufreq_init);
|
||||
+module_exit(omap_cpufreq_exit);
|
||||
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
|
||||
index 05cd983..e9c2445 100644
|
||||
--- a/arch/arm/mach-omap2/Makefile
|
||||
+++ b/arch/arm/mach-omap2/Makefile
|
||||
@@ -56,6 +56,9 @@ obj-$(CONFIG_ARCH_OMAP3) += opp3xxx_data.o
|
||||
obj-$(CONFIG_ARCH_OMAP4) += opp4xxx_data.o
|
||||
endif
|
||||
|
||||
+# CPUFREQ driver
|
||||
+obj-$(CONFIG_CPU_FREQ) += omap2plus-cpufreq.o
|
||||
+
|
||||
# Power Management
|
||||
ifeq ($(CONFIG_PM),y)
|
||||
obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
new file mode 100644
|
||||
index 0000000..14f84cc
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -0,0 +1,201 @@
|
||||
+/*
|
||||
+ * OMAP2PLUS cpufreq driver
|
||||
+ *
|
||||
+ * CPU frequency scaling for OMAP
|
||||
+ *
|
||||
+ * Copyright (C) 2005 Nokia Corporation
|
||||
+ * Written by Tony Lindgren <tony@atomide.com>
|
||||
+ *
|
||||
+ * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
|
||||
+ *
|
||||
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
|
||||
+ * Updated to support OMAP3
|
||||
+ * Rajendra Nayak <rnayak@ti.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License version 2 as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/sched.h>
|
||||
+#include <linux/cpufreq.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/opp.h>
|
||||
+
|
||||
+#include <asm/system.h>
|
||||
+#include <asm/smp_plat.h>
|
||||
+
|
||||
+#include <plat/clock.h>
|
||||
+#include <plat/omap-pm.h>
|
||||
+#include <plat/common.h>
|
||||
+
|
||||
+#include <mach/hardware.h>
|
||||
+
|
||||
+#define VERY_HI_RATE 900000000
|
||||
+
|
||||
+static struct cpufreq_frequency_table *freq_table;
|
||||
+static struct clk *mpu_clk;
|
||||
+
|
||||
+static int omap_verify_speed(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ if (freq_table)
|
||||
+ return cpufreq_frequency_table_verify(policy, freq_table);
|
||||
+
|
||||
+ if (policy->cpu)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
+ policy->cpuinfo.max_freq);
|
||||
+
|
||||
+ policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000;
|
||||
+ policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000;
|
||||
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
+ policy->cpuinfo.max_freq);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static unsigned int omap_getspeed(unsigned int cpu)
|
||||
+{
|
||||
+ unsigned long rate;
|
||||
+
|
||||
+ if (cpu)
|
||||
+ return 0;
|
||||
+
|
||||
+ rate = clk_get_rate(mpu_clk) / 1000;
|
||||
+ return rate;
|
||||
+}
|
||||
+
|
||||
+static int omap_target(struct cpufreq_policy *policy,
|
||||
+ unsigned int target_freq,
|
||||
+ unsigned int relation)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ struct cpufreq_freqs freqs;
|
||||
+
|
||||
+ /* Ensure desired rate is within allowed range. Some govenors
|
||||
+ * (ondemand) will just pass target_freq=0 to get the minimum. */
|
||||
+ if (target_freq < policy->min)
|
||||
+ target_freq = policy->min;
|
||||
+ if (target_freq > policy->max)
|
||||
+ target_freq = policy->max;
|
||||
+
|
||||
+ freqs.old = omap_getspeed(0);
|
||||
+ freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
|
||||
+ freqs.cpu = 0;
|
||||
+
|
||||
+ if (freqs.old == freqs.new)
|
||||
+ return ret;
|
||||
+
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
+
|
||||
+#ifdef CONFIG_CPU_FREQ_DEBUG
|
||||
+ pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
|
||||
+#endif
|
||||
+
|
||||
+ ret = clk_set_rate(mpu_clk, freqs.new * 1000);
|
||||
+
|
||||
+ /*
|
||||
+ * Generic CPUFREQ driver jiffy update is under !SMP. So jiffies
|
||||
+ * won't get updated when UP machine cpufreq build with
|
||||
+ * CONFIG_SMP enabled. Below code is added only to manage that
|
||||
+ * scenario
|
||||
+ */
|
||||
+ if (!is_smp())
|
||||
+ loops_per_jiffy =
|
||||
+ cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new);
|
||||
+
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ int result = 0;
|
||||
+ struct device *mpu_dev;
|
||||
+
|
||||
+ if (cpu_is_omap24xx())
|
||||
+ mpu_clk = clk_get(NULL, "virt_prcm_set");
|
||||
+ else if (cpu_is_omap34xx())
|
||||
+ mpu_clk = clk_get(NULL, "dpll1_ck");
|
||||
+ else if (cpu_is_omap34xx())
|
||||
+ mpu_clk = clk_get(NULL, "dpll_mpu_ck");
|
||||
+
|
||||
+ if (IS_ERR(mpu_clk))
|
||||
+ return PTR_ERR(mpu_clk);
|
||||
+
|
||||
+ if (policy->cpu != 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ policy->cur = policy->min = policy->max = omap_getspeed(0);
|
||||
+
|
||||
+ mpu_dev = omap2_get_mpuss_device();
|
||||
+ if (!mpu_dev) {
|
||||
+ pr_warning("%s: unable to get the mpu device\n", __func__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ opp_init_cpufreq_table(mpu_dev, &freq_table);
|
||||
+
|
||||
+ if (freq_table) {
|
||||
+ result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
+ if (!result)
|
||||
+ cpufreq_frequency_table_get_attr(freq_table,
|
||||
+ policy->cpu);
|
||||
+ } else {
|
||||
+ policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
|
||||
+ policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
|
||||
+ VERY_HI_RATE) / 1000;
|
||||
+ }
|
||||
+
|
||||
+ policy->min = policy->cpuinfo.min_freq;
|
||||
+ policy->max = policy->cpuinfo.max_freq;
|
||||
+ policy->cur = omap_getspeed(0);
|
||||
+
|
||||
+ /* FIXME: what's the actual transition time? */
|
||||
+ policy->cpuinfo.transition_latency = 300 * 1000;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int omap_cpu_exit(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ clk_exit_cpufreq_table(&freq_table);
|
||||
+ clk_put(mpu_clk);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct freq_attr *omap_cpufreq_attr[] = {
|
||||
+ &cpufreq_freq_attr_scaling_available_freqs,
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static struct cpufreq_driver omap_driver = {
|
||||
+ .flags = CPUFREQ_STICKY,
|
||||
+ .verify = omap_verify_speed,
|
||||
+ .target = omap_target,
|
||||
+ .get = omap_getspeed,
|
||||
+ .init = omap_cpu_init,
|
||||
+ .exit = omap_cpu_exit,
|
||||
+ .name = "omap2plus",
|
||||
+ .attr = omap_cpufreq_attr,
|
||||
+};
|
||||
+
|
||||
+static int __init omap_cpufreq_init(void)
|
||||
+{
|
||||
+ return cpufreq_register_driver(&omap_driver);
|
||||
+}
|
||||
+
|
||||
+static void __exit omap_cpufreq_exit(void)
|
||||
+{
|
||||
+ cpufreq_unregister_driver(&omap_driver);
|
||||
+}
|
||||
+
|
||||
+MODULE_DESCRIPTION("cpufreq driver for OMAP2PLUS SOCs");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+module_init(omap_cpufreq_init);
|
||||
+module_exit(omap_cpufreq_exit);
|
||||
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
|
||||
index a4a1285..ec7862e 100644
|
||||
--- a/arch/arm/plat-omap/Makefile
|
||||
+++ b/arch/arm/plat-omap/Makefile
|
||||
@@ -21,7 +21,6 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
|
||||
obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o
|
||||
obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o
|
||||
|
||||
-obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
|
||||
obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
|
||||
obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o
|
||||
obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
|
||||
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
|
||||
deleted file mode 100644
|
||||
index 9cd2709..0000000
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ /dev/null
|
||||
@@ -1,204 +0,0 @@
|
||||
-/*
|
||||
- * linux/arch/arm/plat-omap/cpu-omap.c
|
||||
- *
|
||||
- * CPU frequency scaling for OMAP
|
||||
- *
|
||||
- * Copyright (C) 2005 Nokia Corporation
|
||||
- * Written by Tony Lindgren <tony@atomide.com>
|
||||
- *
|
||||
- * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
|
||||
- *
|
||||
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
|
||||
- * Updated to support OMAP3
|
||||
- * Rajendra Nayak <rnayak@ti.com>
|
||||
- *
|
||||
- * This program is free software; you can redistribute it and/or modify
|
||||
- * it under the terms of the GNU General Public License version 2 as
|
||||
- * published by the Free Software Foundation.
|
||||
- */
|
||||
-#include <linux/types.h>
|
||||
-#include <linux/kernel.h>
|
||||
-#include <linux/sched.h>
|
||||
-#include <linux/cpufreq.h>
|
||||
-#include <linux/delay.h>
|
||||
-#include <linux/init.h>
|
||||
-#include <linux/err.h>
|
||||
-#include <linux/clk.h>
|
||||
-#include <linux/io.h>
|
||||
-#include <linux/opp.h>
|
||||
-
|
||||
-#include <mach/hardware.h>
|
||||
-#include <plat/clock.h>
|
||||
-#include <asm/system.h>
|
||||
-
|
||||
-#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
-#include <plat/omap-pm.h>
|
||||
-#include <plat/common.h>
|
||||
-#endif
|
||||
-
|
||||
-#define VERY_HI_RATE 900000000
|
||||
-
|
||||
-static struct cpufreq_frequency_table *freq_table;
|
||||
-
|
||||
-#ifdef CONFIG_ARCH_OMAP1
|
||||
-#define MPU_CLK "mpu"
|
||||
-#elif defined(CONFIG_ARCH_OMAP3)
|
||||
-#define MPU_CLK "arm_fck"
|
||||
-#else
|
||||
-#define MPU_CLK "virt_prcm_set"
|
||||
-#endif
|
||||
-
|
||||
-static struct clk *mpu_clk;
|
||||
-
|
||||
-/* TODO: Add support for SDRAM timing changes */
|
||||
-
|
||||
-static int omap_verify_speed(struct cpufreq_policy *policy)
|
||||
-{
|
||||
- if (freq_table)
|
||||
- return cpufreq_frequency_table_verify(policy, freq_table);
|
||||
-
|
||||
- if (policy->cpu)
|
||||
- return -EINVAL;
|
||||
-
|
||||
- cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
- policy->cpuinfo.max_freq);
|
||||
-
|
||||
- policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000;
|
||||
- policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000;
|
||||
- cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
- policy->cpuinfo.max_freq);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static unsigned int omap_getspeed(unsigned int cpu)
|
||||
-{
|
||||
- unsigned long rate;
|
||||
-
|
||||
- if (cpu)
|
||||
- return 0;
|
||||
-
|
||||
- rate = clk_get_rate(mpu_clk) / 1000;
|
||||
- return rate;
|
||||
-}
|
||||
-
|
||||
-static int omap_target(struct cpufreq_policy *policy,
|
||||
- unsigned int target_freq,
|
||||
- unsigned int relation)
|
||||
-{
|
||||
-#ifdef CONFIG_ARCH_OMAP1
|
||||
- struct cpufreq_freqs freqs;
|
||||
-#endif
|
||||
-#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
- unsigned long freq;
|
||||
- struct device *mpu_dev = omap2_get_mpuss_device();
|
||||
-#endif
|
||||
- int ret = 0;
|
||||
-
|
||||
- /* Ensure desired rate is within allowed range. Some govenors
|
||||
- * (ondemand) will just pass target_freq=0 to get the minimum. */
|
||||
- if (target_freq < policy->min)
|
||||
- target_freq = policy->min;
|
||||
- if (target_freq > policy->max)
|
||||
- target_freq = policy->max;
|
||||
-
|
||||
-#ifdef CONFIG_ARCH_OMAP1
|
||||
- freqs.old = omap_getspeed(0);
|
||||
- freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
|
||||
- freqs.cpu = 0;
|
||||
-
|
||||
- if (freqs.old == freqs.new)
|
||||
- return ret;
|
||||
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
-#ifdef CONFIG_CPU_FREQ_DEBUG
|
||||
- printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n",
|
||||
- freqs.old, freqs.new);
|
||||
-#endif
|
||||
- ret = clk_set_rate(mpu_clk, freqs.new * 1000);
|
||||
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
-#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
- freq = target_freq * 1000;
|
||||
- if (opp_find_freq_ceil(mpu_dev, &freq))
|
||||
- omap_pm_cpu_set_freq(freq);
|
||||
-#endif
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
-{
|
||||
- int result = 0;
|
||||
-
|
||||
- mpu_clk = clk_get(NULL, MPU_CLK);
|
||||
- if (IS_ERR(mpu_clk))
|
||||
- return PTR_ERR(mpu_clk);
|
||||
-
|
||||
- if (policy->cpu != 0)
|
||||
- return -EINVAL;
|
||||
-
|
||||
- policy->cur = policy->min = policy->max = omap_getspeed(0);
|
||||
-
|
||||
- if (!cpu_is_omap34xx()) {
|
||||
- clk_init_cpufreq_table(&freq_table);
|
||||
- } else {
|
||||
- struct device *mpu_dev = omap2_get_mpuss_device();
|
||||
-
|
||||
- opp_init_cpufreq_table(mpu_dev, &freq_table);
|
||||
- }
|
||||
-
|
||||
- if (freq_table) {
|
||||
- result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
- if (!result)
|
||||
- cpufreq_frequency_table_get_attr(freq_table,
|
||||
- policy->cpu);
|
||||
- } else {
|
||||
- policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
|
||||
- policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
|
||||
- VERY_HI_RATE) / 1000;
|
||||
- }
|
||||
-
|
||||
- policy->min = policy->cpuinfo.min_freq;
|
||||
- policy->max = policy->cpuinfo.max_freq;
|
||||
- policy->cur = omap_getspeed(0);
|
||||
-
|
||||
- /* FIXME: what's the actual transition time? */
|
||||
- policy->cpuinfo.transition_latency = 300 * 1000;
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int omap_cpu_exit(struct cpufreq_policy *policy)
|
||||
-{
|
||||
- clk_exit_cpufreq_table(&freq_table);
|
||||
- clk_put(mpu_clk);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static struct freq_attr *omap_cpufreq_attr[] = {
|
||||
- &cpufreq_freq_attr_scaling_available_freqs,
|
||||
- NULL,
|
||||
-};
|
||||
-
|
||||
-static struct cpufreq_driver omap_driver = {
|
||||
- .flags = CPUFREQ_STICKY,
|
||||
- .verify = omap_verify_speed,
|
||||
- .target = omap_target,
|
||||
- .get = omap_getspeed,
|
||||
- .init = omap_cpu_init,
|
||||
- .exit = omap_cpu_exit,
|
||||
- .name = "omap",
|
||||
- .attr = omap_cpufreq_attr,
|
||||
-};
|
||||
-
|
||||
-static int __init omap_cpufreq_init(void)
|
||||
-{
|
||||
- return cpufreq_register_driver(&omap_driver);
|
||||
-}
|
||||
-
|
||||
-late_initcall(omap_cpufreq_init);
|
||||
-
|
||||
-/*
|
||||
- * if ever we want to remove this, upon cleanup call:
|
||||
- *
|
||||
- * cpufreq_unregister_driver()
|
||||
- * cpufreq_frequency_table_put_attr()
|
||||
- */
|
||||
-
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
From f375d3c39d2835929d34c2a046b8c43cea6d1467 Mon Sep 17 00:00:00 2001
|
||||
From: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Date: Mon, 14 Mar 2011 17:08:49 +0530
|
||||
Subject: [PATCH 7/8] OMAP2PLUS: cpufreq: Add SMP support to cater OMAP4430
|
||||
|
||||
On OMAP SMP configuartion, both processors share the voltage
|
||||
and clock. So both CPUs needs to be scaled together and hence
|
||||
needs software co-ordination.
|
||||
|
||||
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Cc: Kevin Hilman <khilman@ti.com>
|
||||
cc: Vishwanath BS <vishwanath.bs@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 73 ++++++++++++++++++++++++++-----
|
||||
1 files changed, 62 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index 14f84cc..8d472f6 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -26,9 +26,11 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/opp.h>
|
||||
+#include <linux/cpu.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/smp_plat.h>
|
||||
+#include <asm/cpu.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/omap-pm.h>
|
||||
@@ -63,7 +65,7 @@ static unsigned int omap_getspeed(unsigned int cpu)
|
||||
{
|
||||
unsigned long rate;
|
||||
|
||||
- if (cpu)
|
||||
+ if (cpu >= NR_CPUS)
|
||||
return 0;
|
||||
|
||||
rate = clk_get_rate(mpu_clk) / 1000;
|
||||
@@ -74,9 +76,13 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
{
|
||||
- int ret = 0;
|
||||
+ int i, ret = 0;
|
||||
struct cpufreq_freqs freqs;
|
||||
|
||||
+ /* Changes not allowed until all CPUs are online */
|
||||
+ if (is_smp() && (num_online_cpus() < NR_CPUS))
|
||||
+ return ret;
|
||||
+
|
||||
/* Ensure desired rate is within allowed range. Some govenors
|
||||
* (ondemand) will just pass target_freq=0 to get the minimum. */
|
||||
if (target_freq < policy->min)
|
||||
@@ -84,15 +90,25 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
if (target_freq > policy->max)
|
||||
target_freq = policy->max;
|
||||
|
||||
- freqs.old = omap_getspeed(0);
|
||||
+ freqs.old = omap_getspeed(policy->cpu);
|
||||
freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
|
||||
- freqs.cpu = 0;
|
||||
+ freqs.cpu = policy->cpu;
|
||||
|
||||
if (freqs.old == freqs.new)
|
||||
return ret;
|
||||
|
||||
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
+ if (!is_smp()) {
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
+ goto set_freq;
|
||||
+ }
|
||||
+
|
||||
+ /* notifiers */
|
||||
+ for_each_cpu(i, policy->cpus) {
|
||||
+ freqs.cpu = i;
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
+ }
|
||||
|
||||
+set_freq:
|
||||
#ifdef CONFIG_CPU_FREQ_DEBUG
|
||||
pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
|
||||
#endif
|
||||
@@ -105,12 +121,33 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
* CONFIG_SMP enabled. Below code is added only to manage that
|
||||
* scenario
|
||||
*/
|
||||
- if (!is_smp())
|
||||
+ freqs.new = omap_getspeed(policy->cpu);
|
||||
+ if (!is_smp()) {
|
||||
loops_per_jiffy =
|
||||
cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new);
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
+ goto skip_lpj;
|
||||
+ }
|
||||
|
||||
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
+#ifdef CONFIG_SMP
|
||||
+ /*
|
||||
+ * Note that loops_per_jiffy is not updated on SMP systems in
|
||||
+ * cpufreq driver. So, update the per-CPU loops_per_jiffy value
|
||||
+ * on frequency transition. We need to update all dependent CPUs.
|
||||
+ */
|
||||
+ for_each_cpu(i, policy->cpus)
|
||||
+ per_cpu(cpu_data, i).loops_per_jiffy =
|
||||
+ cpufreq_scale(per_cpu(cpu_data, i).loops_per_jiffy,
|
||||
+ freqs.old, freqs.new);
|
||||
+#endif
|
||||
|
||||
+ /* notifiers */
|
||||
+ for_each_cpu(i, policy->cpus) {
|
||||
+ freqs.cpu = i;
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
+ }
|
||||
+
|
||||
+skip_lpj:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -118,6 +155,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
int result = 0;
|
||||
struct device *mpu_dev;
|
||||
+ static cpumask_var_t cpumask;
|
||||
|
||||
if (cpu_is_omap24xx())
|
||||
mpu_clk = clk_get(NULL, "virt_prcm_set");
|
||||
@@ -129,12 +167,12 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
if (IS_ERR(mpu_clk))
|
||||
return PTR_ERR(mpu_clk);
|
||||
|
||||
- if (policy->cpu != 0)
|
||||
+ if (policy->cpu >= NR_CPUS)
|
||||
return -EINVAL;
|
||||
|
||||
- policy->cur = policy->min = policy->max = omap_getspeed(0);
|
||||
-
|
||||
+ policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
|
||||
mpu_dev = omap2_get_mpuss_device();
|
||||
+
|
||||
if (!mpu_dev) {
|
||||
pr_warning("%s: unable to get the mpu device\n", __func__);
|
||||
return -EINVAL;
|
||||
@@ -154,7 +192,20 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
|
||||
policy->min = policy->cpuinfo.min_freq;
|
||||
policy->max = policy->cpuinfo.max_freq;
|
||||
- policy->cur = omap_getspeed(0);
|
||||
+ policy->cur = omap_getspeed(policy->cpu);
|
||||
+
|
||||
+ /*
|
||||
+ * On OMAP SMP configuartion, both processors share the voltage
|
||||
+ * and clock. So both CPUs needs to be scaled together and hence
|
||||
+ * needs software co-ordination. Use cpufreq affected_cpus
|
||||
+ * interface to handle this scenario. Additional is_smp() check
|
||||
+ * is to keep SMP_ON_UP build working.
|
||||
+ */
|
||||
+ if (is_smp()) {
|
||||
+ policy->shared_type = CPUFREQ_SHARED_TYPE_ANY;
|
||||
+ cpumask_or(cpumask, cpumask_of(policy->cpu), cpumask);
|
||||
+ cpumask_copy(policy->cpus, cpumask);
|
||||
+ }
|
||||
|
||||
/* FIXME: what's the actual transition time? */
|
||||
policy->cpuinfo.transition_latency = 300 * 1000;
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
From 6e101764a47cb6975a555e2237843ad391a542a4 Mon Sep 17 00:00:00 2001
|
||||
From: Jarkko Nikula <jhnikula@gmail.com>
|
||||
Date: Thu, 14 Apr 2011 16:21:58 +0300
|
||||
Subject: [PATCH 8/8] OMAP2PLUS: cpufreq: Fix typo when attempting to set mpu_clk for OMAP4
|
||||
|
||||
Fix this typo as there is no dpll_mpu_ck for OMAP3 and code flow is clearly
|
||||
trying to set mpu_clk for OMAP4 for which this dpll_mpu_ck is available.
|
||||
|
||||
Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index 8d472f6..d53ce23 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -161,7 +161,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
mpu_clk = clk_get(NULL, "virt_prcm_set");
|
||||
else if (cpu_is_omap34xx())
|
||||
mpu_clk = clk_get(NULL, "dpll1_ck");
|
||||
- else if (cpu_is_omap34xx())
|
||||
+ else if (cpu_is_omap44xx())
|
||||
mpu_clk = clk_get(NULL, "dpll_mpu_ck");
|
||||
|
||||
if (IS_ERR(mpu_clk))
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
From 988f50cb51d18e81ed2f7673a09694d28c9d086a Mon Sep 17 00:00:00 2001
|
||||
From: Rajendra Nayak <rnayak@ti.com>
|
||||
Date: Tue, 5 Apr 2011 15:22:31 +0530
|
||||
Subject: [PATCH 1/6] OMAP2+: clockdomain: Add an api to read idle mode
|
||||
|
||||
Add a clockdomain api to check if hardware supervised
|
||||
idle transitions are enabled on a clockdomain.
|
||||
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/clockdomain.c | 21 +++++++++++++++++++++
|
||||
arch/arm/mach-omap2/clockdomain.h | 3 +++
|
||||
2 files changed, 24 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
|
||||
index 6cb6c03..2ab3686 100644
|
||||
--- a/arch/arm/mach-omap2/clockdomain.c
|
||||
+++ b/arch/arm/mach-omap2/clockdomain.c
|
||||
@@ -795,6 +795,27 @@ void clkdm_deny_idle(struct clockdomain *clkdm)
|
||||
arch_clkdm->clkdm_deny_idle(clkdm);
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * clkdm_is_idle - Check if the clkdm hwsup/autoidle is enabled
|
||||
+ * @clkdm: struct clockdomain *
|
||||
+ *
|
||||
+ * Returns true if the clockdomain is in hardware-supervised
|
||||
+ * idle mode, or 0 otherwise.
|
||||
+ *
|
||||
+ */
|
||||
+int clkdm_is_idle(struct clockdomain *clkdm)
|
||||
+{
|
||||
+ if (!clkdm)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!arch_clkdm || !arch_clkdm->clkdm_is_idle)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ pr_debug("clockdomain: reading idle state for %s\n", clkdm->name);
|
||||
+
|
||||
+ return arch_clkdm->clkdm_is_idle(clkdm);
|
||||
+}
|
||||
+
|
||||
|
||||
/* Clockdomain-to-clock framework interface code */
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
|
||||
index 5823584..085ed82 100644
|
||||
--- a/arch/arm/mach-omap2/clockdomain.h
|
||||
+++ b/arch/arm/mach-omap2/clockdomain.h
|
||||
@@ -138,6 +138,7 @@ struct clockdomain {
|
||||
* @clkdm_wakeup: Force a clockdomain to wakeup
|
||||
* @clkdm_allow_idle: Enable hw supervised idle transitions for clock domain
|
||||
* @clkdm_deny_idle: Disable hw supervised idle transitions for clock domain
|
||||
+ * @clkdm_is_idle: Check if hw supervised idle transitions are enabled
|
||||
* @clkdm_clk_enable: Put the clkdm in right state for a clock enable
|
||||
* @clkdm_clk_disable: Put the clkdm in right state for a clock disable
|
||||
*/
|
||||
@@ -154,6 +155,7 @@ struct clkdm_ops {
|
||||
int (*clkdm_wakeup)(struct clockdomain *clkdm);
|
||||
void (*clkdm_allow_idle)(struct clockdomain *clkdm);
|
||||
void (*clkdm_deny_idle)(struct clockdomain *clkdm);
|
||||
+ int (*clkdm_is_idle)(struct clockdomain *clkdm);
|
||||
int (*clkdm_clk_enable)(struct clockdomain *clkdm);
|
||||
int (*clkdm_clk_disable)(struct clockdomain *clkdm);
|
||||
};
|
||||
@@ -177,6 +179,7 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm);
|
||||
|
||||
void clkdm_allow_idle(struct clockdomain *clkdm);
|
||||
void clkdm_deny_idle(struct clockdomain *clkdm);
|
||||
+int clkdm_is_idle(struct clockdomain *clkdm);
|
||||
|
||||
int clkdm_wakeup(struct clockdomain *clkdm);
|
||||
int clkdm_sleep(struct clockdomain *clkdm);
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
From e3ba8d41bfafd782f3ee7f8930d9bf393986c662 Mon Sep 17 00:00:00 2001
|
||||
From: Rajendra Nayak <rnayak@ti.com>
|
||||
Date: Tue, 5 Apr 2011 15:22:36 +0530
|
||||
Subject: [PATCH 2/6] OMAP2+: clockdomain: Add SoC support for clkdm_is_idle
|
||||
|
||||
Add the SoC specific implemenation for clkdm_is_idle
|
||||
for OMAP2/3 and OMAP4.
|
||||
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | 12 ++++++++++++
|
||||
arch/arm/mach-omap2/clockdomain44xx.c | 7 +++++++
|
||||
2 files changed, 19 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
|
||||
index 48d0db7..db49baa 100644
|
||||
--- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
|
||||
+++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
|
||||
@@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
+#include <linux/errno.h>
|
||||
#include <plat/prcm.h>
|
||||
#include "prm.h"
|
||||
#include "prm2xxx_3xxx.h"
|
||||
@@ -146,6 +147,15 @@ static void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
|
||||
_clkdm_del_autodeps(clkdm);
|
||||
}
|
||||
|
||||
+static int omap2_clkdm_is_idle(struct clockdomain *clkdm)
|
||||
+{
|
||||
+ if (!clkdm->clktrctrl_mask)
|
||||
+ return -1;
|
||||
+
|
||||
+ return omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
|
||||
+ clkdm->clktrctrl_mask);
|
||||
+}
|
||||
+
|
||||
static void _enable_hwsup(struct clockdomain *clkdm)
|
||||
{
|
||||
if (cpu_is_omap24xx())
|
||||
@@ -252,6 +262,7 @@ struct clkdm_ops omap2_clkdm_operations = {
|
||||
.clkdm_wakeup = omap2_clkdm_wakeup,
|
||||
.clkdm_allow_idle = omap2_clkdm_allow_idle,
|
||||
.clkdm_deny_idle = omap2_clkdm_deny_idle,
|
||||
+ .clkdm_is_idle = omap2_clkdm_is_idle,
|
||||
.clkdm_clk_enable = omap2_clkdm_clk_enable,
|
||||
.clkdm_clk_disable = omap2_clkdm_clk_disable,
|
||||
};
|
||||
@@ -269,6 +280,7 @@ struct clkdm_ops omap3_clkdm_operations = {
|
||||
.clkdm_wakeup = omap3_clkdm_wakeup,
|
||||
.clkdm_allow_idle = omap3_clkdm_allow_idle,
|
||||
.clkdm_deny_idle = omap3_clkdm_deny_idle,
|
||||
+ .clkdm_is_idle = omap2_clkdm_is_idle,
|
||||
.clkdm_clk_enable = omap2_clkdm_clk_enable,
|
||||
.clkdm_clk_disable = omap2_clkdm_clk_disable,
|
||||
};
|
||||
diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c
|
||||
index a1a4ecd..4b10727 100644
|
||||
--- a/arch/arm/mach-omap2/clockdomain44xx.c
|
||||
+++ b/arch/arm/mach-omap2/clockdomain44xx.c
|
||||
@@ -93,6 +93,12 @@ static void omap4_clkdm_deny_idle(struct clockdomain *clkdm)
|
||||
clkdm->cm_inst, clkdm->clkdm_offs);
|
||||
}
|
||||
|
||||
+static int omap4_clkdm_is_idle(struct clockdomain *clkdm)
|
||||
+{
|
||||
+ return omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
|
||||
+ clkdm->cm_inst, clkdm->clkdm_offs);
|
||||
+}
|
||||
+
|
||||
static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
|
||||
{
|
||||
bool hwsup = false;
|
||||
@@ -132,6 +138,7 @@ struct clkdm_ops omap4_clkdm_operations = {
|
||||
.clkdm_wakeup = omap4_clkdm_wakeup,
|
||||
.clkdm_allow_idle = omap4_clkdm_allow_idle,
|
||||
.clkdm_deny_idle = omap4_clkdm_deny_idle,
|
||||
+ .clkdm_is_idle = omap4_clkdm_is_idle,
|
||||
.clkdm_clk_enable = omap4_clkdm_clk_enable,
|
||||
.clkdm_clk_disable = omap4_clkdm_clk_disable,
|
||||
};
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
From 7cdc87071a4bb390ad5d7ddea210bd2b4d662114 Mon Sep 17 00:00:00 2001
|
||||
From: Rajendra Nayak <rnayak@ti.com>
|
||||
Date: Tue, 5 Apr 2011 15:22:41 +0530
|
||||
Subject: [PATCH 3/6] OMAP2+: PM: Initialise sleep_switch to a non-valid value
|
||||
|
||||
sleep_switch which is initialised to 0 in omap_set_pwrdm_state
|
||||
happens to be a valid sleep_switch type (FORCEWAKEUP_SWITCH)
|
||||
which are defined as
|
||||
#define FORCEWAKEUP_SWITCH 0
|
||||
#define LOWPOWERSTATE_SWITCH 1
|
||||
|
||||
This causes the function to wrongly program some clock domains
|
||||
even when the Powerdomain is in ON state.
|
||||
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/pm.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
|
||||
index 49486f5..d48813f 100644
|
||||
--- a/arch/arm/mach-omap2/pm.c
|
||||
+++ b/arch/arm/mach-omap2/pm.c
|
||||
@@ -106,7 +106,7 @@ static void omap2_init_processor_devices(void)
|
||||
int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
|
||||
{
|
||||
u32 cur_state;
|
||||
- int sleep_switch = 0;
|
||||
+ int sleep_switch = -1;
|
||||
int ret = 0;
|
||||
|
||||
if (pwrdm == NULL || IS_ERR(pwrdm))
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
From cec133850aa42c03d912c764aaa441677e782eca Mon Sep 17 00:00:00 2001
|
||||
From: Rajendra Nayak <rnayak@ti.com>
|
||||
Date: Tue, 5 Apr 2011 15:22:48 +0530
|
||||
Subject: [PATCH 4/6] OMAP2+: PM: idle clkdms only if already in idle
|
||||
|
||||
The omap_set_pwrdm_state function forces clockdomains
|
||||
to idle, without checking the existing idle state
|
||||
programmed, instead based solely on the HW capability
|
||||
of the clockdomain to support idle.
|
||||
This is wrong and the clockdomains should be idled
|
||||
post a state_switch *only* if idle transitions on the
|
||||
clockdomain were already enabled.
|
||||
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/pm.c | 4 +++-
|
||||
1 files changed, 3 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
|
||||
index d48813f..840b0e1 100644
|
||||
--- a/arch/arm/mach-omap2/pm.c
|
||||
+++ b/arch/arm/mach-omap2/pm.c
|
||||
@@ -108,6 +108,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
|
||||
u32 cur_state;
|
||||
int sleep_switch = -1;
|
||||
int ret = 0;
|
||||
+ int hwsup = 0;
|
||||
|
||||
if (pwrdm == NULL || IS_ERR(pwrdm))
|
||||
return -EINVAL;
|
||||
@@ -127,6 +128,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
|
||||
(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
|
||||
sleep_switch = LOWPOWERSTATE_SWITCH;
|
||||
} else {
|
||||
+ hwsup = clkdm_is_idle(pwrdm->pwrdm_clkdms[0]);
|
||||
clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
|
||||
pwrdm_wait_transition(pwrdm);
|
||||
sleep_switch = FORCEWAKEUP_SWITCH;
|
||||
@@ -142,7 +144,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
|
||||
|
||||
switch (sleep_switch) {
|
||||
case FORCEWAKEUP_SWITCH:
|
||||
- if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO)
|
||||
+ if (hwsup)
|
||||
clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
|
||||
else
|
||||
clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user