--- linux-mvl-dove-2.6.31.orig/MAINTAINERS +++ linux-mvl-dove-2.6.31/MAINTAINERS @@ -897,6 +897,12 @@ S: Maintained F: drivers/net/wireless/ath/ar9170/ +ATK0110 HWMON DRIVER +M: Luca Tettamanti +L: lm-sensors@lm-sensors.org +S: Maintained +F: drivers/hwmon/asus_atk0110.c + ATI_REMOTE2 DRIVER M: Ville Syrjala S: Maintained @@ -1986,7 +1992,7 @@ F: fs/* FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER -M: Riku Voipio +M: Riku Voipio L: lm-sensors@lm-sensors.org S: Maintained F: drivers/hwmon/f75375s.c --- linux-mvl-dove-2.6.31.orig/Makefile +++ linux-mvl-dove-2.6.31/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 31 -EXTRAVERSION = +EXTRAVERSION = .12 NAME = Man-Eating Seals of Antiquity # *DOCUMENTATION* @@ -330,14 +330,23 @@ AFLAGS_KERNEL = CFLAGS_GCOV = -fprofile-arcs -ftest-coverage +# Prefer linux-backports-modules +ifneq ($(KBUILD_SRC),) +ifneq ($(shell if test -e $(KBUILD_OUTPUT)/ubuntu-build; then echo yes; fi),yes) +UBUNTUINCLUDE := -I/usr/src/linux-headers-lbm-$(KERNELRELEASE) +endif +endif # Use LINUXINCLUDE when you must reference the include/ directory. # Needed to be compatible with the O= option -LINUXINCLUDE := -Iinclude \ +LINUXINCLUDE := $(UBUNTUINCLUDE) -Iinclude \ $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \ -I$(srctree)/arch/$(hdr-arch)/include \ -include include/linux/autoconf.h +# UBUNTU: Include our third party driver stuff too +LINUXINCLUDE += -Iubuntu/include $(if $(KBUILD_SRC),-I$(srctree)/ubuntu/include) + KBUILD_CPPFLAGS := -D__KERNEL__ KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ @@ -467,7 +476,7 @@ # Objects we will link into vmlinux / subdirs we need to visit init-y := init/ -drivers-y := drivers/ sound/ firmware/ +drivers-y := drivers/ sound/ firmware/ ubuntu/ net-y := net/ libs-y := lib/ core-y := usr/ @@ -980,11 +989,6 @@ # All the preparing.. prepare: prepare0 -# Leave this as default for preprocessing vmlinux.lds.S, which is now -# done in arch/$(ARCH)/kernel/Makefile - -export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH) - # The asm symlink changes when $(ARCH) changes. # Detect this and ask user to run make mrproper # If asm is a stale symlink (point to dir that does not exist) remove it --- linux-mvl-dove-2.6.31.orig/cesa/openswan/mv_openswan_2.6.21.patch +++ linux-mvl-dove-2.6.31/cesa/openswan/mv_openswan_2.6.21.patch @@ -0,0 +1,387 @@ +diff -Nur openswan-2.6.21/linux/net/ipsec/ipsec_mast.c openswan-2.6.21.patched/linux/net/ipsec/ipsec_mast.c +--- openswan-2.6.21/linux/net/ipsec/ipsec_mast.c 2009-03-30 16:11:28.000000000 +0300 ++++ openswan-2.6.21.patched/linux/net/ipsec/ipsec_mast.c 2009-07-12 16:41:04.000000000 +0300 +@@ -87,7 +87,7 @@ + DEBUG_NO_STATIC int + ipsec_mast_open(struct net_device *dev) + { +- struct mastpriv *prv = dev->priv; ++ struct mastpriv *prv = netdev_priv(dev); + + prv = prv; + +@@ -334,7 +334,7 @@ + DEBUG_NO_STATIC struct net_device_stats * + ipsec_mast_get_stats(struct net_device *dev) + { +- return &(((struct mastpriv *)(dev->priv))->mystats); ++ return &(((struct mastpriv *)netdev_priv(dev))->mystats); + } + + #if 0 +@@ -496,7 +496,7 @@ + ipsec_mast_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + { + struct ipsecmastconf *cf = (struct ipsecmastconf *)&ifr->ifr_data; +- struct ipsecpriv *prv = dev->priv; ++ struct ipsecpriv *prv = netdev_priv(dev); + + cf = cf; + prv=prv; +@@ -529,7 +529,7 @@ + ipsec_mast_device_event(struct notifier_block *unused, unsigned long event, void *ptr) + { + struct net_device *dev = ptr; +- struct mastpriv *priv = dev->priv; ++ struct mastpriv *priv = netdev_priv(dev); + + priv = priv; + +@@ -664,10 +664,10 @@ + dev->hard_start_xmit = ipsec_mast_start_xmit; + dev->get_stats = ipsec_mast_get_stats; + +- dev->priv = kmalloc(sizeof(struct mastpriv), GFP_KERNEL); +- if (dev->priv == NULL) +- return -ENOMEM; +- memset((caddr_t)(dev->priv), 0, sizeof(struct mastpriv)); ++ //dev->priv = kmalloc(sizeof(struct mastpriv), GFP_KERNEL); ++ //if (dev->priv == NULL) ++ // return -ENOMEM; ++ //memset((caddr_t)(dev->priv), 0, sizeof(struct mastpriv)); + + for(i = 0; i < sizeof(zeroes); i++) { + ((__u8*)(zeroes))[i] = 0; +@@ -729,7 +729,7 @@ + snprintf(name, IFNAMSIZ, MAST_DEV_FORMAT, vifnum); + + #ifdef alloc_netdev +- im = alloc_netdev(0, name, ipsec_mast_netdev_setup); ++ im = alloc_netdev(sizeof(struct mastpriv), name, ipsec_mast_netdev_setup); + #else + im = (struct net_device *)kmalloc(sizeof(struct net_device),GFP_KERNEL); + #endif +@@ -785,8 +785,8 @@ + kfree(dev_ipsec->name); + dev_ipsec->name=NULL; + #endif /* !NETDEV_23 */ +- kfree(dev_ipsec->priv); +- dev_ipsec->priv=NULL; ++ //kfree(dev_ipsec->priv); ++ //dev_ipsec->priv=NULL; + + return 0; + } +@@ -853,8 +853,8 @@ + dev_mast = mastdevices[i]; + ipsec_dev_put(dev_mast); + unregister_netdev(dev_mast); +- kfree(dev_mast->priv); +- dev_mast->priv=NULL; ++ //kfree(dev_mast->priv); ++ //dev_mast->priv=NULL; + dev_put(mastdevices[i]); + mastdevices[i]=NULL; + } +diff -Nur openswan-2.6.21/linux/net/ipsec/ipsec_ocf.c openswan-2.6.21.patched/linux/net/ipsec/ipsec_ocf.c +--- openswan-2.6.21/linux/net/ipsec/ipsec_ocf.c 2009-03-30 16:11:28.000000000 +0300 ++++ openswan-2.6.21.patched/linux/net/ipsec/ipsec_ocf.c 2009-07-12 16:41:04.000000000 +0300 +@@ -367,7 +367,7 @@ + + /* OCF needs cri_mlen initialized in order to properly migrate the + * session to another driver */ +- crda->crd_mlen = 12; ++ //crda->crd_mlen = 12; + + /* Copy the authenticator to check aganinst later */ + memcpy(irs->hash, irs->authenticator, 12); +@@ -599,7 +599,7 @@ + + /* OCF needs cri_mlen initialized in order to properly migrate + * the session to another driver */ +- crda->crd_mlen = 12; ++ //crda->crd_mlen = 12; + + crda->crd_key = ipsp->ips_key_a; + crda->crd_klen = ipsp->ips_key_bits_a; +diff -Nur openswan-2.6.21/linux/net/ipsec/ipsec_proc.c openswan-2.6.21.patched/linux/net/ipsec/ipsec_proc.c +--- openswan-2.6.21/linux/net/ipsec/ipsec_proc.c 2009-03-30 16:11:28.000000000 +0300 ++++ openswan-2.6.21.patched/linux/net/ipsec/ipsec_proc.c 2009-07-13 08:55:25.000000000 +0300 +@@ -550,7 +550,7 @@ + ipsec_snprintf(name, (ssize_t) sizeof(name), IPSEC_DEV_FORMAT, i); + dev = __ipsec_dev_get(name); + if(dev) { +- priv = (struct ipsecpriv *)(dev->priv); ++ priv = (struct ipsecpriv *)netdev_priv(dev); + len += ipsec_snprintf(buffer+len, length-len, "%s", + dev->name); + if(priv) { +@@ -947,9 +947,11 @@ + item->read_proc = it->readthing; + item->write_proc = it->writething; + item->data = it->data; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) + #ifdef MODULE + item->owner = THIS_MODULE; + #endif ++#endif + } else { + error |= 1; + } +diff -Nur openswan-2.6.21/linux/net/ipsec/ipsec_rcv.c openswan-2.6.21.patched/linux/net/ipsec/ipsec_rcv.c +--- openswan-2.6.21/linux/net/ipsec/ipsec_rcv.c 2009-03-30 16:11:28.000000000 +0300 ++++ openswan-2.6.21.patched/linux/net/ipsec/ipsec_rcv.c 2009-07-12 16:41:04.000000000 +0300 +@@ -843,7 +843,7 @@ + + for(i = 0; i <= ipsecdevices_max; i++) { + if(ipsecdevices[i] == NULL) continue; +- prvdev = ipsecdevices[i]->priv; ++ prvdev = netdev_priv(ipsecdevices[i]); + + if(prvdev == NULL) continue; + +@@ -1992,7 +1992,7 @@ + { + snprintf(name, IFNAMSIZ, IPSEC_DEV_FORMAT, i); + ipsecdev = __ipsec_dev_get(name); +- prv = ipsecdev ? (struct ipsecpriv *)(ipsecdev->priv) : NULL; ++ prv = ipsecdev ? (struct ipsecpriv *)netdev_priv(ipsecdev) : NULL; + prvdev = prv ? (struct net_device *)(prv->dev) : NULL; + if(prvdev && !strncmp(prvdev->name, skb->dev->name, IFNAMSIZ)) + { +diff -Nur openswan-2.6.21/linux/net/ipsec/ipsec_tunnel.c openswan-2.6.21.patched/linux/net/ipsec/ipsec_tunnel.c +--- openswan-2.6.21/linux/net/ipsec/ipsec_tunnel.c 2009-03-30 16:11:28.000000000 +0300 ++++ openswan-2.6.21.patched/linux/net/ipsec/ipsec_tunnel.c 2009-07-12 16:41:04.000000000 +0300 +@@ -104,7 +104,7 @@ + DEBUG_NO_STATIC int + ipsec_tunnel_open(struct net_device *dev) + { +- struct ipsecpriv *prv = dev->priv; ++ struct ipsecpriv *prv = netdev_priv(dev); + + /* + * Can't open until attached. +@@ -610,7 +610,7 @@ + if (! ixs) { + struct ipsecpriv *prv; + struct net_device_stats *stats; +- prv = dev->priv; ++ prv = netdev_priv(dev); + stats = (struct net_device_stats *) &(prv->mystats); + stats->tx_dropped++; + goto alloc_error; +@@ -661,7 +661,7 @@ + DEBUG_NO_STATIC struct net_device_stats * + ipsec_tunnel_get_stats(struct net_device *dev) + { +- return &(((struct ipsecpriv *)(dev->priv))->mystats); ++ return &(((struct ipsecpriv *)netdev_priv(dev))->mystats); + } + + /* +@@ -673,7 +673,7 @@ + ipsec_tunnel_hard_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, const void *daddr, const void *saddr, unsigned len) + { +- struct ipsecpriv *prv = dev->priv; ++ struct ipsecpriv *prv = netdev_priv(dev); + struct net_device *tmp; + int ret; + struct net_device_stats *stats; /* This device's statistics */ +@@ -805,7 +805,7 @@ + unsigned long raddr, struct sk_buff *skb) + #endif /* NET_21 */ + { +- struct ipsecpriv *prv = skb->dev->priv; ++ struct ipsecpriv *prv = netdev_priv(skb->dev); + struct net_device *tmp; + int ret; + struct net_device_stats *stats; /* This device's statistics */ +@@ -895,7 +895,7 @@ + DEBUG_NO_STATIC int + ipsec_tunnel_set_mac_address(struct net_device *dev, void *addr) + { +- struct ipsecpriv *prv = dev->priv; ++ struct ipsecpriv *prv = netdev_priv(dev); + + struct net_device_stats *stats; /* This device's statistics */ + +@@ -998,7 +998,7 @@ + ipsec_tunnel_cache_update(struct hh_cache *hh, const struct net_device *dev, + const unsigned char * haddr) + { +- struct ipsecpriv *prv = dev->priv; ++ struct ipsecpriv *prv = netdev_priv(dev); + + struct net_device_stats *stats; /* This device's statistics */ + +@@ -1099,7 +1099,7 @@ + ipsec_tunnel_attach(struct net_device *dev, struct net_device *physdev) + { + int i; +- struct ipsecpriv *prv = dev->priv; ++ struct ipsecpriv *prv = netdev_priv(dev); + + if(dev == NULL) { + KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, +@@ -1198,7 +1198,7 @@ + ipsec_tunnel_detach(struct net_device *dev) + { + int i; +- struct ipsecpriv *prv = dev->priv; ++ struct ipsecpriv *prv = netdev_priv(dev); + + if(dev == NULL) { + KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, +@@ -1287,7 +1287,7 @@ + for(i = 0; i < IPSEC_NUM_IF; i++) { + ipsecdev = ipsecdevices[i]; + if(ipsecdev != NULL) { +- if((prv = (struct ipsecpriv *)(ipsecdev->priv))) { ++ if((prv = (struct ipsecpriv *)netdev_priv(ipsecdev))) { + prvdev = (struct net_device *)(prv->dev); + if(prvdev) { + KLIPS_PRINT(debug_tunnel & DB_TN_INIT, +@@ -1316,7 +1316,7 @@ + ipsec_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + { + struct ipsectunnelconf *cf = (struct ipsectunnelconf *)&ifr->ifr_data; +- struct ipsecpriv *prv = dev->priv; ++ struct ipsecpriv *prv = netdev_priv(dev); + struct net_device *them; /* physical device */ + #ifdef CONFIG_IP_ALIAS + char *colon; +@@ -1510,7 +1510,7 @@ + ipsec_dev = ipsecdevices[i]; + + if(ipsec_dev) { +- priv = (struct ipsecpriv *)(ipsec_dev->priv); ++ priv = (struct ipsecpriv *)netdev_priv(ipsec_dev); + if(priv) { + ; + if(((struct net_device *)(priv->dev)) == dev) { +@@ -1616,10 +1616,10 @@ + dev->hard_start_xmit = ipsec_tunnel_start_xmit; + dev->get_stats = ipsec_tunnel_get_stats; + +- dev->priv = kmalloc(sizeof(struct ipsecpriv), GFP_KERNEL); +- if (dev->priv == NULL) +- return -ENOMEM; +- memset((caddr_t)(dev->priv), 0, sizeof(struct ipsecpriv)); ++ //dev->priv = kmalloc(sizeof(struct ipsecpriv), GFP_KERNEL); ++ //if (dev->priv == NULL) ++ // return -ENOMEM; ++ //memset((caddr_t)(dev->priv), 0, sizeof(struct ipsecpriv)); + + for(i = 0; i < sizeof(zeroes); i++) { + ((__u8*)(zeroes))[i] = 0; +@@ -1711,7 +1711,7 @@ + + sprintf(name, IPSEC_DEV_FORMAT, ifnum); + #ifdef alloc_netdev +- dev_ipsec = alloc_netdev(0, name, ipsec_tunnel_netdev_setup); ++ dev_ipsec = alloc_netdev(sizeof(struct ipsecpriv), name, ipsec_tunnel_netdev_setup); + #else + dev_ipsec = (struct net_device*)kmalloc(sizeof(struct net_device), GFP_KERNEL); + #endif +@@ -1818,9 +1818,9 @@ + kfree(dev_ipsec->name); + dev_ipsec->name=NULL; + #endif /* !NETDEV_23 */ +- kfree(dev_ipsec->priv); ++ //kfree(dev_ipsec->priv); + #endif /* alloc_netdev */ +- dev_ipsec->priv=NULL; ++ //dev_ipsec->priv=NULL; + + return 0; + } +@@ -1871,9 +1871,9 @@ + kfree(dev_ipsec->name); + dev_ipsec->name=NULL; + #endif /* !NETDEV_23 */ +- kfree(dev_ipsec->priv); ++ //kfree(dev_ipsec->priv); + #endif /* alloc_netdev */ +- dev_ipsec->priv=NULL; ++ //dev_ipsec->priv=NULL; + } + return error; + } +diff -Nur openswan-2.6.21/linux/net/ipsec/ipsec_xmit.c openswan-2.6.21.patched/linux/net/ipsec/ipsec_xmit.c +--- openswan-2.6.21/linux/net/ipsec/ipsec_xmit.c 2009-03-30 16:11:28.000000000 +0300 ++++ openswan-2.6.21.patched/linux/net/ipsec/ipsec_xmit.c 2009-07-12 16:41:04.000000000 +0300 +@@ -425,7 +425,7 @@ + return IPSEC_XMIT_NODEV; + } + +- ixs->prv = ixs->dev->priv; ++ ixs->prv = netdev_priv(ixs->dev); + if (ixs->prv == NULL) { + KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, + "klips_error:ipsec_xmit_sanity_check_dev: " +diff -Nur openswan-2.6.21/linux/net/ipsec/pfkey_v2.c openswan-2.6.21.patched/linux/net/ipsec/pfkey_v2.c +--- openswan-2.6.21/linux/net/ipsec/pfkey_v2.c 2009-03-30 16:11:28.000000000 +0300 ++++ openswan-2.6.21.patched/linux/net/ipsec/pfkey_v2.c 2009-07-12 16:41:04.000000000 +0300 +@@ -672,7 +672,7 @@ + return -EPROTONOSUPPORT; + } + +- if((current->uid != 0)) { ++ if((current_uid() != 0)) { + KLIPS_PRINT(debug_pfkey, + "klips_debug:pfkey_create: " + "must be root to open pfkey sockets.\n"); +@@ -872,7 +872,7 @@ + SENDERR(-error); + } + +- if((current->uid != 0)) { ++ if((current_uid() != 0)) { + KLIPS_PRINT(debug_pfkey, + "klips_debug:pfkey_sendmsg: " + "must be root to send messages to pfkey sockets.\n"); +diff -Nur openswan-2.6.21/packaging/linus/config-all.h openswan-2.6.21.patched/packaging/linus/config-all.h +--- openswan-2.6.21/packaging/linus/config-all.h 2009-03-30 16:11:28.000000000 +0300 ++++ openswan-2.6.21.patched/packaging/linus/config-all.h 2009-07-12 16:41:04.000000000 +0300 +@@ -22,9 +22,11 @@ + #define CONFIG_KLIPS_AH 1 + #endif + ++#if 0 + #ifndef CONFIG_KLIPS_DEBUG + #define CONFIG_KLIPS_DEBUG 1 + #endif ++#endif + + #ifndef CONFIG_KLIPS_ESP + #define CONFIG_KLIPS_ESP 1 +@@ -72,13 +74,12 @@ + #define CONFIG_KLIPS_ALG_CRYPTOAPI #error + #define CONFIG_KLIPS_ALG_AES #error + +-#if 0 +-/* off by default requiers kernel patch */ ++ + #ifndef CONFIG_KLIPS_OCF +-#define CONFIG_KLIPS_OCF 0 +-#endif ++#define CONFIG_KLIPS_OCF 1 + #endif + ++ + #ifndef CONFIG_KLIPS_ALG_AES_MAC + #define CONFIG_KLIPS_ALG_AES_MAC 1 + #endif +diff -Nur openswan-2.6.21/packaging/makefiles/module.defs openswan-2.6.21.patched/packaging/makefiles/module.defs +--- openswan-2.6.21/packaging/makefiles/module.defs 2009-03-30 16:11:28.000000000 +0300 ++++ openswan-2.6.21.patched/packaging/makefiles/module.defs 2009-07-12 16:41:04.000000000 +0300 +@@ -1,5 +1,7 @@ + # To config as static (preferred), 'y'. To config as module, 'm'. +-CONFIG_KLIPS=m ++CONFIG_KLIPS=y ++ ++CONFIG_KLIPS_OCF=y + + # To enable authentication without encryption, say 'y'. (Not so recommended) + CONFIG_KLIPS_AH=y --- linux-mvl-dove-2.6.31.orig/cesa/openswan/ipsec_setup_dove.sh +++ linux-mvl-dove-2.6.31/cesa/openswan/ipsec_setup_dove.sh @@ -0,0 +1,36 @@ +# This is an example how to setup the network interfaces in order to run IPSec routing + +ifconfig eth0 192.168.0.1 hw ether 00:00:00:00:61:92 netmask 255.255.0.0 +ifconfig eth1 192.167.0.1 hw ether 00:00:00:00:62:81 netmask 255.255.0.0 +echo 1 > /proc/sys/net/ipv4/ip_forward +arp -s 192.167.0.250 00:00:00:00:00:12 +arp -s 192.168.1.1 00:00:00:00:00:11 +#IPSec Configuration +insmod /openswan-2.6.18/modobj26/ipsec.ko + +#SmartBit Configuration +#eth0 - 192.168.1.1 --> 192.167.0.250 +# 00:00:00:00:00:12 --> 00:00:00:00:61:92 +#eth1 - 192.167.0.250 --> 192.168.1.1 +# 00:00:00:00:00:11 -> 00:00:00:00:62:81 + + +# unmark this to disble flow control for Yukon/E1000 NICs +#ethtool -A eth0 tx off +#ethtool -A eth0 rx off +#ethtool -A eth2 tx off +#ethtool -A eth2 rx off + +# Here we build static SA database since it is not supported anymore within OpenSWAN 2.6.18 and on +# This is example setup for ESP AES128/SHA1 +ipsec spi --clear +ipsec eroute --clear +enckey=0x123456789abcdef02468ace02468ace0 +authkey=0x0123456789abcdef02468ace13579bdf12345678 +ipsec spi --af inet --edst 192.168.1.1 --spi 0x12345678 --proto esp --src 192.168.0.1 --esp aes128-sha1 --enckey $enckey --authkey $authkey +ipsec spi --af inet --edst 192.168.1.1 --spi 0x12345678 --proto tun --src 192.168.0.1 --dst 192.168.1.1 --ip4 +ipsec spigrp inet 192.168.1.1 0x12345678 tun inet 192.168.1.1 0x12345678 esp +ipsec eroute --add --eraf inet --src 192.167.0.0/16 --dst 192.168.1.0/24 --said tun0x12345678@192.168.1.1 +ipsec tncfg --attach --virtual ipsec0 --physical eth0 +ifconfig ipsec0 inet 192.168.0.1 netmask 255.255.0.0 broadcast 192.168.255.255 up +route add -host 192.168.1.1 gw 192.168.0.1 dev ipsec0 --- linux-mvl-dove-2.6.31.orig/cesa/openswan/mv_openswan_dove.patch +++ linux-mvl-dove-2.6.31/cesa/openswan/mv_openswan_dove.patch @@ -0,0 +1,377 @@ +diff -Nur openswan-2.6.18/linux/net/ipsec/ipsec_mast.c openswan-2.6.18.patched/linux/net/ipsec/ipsec_mast.c +--- openswan-2.6.18/linux/net/ipsec/ipsec_mast.c 2008-10-06 18:52:49.000000000 +0200 ++++ openswan-2.6.18.patched/linux/net/ipsec/ipsec_mast.c 2009-07-13 09:42:29.000000000 +0300 +@@ -87,7 +87,7 @@ + DEBUG_NO_STATIC int + ipsec_mast_open(struct net_device *dev) + { +- struct mastpriv *prv = dev->priv; ++ struct mastpriv *prv = netdev_priv(dev); + + prv = prv; + +@@ -334,7 +334,7 @@ + DEBUG_NO_STATIC struct net_device_stats * + ipsec_mast_get_stats(struct net_device *dev) + { +- return &(((struct mastpriv *)(dev->priv))->mystats); ++ return &(((struct mastpriv *)netdev_priv(dev))->mystats); + } + + #if 0 +@@ -496,7 +496,7 @@ + ipsec_mast_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + { + struct ipsecmastconf *cf = (struct ipsecmastconf *)&ifr->ifr_data; +- struct ipsecpriv *prv = dev->priv; ++ struct ipsecpriv *prv = netdev_priv(dev); + + cf = cf; + prv=prv; +@@ -529,7 +529,7 @@ + ipsec_mast_device_event(struct notifier_block *unused, unsigned long event, void *ptr) + { + struct net_device *dev = ptr; +- struct mastpriv *priv = dev->priv; ++ struct mastpriv *priv = netdev_priv(dev); + + priv = priv; + +@@ -664,10 +664,10 @@ + dev->hard_start_xmit = ipsec_mast_start_xmit; + dev->get_stats = ipsec_mast_get_stats; + +- dev->priv = kmalloc(sizeof(struct mastpriv), GFP_KERNEL); +- if (dev->priv == NULL) +- return -ENOMEM; +- memset((caddr_t)(dev->priv), 0, sizeof(struct mastpriv)); ++ //dev->priv = kmalloc(sizeof(struct mastpriv), GFP_KERNEL); ++ //if (dev->priv == NULL) ++ // return -ENOMEM; ++ //memset((caddr_t)(dev->priv), 0, sizeof(struct mastpriv)); + + for(i = 0; i < sizeof(zeroes); i++) { + ((__u8*)(zeroes))[i] = 0; +@@ -729,7 +729,7 @@ + snprintf(name, IFNAMSIZ, MAST_DEV_FORMAT, vifnum); + + #ifdef alloc_netdev +- im = alloc_netdev(0, name, ipsec_mast_netdev_setup); ++ im = alloc_netdev(sizeof(struct mastpriv), name, ipsec_mast_netdev_setup); + #else + im = (struct net_device *)kmalloc(sizeof(struct net_device),GFP_KERNEL); + #endif +@@ -785,8 +785,8 @@ + kfree(dev_ipsec->name); + dev_ipsec->name=NULL; + #endif /* !NETDEV_23 */ +- kfree(dev_ipsec->priv); +- dev_ipsec->priv=NULL; ++ //kfree(dev_ipsec->priv); ++ //dev_ipsec->priv=NULL; + + return 0; + } +@@ -852,8 +852,8 @@ + if(mastdevices[i]!=NULL) { + dev_mast = mastdevices[i]; + unregister_netdev(dev_mast); +- kfree(dev_mast->priv); +- dev_mast->priv=NULL; ++ //kfree(dev_mast->priv); ++ //dev_mast->priv=NULL; + dev_put(mastdevices[i]); + mastdevices[i]=NULL; + } +diff -Nur openswan-2.6.18/linux/net/ipsec/ipsec_ocf.c openswan-2.6.18.patched/linux/net/ipsec/ipsec_ocf.c +--- openswan-2.6.18/linux/net/ipsec/ipsec_ocf.c 2008-10-06 18:52:49.000000000 +0200 ++++ openswan-2.6.18.patched/linux/net/ipsec/ipsec_ocf.c 2009-07-13 09:42:29.000000000 +0300 +@@ -64,6 +64,7 @@ + * Tuning parameters, the settings below appear best for + * the IXP + */ ++ + #define USE_BATCH 1 /* enable batch mode */ + #define USE_CBIMM 1 /* enable immediate callbacks */ + #define FORCE_QS 0 /* force use of queues for continuation of state machine */ +@@ -367,7 +368,7 @@ + + /* OCF needs cri_mlen initialized in order to properly migrate the + * session to another driver */ +- crda->crd_mlen = 12; ++ //crda->crd_mlen = 12; + + /* Copy the authenticator to check aganinst later */ + memcpy(irs->hash, irs->authenticator, 12); +@@ -599,7 +600,7 @@ + + /* OCF needs cri_mlen initialized in order to properly migrate + * the session to another driver */ +- crda->crd_mlen = 12; ++ //crda->crd_mlen = 12; + + crda->crd_key = ipsp->ips_key_a; + crda->crd_klen = ipsp->ips_key_bits_a; +diff -Nur openswan-2.6.18/linux/net/ipsec/ipsec_proc.c openswan-2.6.18.patched/linux/net/ipsec/ipsec_proc.c +--- openswan-2.6.18/linux/net/ipsec/ipsec_proc.c 2008-10-06 18:52:49.000000000 +0200 ++++ openswan-2.6.18.patched/linux/net/ipsec/ipsec_proc.c 2009-07-13 09:43:51.000000000 +0300 +@@ -550,7 +550,7 @@ + ipsec_snprintf(name, (ssize_t) sizeof(name), IPSEC_DEV_FORMAT, i); + dev = __ipsec_dev_get(name); + if(dev) { +- priv = (struct ipsecpriv *)(dev->priv); ++ priv = (struct ipsecpriv *)netdev_priv(dev);; + len += ipsec_snprintf(buffer+len, length-len, "%s", + dev->name); + if(priv) { +@@ -947,9 +947,11 @@ + item->read_proc = it->readthing; + item->write_proc = it->writething; + item->data = it->data; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) + #ifdef MODULE + item->owner = THIS_MODULE; + #endif ++#endif + } else { + error |= 1; + } +diff -Nur openswan-2.6.18/linux/net/ipsec/ipsec_rcv.c openswan-2.6.18.patched/linux/net/ipsec/ipsec_rcv.c +--- openswan-2.6.18/linux/net/ipsec/ipsec_rcv.c 2008-10-06 18:52:49.000000000 +0200 ++++ openswan-2.6.18.patched/linux/net/ipsec/ipsec_rcv.c 2009-07-13 09:42:29.000000000 +0300 +@@ -840,7 +840,7 @@ + + for(i = 0; i <= ipsecdevices_max; i++) { + if(ipsecdevices[i] == NULL) continue; +- prvdev = ipsecdevices[i]->priv; ++ prvdev = netdev_priv(ipsecdevices[i]); + + if(prvdev == NULL) continue; + +diff -Nur openswan-2.6.18/linux/net/ipsec/ipsec_tunnel.c openswan-2.6.18.patched/linux/net/ipsec/ipsec_tunnel.c +--- openswan-2.6.18/linux/net/ipsec/ipsec_tunnel.c 2008-10-06 18:52:49.000000000 +0200 ++++ openswan-2.6.18.patched/linux/net/ipsec/ipsec_tunnel.c 2009-07-13 09:42:29.000000000 +0300 +@@ -104,7 +104,7 @@ + DEBUG_NO_STATIC int + ipsec_tunnel_open(struct net_device *dev) + { +- struct ipsecpriv *prv = dev->priv; ++ struct ipsecpriv *prv = netdev_priv(dev); + + /* + * Can't open until attached. +@@ -610,7 +610,7 @@ + if (! ixs) { + struct ipsecpriv *prv; + struct net_device_stats *stats; +- prv = dev->priv; ++ prv = netdev_priv(dev); + stats = (struct net_device_stats *) &(prv->mystats); + stats->tx_dropped++; + goto alloc_error; +@@ -661,7 +661,7 @@ + DEBUG_NO_STATIC struct net_device_stats * + ipsec_tunnel_get_stats(struct net_device *dev) + { +- return &(((struct ipsecpriv *)(dev->priv))->mystats); ++ return &(((struct ipsecpriv *)(netdev_priv(dev)))->mystats); + } + + /* +@@ -673,7 +673,7 @@ + ipsec_tunnel_hard_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, const void *daddr, const void *saddr, unsigned len) + { +- struct ipsecpriv *prv = dev->priv; ++ struct ipsecpriv *prv = netdev_priv(dev); + struct net_device *tmp; + int ret; + struct net_device_stats *stats; /* This device's statistics */ +@@ -805,7 +805,7 @@ + unsigned long raddr, struct sk_buff *skb) + #endif /* NET_21 */ + { +- struct ipsecpriv *prv = skb->dev->priv; ++ struct ipsecpriv *prv = netdev_priv(skb->dev); + struct net_device *tmp; + int ret; + struct net_device_stats *stats; /* This device's statistics */ +@@ -895,7 +895,7 @@ + DEBUG_NO_STATIC int + ipsec_tunnel_set_mac_address(struct net_device *dev, void *addr) + { +- struct ipsecpriv *prv = dev->priv; ++ struct ipsecpriv *prv = netdev_priv(dev); + + struct net_device_stats *stats; /* This device's statistics */ + +@@ -998,7 +998,7 @@ + ipsec_tunnel_cache_update(struct hh_cache *hh, const struct net_device *dev, + const unsigned char * haddr) + { +- struct ipsecpriv *prv = dev->priv; ++ struct ipsecpriv *prv = netdev_priv(dev); + + struct net_device_stats *stats; /* This device's statistics */ + +@@ -1099,7 +1099,7 @@ + ipsec_tunnel_attach(struct net_device *dev, struct net_device *physdev) + { + int i; +- struct ipsecpriv *prv = dev->priv; ++ struct ipsecpriv *prv = netdev_priv(dev); + + if(dev == NULL) { + KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, +@@ -1198,7 +1198,7 @@ + ipsec_tunnel_detach(struct net_device *dev) + { + int i; +- struct ipsecpriv *prv = dev->priv; ++ struct ipsecpriv *prv = netdev_priv(dev); + + if(dev == NULL) { + KLIPS_PRINT(debug_tunnel & DB_TN_REVEC, +@@ -1287,7 +1287,7 @@ + for(i = 0; i < IPSEC_NUM_IF; i++) { + ipsecdev = ipsecdevices[i]; + if(ipsecdev != NULL) { +- if((prv = (struct ipsecpriv *)(ipsecdev->priv))) { ++ if((prv = (struct ipsecpriv *)netdev_priv(ipsecdev))) { + prvdev = (struct net_device *)(prv->dev); + if(prvdev) { + KLIPS_PRINT(debug_tunnel & DB_TN_INIT, +@@ -1316,7 +1316,7 @@ + ipsec_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + { + struct ipsectunnelconf *cf = (struct ipsectunnelconf *)&ifr->ifr_data; +- struct ipsecpriv *prv = dev->priv; ++ struct ipsecpriv *prv = netdev_priv(dev); + struct net_device *them; /* physical device */ + #ifdef CONFIG_IP_ALIAS + char *colon; +@@ -1510,7 +1510,7 @@ + ipsec_dev = ipsecdevices[i]; + + if(ipsec_dev) { +- priv = (struct ipsecpriv *)(ipsec_dev->priv); ++ priv = (struct ipsecpriv *)netdev_priv(ipsec_dev); + if(priv) { + ; + if(((struct net_device *)(priv->dev)) == dev) { +@@ -1616,10 +1616,10 @@ + dev->hard_start_xmit = ipsec_tunnel_start_xmit; + dev->get_stats = ipsec_tunnel_get_stats; + +- dev->priv = kmalloc(sizeof(struct ipsecpriv), GFP_KERNEL); +- if (dev->priv == NULL) +- return -ENOMEM; +- memset((caddr_t)(dev->priv), 0, sizeof(struct ipsecpriv)); ++ //dev->priv = kmalloc(sizeof(struct ipsecpriv), GFP_KERNEL); ++ //if (dev->priv == NULL) ++ // return -ENOMEM; ++ //memset((caddr_t)(dev->priv), 0, sizeof(struct ipsecpriv)); + + for(i = 0; i < sizeof(zeroes); i++) { + ((__u8*)(zeroes))[i] = 0; +@@ -1711,7 +1711,7 @@ + + sprintf(name, IPSEC_DEV_FORMAT, ifnum); + #ifdef alloc_netdev +- dev_ipsec = alloc_netdev(0, name, ipsec_tunnel_netdev_setup); ++ dev_ipsec = alloc_netdev(sizeof(struct ipsecpriv), name, ipsec_tunnel_netdev_setup); + #else + dev_ipsec = (struct net_device*)kmalloc(sizeof(struct net_device), GFP_KERNEL); + #endif +@@ -1820,7 +1820,7 @@ + #endif /* !NETDEV_23 */ + kfree(dev_ipsec->priv); + #endif /* alloc_netdev */ +- dev_ipsec->priv=NULL; ++ //dev_ipsec->priv=NULL; + + return 0; + } +@@ -1873,7 +1873,7 @@ + #endif /* !NETDEV_23 */ + kfree(dev_ipsec->priv); + #endif /* alloc_netdev */ +- dev_ipsec->priv=NULL; ++ //dev_ipsec->priv=NULL; + } + return error; + } +diff -Nur openswan-2.6.18/linux/net/ipsec/ipsec_xmit.c openswan-2.6.18.patched/linux/net/ipsec/ipsec_xmit.c +--- openswan-2.6.18/linux/net/ipsec/ipsec_xmit.c 2008-10-06 18:52:49.000000000 +0200 ++++ openswan-2.6.18.patched/linux/net/ipsec/ipsec_xmit.c 2009-07-13 09:42:29.000000000 +0300 +@@ -425,7 +425,7 @@ + return IPSEC_XMIT_NODEV; + } + +- ixs->prv = ixs->dev->priv; ++ ixs->prv = netdev_priv(ixs->dev); + if (ixs->prv == NULL) { + KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, + "klips_error:ipsec_xmit_sanity_check_dev: " +diff -Nur openswan-2.6.18/linux/net/ipsec/pfkey_v2.c openswan-2.6.18.patched/linux/net/ipsec/pfkey_v2.c +--- openswan-2.6.18/linux/net/ipsec/pfkey_v2.c 2008-10-06 18:52:49.000000000 +0200 ++++ openswan-2.6.18.patched/linux/net/ipsec/pfkey_v2.c 2009-07-13 09:42:29.000000000 +0300 +@@ -672,7 +672,7 @@ + return -EPROTONOSUPPORT; + } + +- if((current->uid != 0)) { ++ if((current_uid() != 0)) { + KLIPS_PRINT(debug_pfkey, + "klips_debug:pfkey_create: " + "must be root to open pfkey sockets.\n"); +@@ -872,7 +872,7 @@ + SENDERR(-error); + } + +- if((current->uid != 0)) { ++ if((current_uid() != 0)) { + KLIPS_PRINT(debug_pfkey, + "klips_debug:pfkey_sendmsg: " + "must be root to send messages to pfkey sockets.\n"); +diff -Nur openswan-2.6.18/packaging/linus/config-all.h openswan-2.6.18.patched/packaging/linus/config-all.h +--- openswan-2.6.18/packaging/linus/config-all.h 2008-10-06 18:52:49.000000000 +0200 ++++ openswan-2.6.18.patched/packaging/linus/config-all.h 2009-07-13 09:42:29.000000000 +0300 +@@ -22,9 +22,11 @@ + #define CONFIG_KLIPS_AH 1 + #endif + ++#if 0 + #ifndef CONFIG_KLIPS_DEBUG + #define CONFIG_KLIPS_DEBUG 1 + #endif ++#endif + + #ifndef CONFIG_KLIPS_ESP + #define CONFIG_KLIPS_ESP 1 +@@ -72,11 +74,9 @@ + #define CONFIG_KLIPS_ALG_CRYPTOAPI #error + #define CONFIG_KLIPS_ALG_AES #error + +-#if 0 +-/* off by default requiers kernel patch */ ++ + #ifndef CONFIG_KLIPS_OCF +-#define CONFIG_KLIPS_OCF 0 +-#endif ++#define CONFIG_KLIPS_OCF 1 + #endif + + #ifndef CONFIG_KLIPS_ALG_AES_MAC +diff -Nur openswan-2.6.18/packaging/makefiles/module.defs openswan-2.6.18.patched/packaging/makefiles/module.defs +--- openswan-2.6.18/packaging/makefiles/module.defs 2008-10-06 18:52:49.000000000 +0200 ++++ openswan-2.6.18.patched/packaging/makefiles/module.defs 2009-07-13 09:42:29.000000000 +0300 +@@ -1,5 +1,7 @@ + # To config as static (preferred), 'y'. To config as module, 'm'. +-CONFIG_KLIPS=m ++CONFIG_KLIPS=y ++ ++CONFIG_KLIPS_OCF=y + + # To enable authentication without encryption, say 'y'. (Not so recommended) + CONFIG_KLIPS_AH=y --- linux-mvl-dove-2.6.31.orig/cesa/openswan/README +++ linux-mvl-dove-2.6.31/cesa/openswan/README @@ -0,0 +1,57 @@ +OpenSWAN +========= + In order to explore the Dove CESA through the OpenSWAN, 1 patch should be applied to the OpenSWAN. + + download openswan-2.6.18 (http://www.openswan.org/), then untar+unzip it. + apply the patch: + + - mv_openswan_dove.patch - a patch from OCF to include the OCF support into the IPsec DP. + add OCF support by default. (packaging/linus/config-all.h packaging/makefiles/module.defs) + use OCF in user space. + remove DEBUG info. + and compile: + + + ipsec module (cross compilation) : + 'make KERNELSRC= module ARCH=arm CC= LD=' + then copy the module to the host FS: /lib/modules//kernel/net/ipsec/ + + + ipsec user (native) : + make sure that you have the kernel source on the FS. + 'make KERNELSRC= programs' + ( - Need to copy cryptodev.h from the kernel crypto/ocf/ to include/crypto/ + - Need to copy autoconf from the kernel include to include, in order to overcome missing include path of pluto compilation. ) + 'make install' + + +IPSec routing using encryption/authentication only + + basic vpn connection: + +++++++++++++++++++++ + - platform: Dove to Dove conncted with egiga. + - make sure you have 'ip' (part of the iproute package) installed. + - edit /etc/ipsec.conf (on both DOve FS) ,check the "man ipsec.conf" : + +config setup + interfaces="ipsec0=egiga0" # Virtual/physical interfaces + klipsdebug="none" # Debug KLIPS + plutodebug="none" # Debug PLUTO + +conn dove_psk_vpn + type=tunnel # type of the connection: tunnel(default),passthrough,transport,reject,drop + authby=secret + left=192.168.1.1 + leftsubnet=192.168.1.0/16 + right=192.168.0.1 # Remote information + rightsubnet=192.168.0.0/16 + auto=start # start this connection at startup + + + - edit /etc/ipsec.secrets (on both Dove FS) to have shared secret. +192.168.1.1 192.168.0.1 : PSK "123456" + + - Dove1: 'ifconfig eth0 192.168.0.1 netmask 255.255.0.0' + - Dove2: 'ifconfig eth0 192.168.1.1 netmask 255.255.0.0' + - check connectivity: ping from Dove1 to 192.168.1.1 + - '/etc/init.d/ipsec start' (on both Dove), create new interface ipsec0. + - check connectivity: ping from Dove1 to 192.168.1.1 --> VPN is working (make sure by sniffing) + --- linux-mvl-dove-2.6.31.orig/drivers/s390/block/dasd_diag.c +++ linux-mvl-dove-2.6.31/drivers/s390/block/dasd_diag.c @@ -145,6 +145,15 @@ mdsk_term_io(device); rc = mdsk_init_io(device, device->block->bp_block, 0, NULL); + if (rc == 4) { + if (!(device->features & DASD_FEATURE_READONLY)) { + dev_warn(&device->cdev->dev, + "The access mode of a DIAG device changed" + " to read-only"); + device->features |= DASD_FEATURE_READONLY; + } + rc = 0; + } if (rc) dev_warn(&device->cdev->dev, "DIAG ERP failed with " "rc=%d\n", rc); @@ -433,16 +442,20 @@ for (sb = 512; sb < bsize; sb = sb << 1) block->s2b_shift++; rc = mdsk_init_io(device, block->bp_block, 0, NULL); - if (rc) { + if (rc && (rc != 4)) { dev_warn(&device->cdev->dev, "DIAG initialization " "failed with rc=%d\n", rc); rc = -EIO; } else { + if (rc == 4) + device->features |= DASD_FEATURE_READONLY; dev_info(&device->cdev->dev, - "New DASD with %ld byte/block, total size %ld KB\n", + "New DASD with %ld byte/block, total size %ld KB%s\n", (unsigned long) block->bp_block, (unsigned long) (block->blocks << - block->s2b_shift) >> 1); + block->s2b_shift) >> 1, + (rc == 4) ? ", read-only device" : ""); + rc = 0; } out_label: free_page((long) label); --- linux-mvl-dove-2.6.31.orig/drivers/ide/ide-probe.c +++ linux-mvl-dove-2.6.31/drivers/ide/ide-probe.c @@ -1035,15 +1035,6 @@ if (port_ops && port_ops->init_dev) port_ops->init_dev(drive); } - - ide_port_for_each_dev(i, drive, hwif) { - /* - * default to PIO Mode 0 before we figure out - * the most suited mode for the attached device - */ - if (port_ops && port_ops->set_pio_mode) - port_ops->set_pio_mode(drive, 0); - } } static void ide_init_port(ide_hwif_t *hwif, unsigned int port, --- linux-mvl-dove-2.6.31.orig/drivers/ide/cmd64x.c +++ linux-mvl-dove-2.6.31/drivers/ide/cmd64x.c @@ -379,7 +379,8 @@ .enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}}, .port_ops = &cmd64x_port_ops, .host_flags = IDE_HFLAG_CLEAR_SIMPLEX | - IDE_HFLAG_ABUSE_PREFETCH, + IDE_HFLAG_ABUSE_PREFETCH | + IDE_HFLAG_SERIALIZE, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, .udma_mask = 0x00, /* no udma */ @@ -389,7 +390,8 @@ .init_chipset = init_chipset_cmd64x, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, .port_ops = &cmd648_port_ops, - .host_flags = IDE_HFLAG_ABUSE_PREFETCH, + .host_flags = IDE_HFLAG_ABUSE_PREFETCH | + IDE_HFLAG_SERIALIZE, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA2, --- linux-mvl-dove-2.6.31.orig/drivers/ide/slc90e66.c +++ linux-mvl-dove-2.6.31/drivers/ide/slc90e66.c @@ -91,8 +91,7 @@ if (!(reg48 & u_flag)) pci_write_config_word(dev, 0x48, reg48|u_flag); - /* FIXME: (reg4a & a_speed) ? */ - if ((reg4a & u_speed) != u_speed) { + if ((reg4a & a_speed) != u_speed) { pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); pci_read_config_word(dev, 0x4a, ®4a); pci_write_config_word(dev, 0x4a, reg4a|u_speed); --- linux-mvl-dove-2.6.31.orig/drivers/ide/sis5513.c +++ linux-mvl-dove-2.6.31/drivers/ide/sis5513.c @@ -2,7 +2,7 @@ * Copyright (C) 1999-2000 Andre Hedrick * Copyright (C) 2002 Lionel Bouton , Maintainer * Copyright (C) 2003 Vojtech Pavlik - * Copyright (C) 2007 Bartlomiej Zolnierkiewicz + * Copyright (C) 2007-2009 Bartlomiej Zolnierkiewicz * * May be copied or modified under the terms of the GNU General Public License * @@ -281,11 +281,13 @@ pci_read_config_byte(dev, 0x4b, ®4bh); + rw_prefetch = reg4bh & ~(0x11 << drive->dn); + if (drive->media == ide_disk) - rw_prefetch = 0x11 << drive->dn; + rw_prefetch |= 0x11 << drive->dn; - if ((reg4bh & (0x11 << drive->dn)) != rw_prefetch) - pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch); + if (reg4bh != rw_prefetch) + pci_write_config_byte(dev, 0x4b, rw_prefetch); } static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio) --- linux-mvl-dove-2.6.31.orig/drivers/ide/ide-ioctls.c +++ linux-mvl-dove-2.6.31/drivers/ide/ide-ioctls.c @@ -162,7 +162,7 @@ if (tf->command == ATA_CMD_SET_FEATURES && tf->feature == SETFEATURES_XFER && tf->nsect >= XFER_SW_DMA_0) { - xfer_rate = ide_find_dma_mode(drive, XFER_UDMA_6); + xfer_rate = ide_find_dma_mode(drive, tf->nsect); if (xfer_rate != tf->nsect) { err = -EINVAL; goto abort; --- linux-mvl-dove-2.6.31.orig/drivers/i2c/i2c-core.c +++ linux-mvl-dove-2.6.31/drivers/i2c/i2c-core.c @@ -718,6 +718,7 @@ { int res = 0; struct i2c_adapter *found; + struct i2c_client *client, *next; /* First make sure that this adapter was ever added */ mutex_lock(&core_lock); @@ -737,6 +738,16 @@ if (res) return res; + /* Remove devices instantiated from sysfs */ + list_for_each_entry_safe(client, next, &userspace_devices, detected) { + if (client->adapter == adap) { + dev_dbg(&adap->dev, "Removing %s at 0x%x\n", + client->name, client->addr); + list_del(&client->detected); + i2c_unregister_device(client); + } + } + /* Detach any active clients. This can't fail, thus we do not checking the returned value. */ res = device_for_each_child(&adap->dev, NULL, __unregister_client); --- linux-mvl-dove-2.6.31.orig/drivers/i2c/chips/max1535.c +++ linux-mvl-dove-2.6.31/drivers/i2c/chips/max1535.c @@ -0,0 +1,134 @@ +/* + This driver supports the MAX 1535B/1535C/1535D SMBus Battery Chargers. + + 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 of the License. +*/ + +#include +#include +#include +#include +#include +#include + +#define MAX1535_CHARGER_SPEC_INFO 0x11 +#define MAX1535_CHARGER_STATUS 0x13 +#define MAX1535_MANUFACTURER_ID 0xFE +#define MAX1535_DEVICE_ID 0xFF +#define MAX1535_INPUT_CURRENT_LIMIT 0x3F +#define MAX1535_INPUT_CURRENT_LIMIT_DEF 0x0800 /* 4A */ + +static const struct i2c_device_id max1535_id[] = { + { "max1535_i2c", 0 }, + { } +}; + +struct i2c_client *max1535_client = NULL; + +int charger_proc_write(struct file *file, const char *buffer,unsigned long count, void *data) +{ + int cmd; + int val; + + sscanf(buffer, "%x %x", &cmd, &val); + printk("Writing to 0x%x 0x%x\n", (u8)cmd, (u16)val); + i2c_smbus_write_word_data(max1535_client, (u8)cmd, (u16)val); + + return count; +} + +int charger_proc_read(char* page, char** start, off_t off, int count,int* eof, void* data) +{ + int len = 0; + s32 rd; + + if ((rd = (int)i2c_smbus_read_word_data(max1535_client, MAX1535_CHARGER_SPEC_INFO)) < 0) { + return -EIO; + } + len += sprintf(page+len, "Charger Spec Info (0x11) = %04x\n", rd); + + if ((rd = (int)i2c_smbus_read_word_data(max1535_client, MAX1535_CHARGER_STATUS)) < 0) { + return -EIO; + } + len += sprintf(page+len, "Charger Status (0x13) = %04x\n", rd); + + if ((rd = (int)i2c_smbus_read_word_data(max1535_client, MAX1535_MANUFACTURER_ID)) < 0) { + return -EIO; + } + len += sprintf(page+len, "Manufacturer ID (0xFE) = %04x\n", rd); + + if ((rd = (int)i2c_smbus_read_word_data(max1535_client, MAX1535_DEVICE_ID)) < 0) { + return -EIO; + } + len += sprintf(page+len, "Device ID (0xFF) = %04x\n", rd); + + len += sprintf(page+len, "\n\nUsage:\n"); + len += sprintf(page+len, " echo > /proc/charger\n"); + return len; +} + +static struct proc_dir_entry *charger_proc_entry; +extern struct proc_dir_entry proc_root; +static int charger_proc_init(void) +{ + charger_proc_entry = create_proc_entry("charger", 0666, &proc_root); + charger_proc_entry->read_proc = charger_proc_read; + charger_proc_entry->write_proc = charger_proc_write; + return 0; +} + +static int __devinit max1535_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + if (!i2c_check_functionality(to_i2c_adapter(client->dev.parent), + I2C_FUNC_SMBUS_EMUL)) + return -EIO; + + /* Raise the charge current */ + if (i2c_smbus_write_word_data(client, MAX1535_INPUT_CURRENT_LIMIT, + MAX1535_INPUT_CURRENT_LIMIT_DEF) < 0) { + dev_err(&client->dev, "Failed To initialize Current Limit in SMBus Charger"); + return -EIO; + } + + max1535_client = client; + + charger_proc_init(); + + printk("MAX1535 SMBus Battery Charger driver loaded successfully\n"); + return 0; +} +static int __devexit max1535_remove(struct i2c_client *client) +{ + return 0; +} + + +static struct i2c_driver max1535_driver = { + .driver = { + .name = "max1535_i2c", + .owner = THIS_MODULE, + }, + .probe = max1535_probe, + .remove = __devexit_p(max1535_remove), + .id_table = max1535_id, +}; + +static int __init max1535_init(void) +{ + return i2c_add_driver(&max1535_driver); +} + +static void __exit max1535_exit(void) +{ + i2c_del_driver(&max1535_driver); +} + +MODULE_AUTHOR("Tawfik Bayouk "); +MODULE_DESCRIPTION("MAX1535 SMBus Battery Charger Driver"); +MODULE_LICENSE("GPL"); + +module_init(max1535_init); +module_exit(max1535_exit); --- linux-mvl-dove-2.6.31.orig/drivers/i2c/chips/Kconfig +++ linux-mvl-dove-2.6.31/drivers/i2c/chips/Kconfig @@ -74,4 +74,21 @@ This driver can also be built as a module. If so, the module will be called tsl2550. +config MENELAUS + bool "TWL92330/Menelaus PM chip" + depends on I2C=y && ARCH_OMAP24XX + help + If you say yes here you get support for the Texas Instruments + TWL92330/Menelaus Power Management chip. This include voltage + regulators, Dual slot memory card tranceivers, real-time clock + and other features that are often used in portable devices like + cell phones and PDAs. + +config MAX1535 + tristate "MAX 1535 SMBus Battery Charger chip" + default y if MACH_DOVE_RD + help + If you say yes here you get support for MAX 1535 SMBus Battery + Charger. + endmenu --- linux-mvl-dove-2.6.31.orig/drivers/i2c/chips/Makefile +++ linux-mvl-dove-2.6.31/drivers/i2c/chips/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o obj-$(CONFIG_PCF8575) += pcf8575.o obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o +obj-$(CONFIG_MAX1535) += max1535.o ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) EXTRA_CFLAGS += -DDEBUG --- linux-mvl-dove-2.6.31.orig/drivers/i2c/chips/tsl2550.c +++ linux-mvl-dove-2.6.31/drivers/i2c/chips/tsl2550.c @@ -277,6 +277,7 @@ static ssize_t __tsl2550_show_lux(struct i2c_client *client, char *buf) { + struct tsl2550_data *data = i2c_get_clientdata(client); u8 ch0, ch1; int ret; @@ -296,6 +297,8 @@ ret = tsl2550_calculate_lux(ch0, ch1); if (ret < 0) return ret; + if (data->operating_mode == 1) + ret *= 5; return sprintf(buf, "%d\n", ret); } --- linux-mvl-dove-2.6.31.orig/drivers/i2c/busses/i2c-piix4.c +++ linux-mvl-dove-2.6.31/drivers/i2c/busses/i2c-piix4.c @@ -168,7 +168,7 @@ } if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) - return -EBUSY; + return -ENODEV; if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) { dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n", @@ -259,7 +259,7 @@ piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0; if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) - return -EBUSY; + return -ENODEV; if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) { dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n", --- linux-mvl-dove-2.6.31.orig/drivers/i2c/busses/i2c-mv64xxx.c +++ linux-mvl-dove-2.6.31/drivers/i2c/busses/i2c-mv64xxx.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -97,10 +98,30 @@ u32 freq_n; wait_queue_head_t waitq; spinlock_t lock; + struct device *dev; struct i2c_msg *msg; + struct i2c_adapter *adapter; +#ifdef CONFIG_I2C_MV64XXX_PORT_EXPANDER + struct semaphore exp_sem; + int (*select_exp_port)(unsigned int port_id); +#endif + u32 combine_access; +}; + +struct mv64xxx_i2c_exp_data { + struct mv64xxx_i2c_data *hw_adapter; struct i2c_adapter adapter; }; +#define get_adapter(pdata) ((pdata)->adapter) + /* in micor seconds delay after each write to control register */ +#define MV_WRITE_DELAY 2 +static void +mv_ctrl_writel(struct mv64xxx_i2c_data *drv_data, u32 val, unsigned int offset) +{ + writel(val, drv_data->reg_base + offset); + udelay(MV_WRITE_DELAY); +} /* ***************************************************************************** * @@ -118,8 +139,9 @@ drv_data->reg_base + MV64XXX_I2C_REG_BAUD); writel(0, drv_data->reg_base + MV64XXX_I2C_REG_SLAVE_ADDR); writel(0, drv_data->reg_base + MV64XXX_I2C_REG_EXT_SLAVE_ADDR); - writel(MV64XXX_I2C_REG_CONTROL_TWSIEN | MV64XXX_I2C_REG_CONTROL_STOP, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + mv_ctrl_writel(drv_data, MV64XXX_I2C_REG_CONTROL_TWSIEN | + MV64XXX_I2C_REG_CONTROL_STOP, + MV64XXX_I2C_REG_CONTROL); drv_data->state = MV64XXX_I2C_STATE_IDLE; } @@ -213,7 +235,7 @@ break; default: - dev_err(&drv_data->adapter.dev, + dev_err(drv_data->dev, "mv64xxx_i2c_fsm: Ctlr Error -- state: 0x%x, " "status: 0x%x, addr: 0x%x, flags: 0x%x\n", drv_data->state, status, drv_data->msg->addr, @@ -229,77 +251,87 @@ { switch(drv_data->action) { case MV64XXX_I2C_ACTION_CONTINUE: - writel(drv_data->cntl_bits, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + mv_ctrl_writel(drv_data, drv_data->cntl_bits, + MV64XXX_I2C_REG_CONTROL); break; case MV64XXX_I2C_ACTION_SEND_START: - writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + mv_ctrl_writel(drv_data, drv_data->cntl_bits | + MV64XXX_I2C_REG_CONTROL_START, + MV64XXX_I2C_REG_CONTROL); break; case MV64XXX_I2C_ACTION_SEND_ADDR_1: writel(drv_data->addr1, drv_data->reg_base + MV64XXX_I2C_REG_DATA); - writel(drv_data->cntl_bits, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + mv_ctrl_writel(drv_data, drv_data->cntl_bits, + MV64XXX_I2C_REG_CONTROL); break; case MV64XXX_I2C_ACTION_SEND_ADDR_2: writel(drv_data->addr2, drv_data->reg_base + MV64XXX_I2C_REG_DATA); - writel(drv_data->cntl_bits, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + mv_ctrl_writel(drv_data, drv_data->cntl_bits, + MV64XXX_I2C_REG_CONTROL); break; case MV64XXX_I2C_ACTION_SEND_DATA: writel(drv_data->msg->buf[drv_data->byte_posn++], drv_data->reg_base + MV64XXX_I2C_REG_DATA); - writel(drv_data->cntl_bits, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + mv_ctrl_writel(drv_data, drv_data->cntl_bits, + MV64XXX_I2C_REG_CONTROL); break; case MV64XXX_I2C_ACTION_RCV_DATA: drv_data->msg->buf[drv_data->byte_posn++] = readl(drv_data->reg_base + MV64XXX_I2C_REG_DATA); - writel(drv_data->cntl_bits, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + mv_ctrl_writel(drv_data, drv_data->cntl_bits, + MV64XXX_I2C_REG_CONTROL); break; case MV64XXX_I2C_ACTION_RCV_DATA_STOP: drv_data->msg->buf[drv_data->byte_posn++] = readl(drv_data->reg_base + MV64XXX_I2C_REG_DATA); drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; - writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + + if(drv_data->combine_access) + {//because of combine access, we can't send STOP here. + //But it will occur problem, so need software reset to work around + mv64xxx_i2c_hw_init(drv_data); + }else{ + mv_ctrl_writel(drv_data, drv_data->cntl_bits | + MV64XXX_I2C_REG_CONTROL_STOP, + MV64XXX_I2C_REG_CONTROL); + } drv_data->block = 0; wake_up_interruptible(&drv_data->waitq); break; case MV64XXX_I2C_ACTION_INVALID: default: - dev_err(&drv_data->adapter.dev, + dev_err(drv_data->dev, "mv64xxx_i2c_do_action: Invalid action: %d\n", drv_data->action); drv_data->rc = -EIO; /* FALLTHRU */ case MV64XXX_I2C_ACTION_SEND_STOP: drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; - writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + mv_ctrl_writel(drv_data, drv_data->cntl_bits | + MV64XXX_I2C_REG_CONTROL_STOP, + MV64XXX_I2C_REG_CONTROL); drv_data->block = 0; wake_up_interruptible(&drv_data->waitq); break; } } -static int +static irqreturn_t mv64xxx_i2c_intr(int irq, void *dev_id) { struct mv64xxx_i2c_data *drv_data = dev_id; unsigned long flags; u32 status; - int rc = IRQ_NONE; + irqreturn_t rc = IRQ_NONE; spin_lock_irqsave(&drv_data->lock, flags); while (readl(drv_data->reg_base + MV64XXX_I2C_REG_CONTROL) & @@ -358,7 +390,7 @@ char abort = 0; time_left = wait_event_interruptible_timeout(drv_data->waitq, - !drv_data->block, drv_data->adapter.timeout); + !drv_data->block, get_adapter(drv_data)->timeout); spin_lock_irqsave(&drv_data->lock, flags); if (!time_left) { /* Timed out */ @@ -374,11 +406,11 @@ spin_unlock_irqrestore(&drv_data->lock, flags); time_left = wait_event_timeout(drv_data->waitq, - !drv_data->block, drv_data->adapter.timeout); + !drv_data->block, get_adapter(drv_data)->timeout); if ((time_left <= 0) && drv_data->block) { drv_data->state = MV64XXX_I2C_STATE_IDLE; - dev_err(&drv_data->adapter.dev, + dev_err(drv_data->dev, "mv64xxx: I2C bus locked, block: %d, " "time_left: %d\n", drv_data->block, (int)time_left); @@ -433,7 +465,7 @@ { return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL; } - +#ifndef CONFIG_I2C_MV64XXX_PORT_EXPANDER static int mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) { @@ -451,7 +483,7 @@ .master_xfer = mv64xxx_i2c_xfer, .functionality = mv64xxx_i2c_functionality, }; - +#endif /* ***************************************************************************** * @@ -471,7 +503,7 @@ size = resource_size(r); - if (!request_mem_region(r->start, size, drv_data->adapter.name)) + if (!request_mem_region(r->start, size, pd->name)) return -EBUSY; drv_data->reg_base = ioremap(r->start, size); @@ -498,6 +530,7 @@ { struct mv64xxx_i2c_data *drv_data; struct mv64xxx_i2c_pdata *pdata = pd->dev.platform_data; + struct i2c_adapter *adapter; int rc; if ((pd->id != 0) || !pdata) @@ -506,18 +539,24 @@ drv_data = kzalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL); if (!drv_data) return -ENOMEM; +#ifndef CONFIG_I2C_MV64XXX_PORT_EXPANDER + adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); + if (!adapter) + return -ENOMEM; + drv_data->adapter = adapter; +#endif if (mv64xxx_i2c_map_regs(pd, drv_data)) { rc = -ENODEV; goto exit_kfree; } - strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter", - sizeof(drv_data->adapter.name)); - init_waitqueue_head(&drv_data->waitq); spin_lock_init(&drv_data->lock); - +#ifdef CONFIG_I2C_MV64XXX_PORT_EXPANDER + init_MUTEX(&drv_data->exp_sem); + drv_data->select_exp_port = pdata->select_exp_port; +#endif drv_data->freq_m = pdata->freq_m; drv_data->freq_n = pdata->freq_n; drv_data->irq = platform_get_irq(pd, 0); @@ -525,28 +564,35 @@ rc = -ENXIO; goto exit_unmap_regs; } - drv_data->adapter.dev.parent = &pd->dev; - drv_data->adapter.algo = &mv64xxx_i2c_algo; - drv_data->adapter.owner = THIS_MODULE; - drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout); - drv_data->adapter.nr = pd->id; + drv_data->dev = &pd->dev; +#ifndef CONFIG_I2C_MV64XXX_PORT_EXPANDER + strlcpy(drv_data->adapter->name, MV64XXX_I2C_CTLR_NAME " adapter", + sizeof(drv_data->adapter->name)); + drv_data->adapter->dev.parent = &pd->dev; + drv_data->adapter->algo = &mv64xxx_i2c_algo; + drv_data->adapter->owner = THIS_MODULE; + drv_data->adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + drv_data->adapter->timeout = pdata->timeout; + drv_data->adapter->nr = pd->id; + i2c_set_adapdata(drv_data->adapter, drv_data); +#endif platform_set_drvdata(pd, drv_data); - i2c_set_adapdata(&drv_data->adapter, drv_data); mv64xxx_i2c_hw_init(drv_data); if (request_irq(drv_data->irq, mv64xxx_i2c_intr, 0, MV64XXX_I2C_CTLR_NAME, drv_data)) { - dev_err(&drv_data->adapter.dev, + dev_err(drv_data->dev, "mv64xxx: Can't register intr handler irq: %d\n", drv_data->irq); rc = -EINVAL; goto exit_unmap_regs; - } else if ((rc = i2c_add_numbered_adapter(&drv_data->adapter)) != 0) { - dev_err(&drv_data->adapter.dev, +#ifndef CONFIG_I2C_MV64XXX_PORT_EXPANDER + } else if ((rc = i2c_add_numbered_adapter(drv_data->adapter)) != 0) { + dev_err(drv_data->dev, "mv64xxx: Can't add i2c adapter, rc: %d\n", -rc); goto exit_free_irq; +#endif } return 0; @@ -564,9 +610,11 @@ mv64xxx_i2c_remove(struct platform_device *dev) { struct mv64xxx_i2c_data *drv_data = platform_get_drvdata(dev); - int rc; + int rc = 0; - rc = i2c_del_adapter(&drv_data->adapter); +#ifndef CONFIG_I2C_MV64XXX_PORT_EXPANDER + rc = i2c_del_adapter(drv_data->adapter); +#endif free_irq(drv_data->irq, drv_data); mv64xxx_i2c_unmap_regs(drv_data); kfree(drv_data); @@ -583,15 +631,111 @@ }, }; +#ifdef CONFIG_I2C_MV64XXX_PORT_EXPANDER +static int +mv64xxx_i2c_exp_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) +{ + struct mv64xxx_i2c_exp_data *exp_drv_data = i2c_get_adapdata(adap); + struct mv64xxx_i2c_data *drv_data = exp_drv_data->hw_adapter; + int i, rc; + + down(&drv_data->exp_sem); + drv_data->adapter = adap; + drv_data->select_exp_port(adap->nr); + for (i=0; i 1 && (i != num-1)) + {//if comebine access, we don't send stop signal between msgs. + drv_data->combine_access = 1; + }else{ + drv_data->combine_access = 0; + } + + if ((rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i])) < 0) { + up(&drv_data->exp_sem); + return rc; + } + } + up(&drv_data->exp_sem); + return num; +} + +static const struct i2c_algorithm mv64xxx_i2c_exp_algo = { + .master_xfer = mv64xxx_i2c_exp_xfer, + .functionality = mv64xxx_i2c_functionality, +}; + +static int __devinit +mv64xxx_i2c_exp_probe(struct platform_device *pd) +{ + struct mv64xxx_i2c_exp_data *exp_drv_data; + struct mv64xxx_i2c_exp_pdata *pdata = pd->dev.platform_data; + int rc = 0; + + if (!pdata) + return -ENODEV; + + exp_drv_data = devm_kzalloc(&pd->dev, sizeof(struct mv64xxx_i2c_exp_data), + GFP_KERNEL); + if (!exp_drv_data) + return -ENOMEM; + + strlcpy(exp_drv_data->adapter.name, MV64XXX_I2C_EXPANDER_NAME " adapter", + sizeof(exp_drv_data->adapter.name)); + exp_drv_data->adapter.dev.parent = &pd->dev; + exp_drv_data->adapter.algo = &mv64xxx_i2c_exp_algo; + exp_drv_data->adapter.owner = THIS_MODULE; + exp_drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + exp_drv_data->adapter.timeout = pdata->timeout; + exp_drv_data->adapter.nr = pd->id; + exp_drv_data->hw_adapter = platform_get_drvdata(pdata->hw_adapter); + platform_set_drvdata(pd, exp_drv_data); + i2c_set_adapdata(&exp_drv_data->adapter, exp_drv_data); + + if ((rc = i2c_add_numbered_adapter(&exp_drv_data->adapter)) != 0) { + dev_err(&pd->dev, + "mv64xxx expander: Can't add i2c adapter, rc: %d\n", -rc); + } + return rc; +} + +static int __devexit +mv64xxx_i2c_exp_remove(struct platform_device *dev) +{ + struct mv64xxx_i2c_exp_data *exp_drv_data = platform_get_drvdata(dev); + + return i2c_del_adapter(&exp_drv_data->adapter); +} + +static struct platform_driver mv64xxx_i2c_exp_driver = { + .probe = mv64xxx_i2c_exp_probe, + .remove = __devexit_p(mv64xxx_i2c_exp_remove), + .driver = { + .owner = THIS_MODULE, + .name = MV64XXX_I2C_EXPANDER_NAME, + }, +}; +#endif + static int __init mv64xxx_i2c_init(void) { - return platform_driver_register(&mv64xxx_i2c_driver); + int rc = platform_driver_register(&mv64xxx_i2c_driver); + if (rc < 0) + return rc; + +#ifdef CONFIG_I2C_MV64XXX_PORT_EXPANDER + rc = platform_driver_register(&mv64xxx_i2c_exp_driver); +#endif + return rc; } static void __exit mv64xxx_i2c_exit(void) { +#ifdef CONFIG_I2C_MV64XXX_PORT_EXPANDER + platform_driver_unregister(&mv64xxx_i2c_exp_driver); +#endif platform_driver_unregister(&mv64xxx_i2c_driver); } --- linux-mvl-dove-2.6.31.orig/drivers/i2c/busses/i2c-sis96x.c +++ linux-mvl-dove-2.6.31/drivers/i2c/busses/i2c-sis96x.c @@ -280,7 +280,7 @@ retval = acpi_check_resource_conflict(&dev->resource[SIS96x_BAR]); if (retval) - return retval; + return -ENODEV; /* Everything is happy, let's grab the memory and set things up. */ if (!request_region(sis96x_smbus_base, SMB_IOSIZE, --- linux-mvl-dove-2.6.31.orig/drivers/i2c/busses/i2c-i801.c +++ linux-mvl-dove-2.6.31/drivers/i2c/busses/i2c-i801.c @@ -732,8 +732,10 @@ } err = acpi_check_resource_conflict(&dev->resource[SMBBAR]); - if (err) + if (err) { + err = -ENODEV; goto exit; + } err = pci_request_region(dev, SMBBAR, i801_driver.name); if (err) { --- linux-mvl-dove-2.6.31.orig/drivers/i2c/busses/i2c-isch.c +++ linux-mvl-dove-2.6.31/drivers/i2c/busses/i2c-isch.c @@ -281,7 +281,7 @@ return -ENODEV; } if (acpi_check_region(sch_smba, SMBIOSIZE, sch_driver.name)) - return -EBUSY; + return -ENODEV; if (!request_region(sch_smba, SMBIOSIZE, sch_driver.name)) { dev_err(&dev->dev, "SMBus region 0x%x already in use!\n", sch_smba); --- linux-mvl-dove-2.6.31.orig/drivers/i2c/busses/Kconfig +++ linux-mvl-dove-2.6.31/drivers/i2c/busses/Kconfig @@ -422,6 +422,13 @@ This driver can also be built as a module. If so, the module will be called i2c-mv64xxx. +config I2C_MV64XXX_PORT_EXPANDER + bool "Marvell mv64xxx I2C Port Expander" + depends on I2C_MV64XXX + help + If you say yes to this option, support will be included for the + I2C port expander on some of Marvell SoC's. + config I2C_OCORES tristate "OpenCores I2C Controller" depends on EXPERIMENTAL --- linux-mvl-dove-2.6.31.orig/drivers/i2c/busses/i2c-viapro.c +++ linux-mvl-dove-2.6.31/drivers/i2c/busses/i2c-viapro.c @@ -365,7 +365,7 @@ found: error = acpi_check_region(vt596_smba, 8, vt596_driver.name); if (error) - return error; + return -ENODEV; if (!request_region(vt596_smba, 8, vt596_driver.name)) { dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n", --- linux-mvl-dove-2.6.31.orig/drivers/i2c/busses/i2c-amd756.c +++ linux-mvl-dove-2.6.31/drivers/i2c/busses/i2c-amd756.c @@ -364,7 +364,7 @@ error = acpi_check_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name); if (error) - return error; + return -ENODEV; if (!request_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name)) { dev_err(&pdev->dev, "SMB region 0x%x already in use!\n", --- linux-mvl-dove-2.6.31.orig/drivers/i2c/busses/i2c-amd8111.c +++ linux-mvl-dove-2.6.31/drivers/i2c/busses/i2c-amd8111.c @@ -376,8 +376,10 @@ smbus->size = pci_resource_len(dev, 0); error = acpi_check_resource_conflict(&dev->resource[0]); - if (error) + if (error) { + error = -ENODEV; goto out_kfree; + } if (!request_region(smbus->base, smbus->size, amd8111_driver.name)) { error = -EBUSY; --- linux-mvl-dove-2.6.31.orig/drivers/serial/suncore.h +++ linux-mvl-dove-2.6.31/drivers/serial/suncore.h @@ -26,7 +26,8 @@ extern void sunserial_unregister_minors(struct uart_driver *, int); extern int sunserial_console_match(struct console *, struct device_node *, - struct uart_driver *, int); -extern void sunserial_console_termios(struct console *); + struct uart_driver *, int, bool); +extern void sunserial_console_termios(struct console *, + struct device_node *); #endif /* !(_SERIAL_SUN_H) */ --- linux-mvl-dove-2.6.31.orig/drivers/serial/sunzilog.c +++ linux-mvl-dove-2.6.31/drivers/serial/sunzilog.c @@ -1180,7 +1180,7 @@ (sunzilog_reg.minor - 64) + con->index, con->index); /* Get firmware console settings. */ - sunserial_console_termios(con); + sunserial_console_termios(con, to_of_device(up->port.dev)->node); /* Firmware console speed is limited to 150-->38400 baud so * this hackish cflag thing is OK. @@ -1416,7 +1416,8 @@ if (!keyboard_mouse) { if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node, - &sunzilog_reg, up[0].port.line)) + &sunzilog_reg, up[0].port.line, + false)) up->flags |= SUNZILOG_FLAG_IS_CONS; err = uart_add_one_port(&sunzilog_reg, &up[0].port); if (err) { @@ -1425,7 +1426,8 @@ return err; } if (sunserial_console_match(SUNZILOG_CONSOLE(), op->node, - &sunzilog_reg, up[1].port.line)) + &sunzilog_reg, up[1].port.line, + false)) up->flags |= SUNZILOG_FLAG_IS_CONS; err = uart_add_one_port(&sunzilog_reg, &up[1].port); if (err) { --- linux-mvl-dove-2.6.31.orig/drivers/serial/sunsab.c +++ linux-mvl-dove-2.6.31/drivers/serial/sunsab.c @@ -883,7 +883,7 @@ printk("Console: ttyS%d (SAB82532)\n", (sunsab_reg.minor - 64) + con->index); - sunserial_console_termios(con); + sunserial_console_termios(con, to_of_device(up->port.dev)->node); switch (con->cflag & CBAUD) { case B150: baud = 150; break; @@ -1027,10 +1027,12 @@ goto out1; sunserial_console_match(SUNSAB_CONSOLE(), op->node, - &sunsab_reg, up[0].port.line); + &sunsab_reg, up[0].port.line, + false); sunserial_console_match(SUNSAB_CONSOLE(), op->node, - &sunsab_reg, up[1].port.line); + &sunsab_reg, up[1].port.line, + false); err = uart_add_one_port(&sunsab_reg, &up[0].port); if (err) @@ -1116,7 +1118,6 @@ if (!sunsab_ports) return -ENOMEM; - sunsab_reg.cons = SUNSAB_CONSOLE(); err = sunserial_register_minors(&sunsab_reg, num_channels); if (err) { kfree(sunsab_ports); --- linux-mvl-dove-2.6.31.orig/drivers/serial/bfin_5xx.c +++ linux-mvl-dove-2.6.31/drivers/serial/bfin_5xx.c @@ -42,6 +42,10 @@ # undef CONFIG_EARLY_PRINTK #endif +#ifdef CONFIG_SERIAL_BFIN_MODULE +# undef CONFIG_EARLY_PRINTK +#endif + /* UART name and device definitions */ #define BFIN_SERIAL_NAME "ttyBF" #define BFIN_SERIAL_MAJOR 204 --- linux-mvl-dove-2.6.31.orig/drivers/serial/serial_cs.c +++ linux-mvl-dove-2.6.31/drivers/serial/serial_cs.c @@ -884,6 +884,7 @@ PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */ PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */ PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"), + PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-2", 0x96913a85, 0x27ab5437, "COMpad2.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"), PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"), PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "RS-COM-2P.cis"), --- linux-mvl-dove-2.6.31.orig/drivers/serial/sunsu.c +++ linux-mvl-dove-2.6.31/drivers/serial/sunsu.c @@ -1329,11 +1329,9 @@ */ static int __init sunsu_console_setup(struct console *co, char *options) { + static struct ktermios dummy; + struct ktermios termios; struct uart_port *port; - int baud = 9600; - int bits = 8; - int parity = 'n'; - int flow = 'n'; printk("Console: ttyS%d (SU)\n", (sunsu_reg.minor - 64) + co->index); @@ -1352,10 +1350,15 @@ */ spin_lock_init(&port->lock); - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); + /* Get firmware console settings. */ + sunserial_console_termios(co, to_of_device(port->dev)->node); - return uart_set_options(port, co, baud, parity, bits, flow); + memset(&termios, 0, sizeof(struct ktermios)); + termios.c_cflag = co->cflag; + port->mctrl |= TIOCM_DTR; + port->ops->set_termios(port, &termios, &dummy); + + return 0; } static struct console sunsu_console = { @@ -1409,6 +1412,7 @@ struct uart_sunsu_port *up; struct resource *rp; enum su_type type; + bool ignore_line; int err; type = su_get_type(dp); @@ -1467,8 +1471,14 @@ up->port.ops = &sunsu_pops; + ignore_line = false; + if (!strcmp(dp->name, "rsc-console") || + !strcmp(dp->name, "lom-console")) + ignore_line = true; + sunserial_console_match(SUNSU_CONSOLE(), dp, - &sunsu_reg, up->port.line); + &sunsu_reg, up->port.line, + ignore_line); err = uart_add_one_port(&sunsu_reg, &up->port); if (err) goto out_unmap; @@ -1517,6 +1527,10 @@ .name = "serial", .compatible = "su", }, + { + .type = "serial", + .compatible = "su", + }, {}, }; MODULE_DEVICE_TABLE(of, su_match); @@ -1548,6 +1562,12 @@ num_uart++; } } + for_each_node_by_type(dp, "serial") { + if (of_device_is_compatible(dp, "su")) { + if (su_get_type(dp) == SU_PORT_PORT) + num_uart++; + } + } if (num_uart) { err = sunserial_register_minors(&sunsu_reg, num_uart); --- linux-mvl-dove-2.6.31.orig/drivers/serial/suncore.c +++ linux-mvl-dove-2.6.31/drivers/serial/suncore.c @@ -53,20 +53,21 @@ EXPORT_SYMBOL(sunserial_unregister_minors); int sunserial_console_match(struct console *con, struct device_node *dp, - struct uart_driver *drv, int line) + struct uart_driver *drv, int line, bool ignore_line) { - int off; - if (!con || of_console_device != dp) return 0; - off = 0; - if (of_console_options && - *of_console_options == 'b') - off = 1; + if (!ignore_line) { + int off = 0; - if ((line & 1) != off) - return 0; + if (of_console_options && + *of_console_options == 'b') + off = 1; + + if ((line & 1) != off) + return 0; + } con->index = line; drv->cons = con; @@ -76,23 +77,24 @@ } EXPORT_SYMBOL(sunserial_console_match); -void -sunserial_console_termios(struct console *con) +void sunserial_console_termios(struct console *con, struct device_node *uart_dp) { - struct device_node *dp; - const char *od, *mode, *s; + const char *mode, *s; char mode_prop[] = "ttyX-mode"; int baud, bits, stop, cflag; char parity; - dp = of_find_node_by_path("/options"); - od = of_get_property(dp, "output-device", NULL); - if (!strcmp(od, "rsc")) { - mode = of_get_property(of_console_device, + if (!strcmp(uart_dp->name, "rsc") || + !strcmp(uart_dp->name, "rsc-console") || + !strcmp(uart_dp->name, "rsc-control")) { + mode = of_get_property(uart_dp, "ssp-console-modes", NULL); if (!mode) mode = "115200,8,n,1,-"; + } else if (!strcmp(uart_dp->name, "lom-console")) { + mode = "9600,8,n,1,-"; } else { + struct device_node *dp; char c; c = 'a'; @@ -101,6 +103,7 @@ mode_prop[3] = c; + dp = of_find_node_by_path("/options"); mode = of_get_property(dp, mode_prop, NULL); if (!mode) mode = "9600,8,n,1,-"; --- linux-mvl-dove-2.6.31.orig/drivers/serial/8250_pci.c +++ linux-mvl-dove-2.6.31/drivers/serial/8250_pci.c @@ -1561,6 +1561,7 @@ pbn_exar_XR17C152, pbn_exar_XR17C154, pbn_exar_XR17C158, + pbn_exar_ibm_saturn, pbn_pasemi_1682M, pbn_ni8430_2, pbn_ni8430_4, @@ -2146,6 +2147,13 @@ .base_baud = 921600, .uart_offset = 0x200, }, + [pbn_exar_ibm_saturn] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 921600, + .uart_offset = 0x200, + }, + /* * PA Semi PWRficient PA6T-1682M on-chip UART */ @@ -2649,6 +2657,9 @@ PCI_SUBVENDOR_ID_CONNECT_TECH, PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485, 0, 0, pbn_b0_8_1843200_200 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152, + PCI_VENDOR_ID_IBM, PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT, + 0, 0, pbn_exar_ibm_saturn }, { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, --- linux-mvl-dove-2.6.31.orig/drivers/serial/sunhv.c +++ linux-mvl-dove-2.6.31/drivers/serial/sunhv.c @@ -566,7 +566,7 @@ goto out_free_con_read_page; sunserial_console_match(&sunhv_console, op->node, - &sunhv_reg, port->line); + &sunhv_reg, port->line, false); err = uart_add_one_port(&sunhv_reg, port); if (err) --- linux-mvl-dove-2.6.31.orig/drivers/serial/of_serial.c +++ linux-mvl-dove-2.6.31/drivers/serial/of_serial.c @@ -161,6 +161,7 @@ static struct of_device_id __devinitdata of_platform_serial_table[] = { { .type = "serial", .compatible = "ns8250", .data = (void *)PORT_8250, }, { .type = "serial", .compatible = "ns16450", .data = (void *)PORT_16450, }, + { .type = "serial", .compatible = "ns16550a", .data = (void *)PORT_16550A, }, { .type = "serial", .compatible = "ns16550", .data = (void *)PORT_16550, }, { .type = "serial", .compatible = "ns16750", .data = (void *)PORT_16750, }, { .type = "serial", .compatible = "ns16850", .data = (void *)PORT_16850, }, --- linux-mvl-dove-2.6.31.orig/drivers/serial/8250.c +++ linux-mvl-dove-2.6.31/drivers/serial/8250.c @@ -1337,14 +1337,12 @@ serial_out(up, UART_IER, up->ier); if (up->bugs & UART_BUG_TXEN) { - unsigned char lsr, iir; + unsigned char lsr; lsr = serial_in(up, UART_LSR); up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; - iir = serial_in(up, UART_IIR) & 0x0f; if ((up->port.type == PORT_RM9000) ? - (lsr & UART_LSR_THRE && - (iir == UART_IIR_NO_INT || iir == UART_IIR_THRI)) : - (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT)) + (lsr & UART_LSR_THRE) : + (lsr & UART_LSR_TEMT)) transmit_chars(up); } } --- linux-mvl-dove-2.6.31.orig/drivers/block/nbd.c +++ linux-mvl-dove-2.6.31/drivers/block/nbd.c @@ -56,7 +56,7 @@ static unsigned int nbds_max = 16; static struct nbd_device *nbd_dev; -static int max_part; +static int max_part = 15; /* * Use just one lock (or at most 1 per NIC). Two arguments for this: --- linux-mvl-dove-2.6.31.orig/drivers/isdn/gigaset/interface.c +++ linux-mvl-dove-2.6.31/drivers/isdn/gigaset/interface.c @@ -408,33 +408,28 @@ return retval; } -/* FIXME: This function does not have error returns */ - static int if_chars_in_buffer(struct tty_struct *tty) { struct cardstate *cs; - int retval = -ENODEV; + int retval = 0; cs = (struct cardstate *) tty->driver_data; if (!cs) { pr_err("%s: no cardstate\n", __func__); - return -ENODEV; + return 0; } gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + mutex_lock(&cs->mutex); - if (!cs->connected) { + if (!cs->connected) gig_dbg(DEBUG_IF, "not connected"); - retval = -ENODEV; - } else if (!cs->open_count) + else if (!cs->open_count) dev_warn(cs->dev, "%s: device not opened\n", __func__); - else if (cs->mstate != MS_LOCKED) { + else if (cs->mstate != MS_LOCKED) dev_warn(cs->dev, "can't write to unlocked device\n"); - retval = -EBUSY; - } else + else retval = cs->ops->chars_in_buffer(cs); mutex_unlock(&cs->mutex); --- linux-mvl-dove-2.6.31.orig/drivers/isdn/hisax/hfc_usb.c +++ linux-mvl-dove-2.6.31/drivers/isdn/hisax/hfc_usb.c @@ -817,8 +817,8 @@ } /* we have a complete hdlc packet */ if (finish) { - if ((!fifo->skbuff->data[fifo->skbuff->len - 1]) - && (fifo->skbuff->len > 3)) { + if (fifo->skbuff->len > 3 && + !fifo->skbuff->data[fifo->skbuff->len - 1]) { if (fifon == HFCUSB_D_RX) { DBG(HFCUSB_DBG_DCHANNEL, --- linux-mvl-dove-2.6.31.orig/drivers/isdn/i4l/isdn_ppp.c +++ linux-mvl-dove-2.6.31/drivers/isdn/i4l/isdn_ppp.c @@ -1535,10 +1535,8 @@ int sz = ISDN_MAX_CHANNELS*sizeof(ippp_bundle); if( (isdn_ppp_bundle_arr = kzalloc(sz, GFP_KERNEL)) == NULL ) return -ENOMEM; - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { + for( i = 0; i < ISDN_MAX_CHANNELS; i++ ) spin_lock_init(&isdn_ppp_bundle_arr[i].lock); - skb_queue_head_init(&isdn_ppp_bundle_arr[i].frags); - } return 0; } @@ -1571,7 +1569,7 @@ if ((lp->netdev->pb = isdn_ppp_mp_bundle_alloc()) == NULL) return -ENOMEM; lp->next = lp->last = lp; /* nobody else in a queue */ - skb_queue_head_init(&lp->netdev->pb->frags); + lp->netdev->pb->frags = NULL; lp->netdev->pb->frames = 0; lp->netdev->pb->seq = UINT_MAX; } @@ -1583,29 +1581,28 @@ static u32 isdn_ppp_mp_get_seq( int short_seq, struct sk_buff * skb, u32 last_seq ); -static void isdn_ppp_mp_discard(ippp_bundle *mp, struct sk_buff *from, - struct sk_buff *to); -static void isdn_ppp_mp_reassembly(isdn_net_dev *net_dev, isdn_net_local *lp, - struct sk_buff *from, struct sk_buff *to, - u32 lastseq); -static void isdn_ppp_mp_free_skb(ippp_bundle *mp, struct sk_buff *skb); +static struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp, + struct sk_buff * from, struct sk_buff * to ); +static void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp, + struct sk_buff * from, struct sk_buff * to ); +static void isdn_ppp_mp_free_skb( ippp_bundle * mp, struct sk_buff * skb ); static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb ); static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, - struct sk_buff *skb) + struct sk_buff *skb) { - struct sk_buff *newfrag, *frag, *start, *nextf; - u32 newseq, minseq, thisseq; - isdn_mppp_stats *stats; struct ippp_struct *is; + isdn_net_local * lpq; + ippp_bundle * mp; + isdn_mppp_stats * stats; + struct sk_buff * newfrag, * frag, * start, *nextf; + u32 newseq, minseq, thisseq; unsigned long flags; - isdn_net_local *lpq; - ippp_bundle *mp; int slot; spin_lock_irqsave(&net_dev->pb->lock, flags); - mp = net_dev->pb; - stats = &mp->stats; + mp = net_dev->pb; + stats = &mp->stats; slot = lp->ppp_slot; if (slot < 0 || slot >= ISDN_MAX_CHANNELS) { printk(KERN_ERR "%s: lp->ppp_slot(%d)\n", @@ -1616,19 +1613,20 @@ return; } is = ippp_table[slot]; - if (++mp->frames > stats->max_queue_len) + if( ++mp->frames > stats->max_queue_len ) stats->max_queue_len = mp->frames; if (is->debug & 0x8) isdn_ppp_mp_print_recv_pkt(lp->ppp_slot, skb); newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ, - skb, is->last_link_seqno); + skb, is->last_link_seqno); + /* if this packet seq # is less than last already processed one, * toss it right away, but check for sequence start case first */ - if (mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT)) { + if( mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT) ) { mp->seq = newseq; /* the first packet: required for * rfc1990 non-compliant clients -- * prevents constant packet toss */ @@ -1659,31 +1657,22 @@ * packets */ newfrag = skb; - /* Insert new fragment into the proper sequence slot. */ - skb_queue_walk(&mp->frags, frag) { - if (MP_SEQ(frag) == newseq) { - isdn_ppp_mp_free_skb(mp, newfrag); - newfrag = NULL; - break; - } - if (MP_LT(newseq, MP_SEQ(frag))) { - __skb_queue_before(&mp->frags, frag, newfrag); - newfrag = NULL; - break; - } - } - if (newfrag) - __skb_queue_tail(&mp->frags, newfrag); + /* if this new fragment is before the first one, then enqueue it now. */ + if ((frag = mp->frags) == NULL || MP_LT(newseq, MP_SEQ(frag))) { + newfrag->next = frag; + mp->frags = frag = newfrag; + newfrag = NULL; + } - frag = skb_peek(&mp->frags); - start = ((MP_FLAGS(frag) & MP_BEGIN_FRAG) && - (MP_SEQ(frag) == mp->seq)) ? frag : NULL; - if (!start) - goto check_overflow; + start = MP_FLAGS(frag) & MP_BEGIN_FRAG && + MP_SEQ(frag) == mp->seq ? frag : NULL; - /* main fragment traversing loop + /* + * main fragment traversing loop * * try to accomplish several tasks: + * - insert new fragment into the proper sequence slot (once that's done + * newfrag will be set to NULL) * - reassemble any complete fragment sequence (non-null 'start' * indicates there is a continguous sequence present) * - discard any incomplete sequences that are below minseq -- due @@ -1692,46 +1681,71 @@ * come to complete such sequence and it should be discarded * * loop completes when we accomplished the following tasks: + * - new fragment is inserted in the proper sequence ('newfrag' is + * set to NULL) * - we hit a gap in the sequence, so no reassembly/processing is * possible ('start' would be set to NULL) * * algorithm for this code is derived from code in the book * 'PPP Design And Debugging' by James Carlson (Addison-Wesley) */ - skb_queue_walk_safe(&mp->frags, frag, nextf) { - thisseq = MP_SEQ(frag); + while (start != NULL || newfrag != NULL) { + + thisseq = MP_SEQ(frag); + nextf = frag->next; - /* check for misplaced start */ - if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) { - printk(KERN_WARNING"isdn_mppp(seq %d): new " - "BEGIN flag with no prior END", thisseq); - stats->seqerrs++; - stats->frame_drops++; - isdn_ppp_mp_discard(mp, start, frag); - start = frag; - } else if (MP_LE(thisseq, minseq)) { - if (MP_FLAGS(frag) & MP_BEGIN_FRAG) + /* drop any duplicate fragments */ + if (newfrag != NULL && thisseq == newseq) { + isdn_ppp_mp_free_skb(mp, newfrag); + newfrag = NULL; + } + + /* insert new fragment before next element if possible. */ + if (newfrag != NULL && (nextf == NULL || + MP_LT(newseq, MP_SEQ(nextf)))) { + newfrag->next = nextf; + frag->next = nextf = newfrag; + newfrag = NULL; + } + + if (start != NULL) { + /* check for misplaced start */ + if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) { + printk(KERN_WARNING"isdn_mppp(seq %d): new " + "BEGIN flag with no prior END", thisseq); + stats->seqerrs++; + stats->frame_drops++; + start = isdn_ppp_mp_discard(mp, start,frag); + nextf = frag->next; + } + } else if (MP_LE(thisseq, minseq)) { + if (MP_FLAGS(frag) & MP_BEGIN_FRAG) start = frag; - else { + else { if (MP_FLAGS(frag) & MP_END_FRAG) - stats->frame_drops++; - __skb_unlink(skb, &mp->frags); + stats->frame_drops++; + if( mp->frags == frag ) + mp->frags = nextf; isdn_ppp_mp_free_skb(mp, frag); + frag = nextf; continue; - } + } } - /* if we have end fragment, then we have full reassembly - * sequence -- reassemble and process packet now + /* if start is non-null and we have end fragment, then + * we have full reassembly sequence -- reassemble + * and process packet now */ - if (MP_FLAGS(frag) & MP_END_FRAG) { - minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK; - /* Reassemble the packet then dispatch it */ - isdn_ppp_mp_reassembly(net_dev, lp, start, frag, thisseq); + if (start != NULL && (MP_FLAGS(frag) & MP_END_FRAG)) { + minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK; + /* Reassemble the packet then dispatch it */ + isdn_ppp_mp_reassembly(net_dev, lp, start, nextf); - start = NULL; - frag = NULL; - } + start = NULL; + frag = NULL; + + mp->frags = nextf; + } /* check if need to update start pointer: if we just * reassembled the packet and sequence is contiguous @@ -1742,25 +1756,26 @@ * below low watermark and set start to the next frag or * clear start ptr. */ - if (nextf != (struct sk_buff *)&mp->frags && + if (nextf != NULL && ((thisseq+1) & MP_LONGSEQ_MASK) == MP_SEQ(nextf)) { - /* if we just reassembled and the next one is here, - * then start another reassembly. - */ - if (frag == NULL) { + /* if we just reassembled and the next one is here, + * then start another reassembly. */ + + if (frag == NULL) { if (MP_FLAGS(nextf) & MP_BEGIN_FRAG) - start = nextf; - else { - printk(KERN_WARNING"isdn_mppp(seq %d):" - " END flag with no following " - "BEGIN", thisseq); + start = nextf; + else + { + printk(KERN_WARNING"isdn_mppp(seq %d):" + " END flag with no following " + "BEGIN", thisseq); stats->seqerrs++; } } - } else { - if (nextf != (struct sk_buff *)&mp->frags && - frag != NULL && - MP_LT(thisseq, minseq)) { + + } else { + if ( nextf != NULL && frag != NULL && + MP_LT(thisseq, minseq)) { /* we've got a break in the sequence * and we not at the end yet * and we did not just reassembled @@ -1769,39 +1784,41 @@ * discard all the frames below low watermark * and start over */ stats->frame_drops++; - isdn_ppp_mp_discard(mp, start, nextf); + mp->frags = isdn_ppp_mp_discard(mp,start,nextf); } /* break in the sequence, no reassembly */ - start = NULL; - } - if (!start) - break; - } + start = NULL; + } + + frag = nextf; + } /* while -- main loop */ + + if (mp->frags == NULL) + mp->frags = frag; -check_overflow: /* rather straighforward way to deal with (not very) possible - * queue overflow - */ + * queue overflow */ if (mp->frames > MP_MAX_QUEUE_LEN) { stats->overflows++; - skb_queue_walk_safe(&mp->frags, frag, nextf) { - if (mp->frames <= MP_MAX_QUEUE_LEN) - break; - __skb_unlink(frag, &mp->frags); - isdn_ppp_mp_free_skb(mp, frag); + while (mp->frames > MP_MAX_QUEUE_LEN) { + frag = mp->frags->next; + isdn_ppp_mp_free_skb(mp, mp->frags); + mp->frags = frag; } } spin_unlock_irqrestore(&mp->lock, flags); } -static void isdn_ppp_mp_cleanup(isdn_net_local *lp) +static void isdn_ppp_mp_cleanup( isdn_net_local * lp ) { - struct sk_buff *skb, *tmp; - - skb_queue_walk_safe(&lp->netdev->pb->frags, skb, tmp) { - __skb_unlink(skb, &lp->netdev->pb->frags); - isdn_ppp_mp_free_skb(lp->netdev->pb, skb); + struct sk_buff * frag = lp->netdev->pb->frags; + struct sk_buff * nextfrag; + while( frag ) { + nextfrag = frag->next; + isdn_ppp_mp_free_skb(lp->netdev->pb, frag); + frag = nextfrag; } + lp->netdev->pb->frags = NULL; } static u32 isdn_ppp_mp_get_seq( int short_seq, @@ -1838,115 +1855,72 @@ return seq; } -static void isdn_ppp_mp_discard(ippp_bundle *mp, struct sk_buff *from, - struct sk_buff *to) +struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp, + struct sk_buff * from, struct sk_buff * to ) { - if (from) { - struct sk_buff *skb, *tmp; - int freeing = 0; - - skb_queue_walk_safe(&mp->frags, skb, tmp) { - if (skb == to) - break; - if (skb == from) - freeing = 1; - if (!freeing) - continue; - __skb_unlink(skb, &mp->frags); - isdn_ppp_mp_free_skb(mp, skb); + if( from ) + while (from != to) { + struct sk_buff * next = from->next; + isdn_ppp_mp_free_skb(mp, from); + from = next; } - } -} - -static unsigned int calc_tot_len(struct sk_buff_head *queue, - struct sk_buff *from, struct sk_buff *to) -{ - unsigned int tot_len = 0; - struct sk_buff *skb; - int found_start = 0; - - skb_queue_walk(queue, skb) { - if (skb == from) - found_start = 1; - if (!found_start) - continue; - tot_len += skb->len - MP_HEADER_LEN; - if (skb == to) - break; - } - return tot_len; + return from; } -/* Reassemble packet using fragments in the reassembly queue from - * 'from' until 'to', inclusive. - */ -static void isdn_ppp_mp_reassembly(isdn_net_dev *net_dev, isdn_net_local *lp, - struct sk_buff *from, struct sk_buff *to, - u32 lastseq) +void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp, + struct sk_buff * from, struct sk_buff * to ) { - ippp_bundle *mp = net_dev->pb; - unsigned int tot_len; - struct sk_buff *skb; + ippp_bundle * mp = net_dev->pb; int proto; + struct sk_buff * skb; + unsigned int tot_len; if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) { printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n", __func__, lp->ppp_slot); return; } - - tot_len = calc_tot_len(&mp->frags, from, to); - - if (MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG)) { - if (ippp_table[lp->ppp_slot]->debug & 0x40) + if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) { + if( ippp_table[lp->ppp_slot]->debug & 0x40 ) printk(KERN_DEBUG "isdn_mppp: reassembly: frame %d, " - "len %d\n", MP_SEQ(from), from->len); + "len %d\n", MP_SEQ(from), from->len ); skb = from; skb_pull(skb, MP_HEADER_LEN); - __skb_unlink(skb, &mp->frags); mp->frames--; } else { - struct sk_buff *walk, *tmp; - int found_start = 0; + struct sk_buff * frag; + int n; - if (ippp_table[lp->ppp_slot]->debug & 0x40) - printk(KERN_DEBUG"isdn_mppp: reassembling frames %d " - "to %d, len %d\n", MP_SEQ(from), lastseq, - tot_len); + for(tot_len=n=0, frag=from; frag != to; frag=frag->next, n++) + tot_len += frag->len - MP_HEADER_LEN; - skb = dev_alloc_skb(tot_len); - if (!skb) + if( ippp_table[lp->ppp_slot]->debug & 0x40 ) + printk(KERN_DEBUG"isdn_mppp: reassembling frames %d " + "to %d, len %d\n", MP_SEQ(from), + (MP_SEQ(from)+n-1) & MP_LONGSEQ_MASK, tot_len ); + if( (skb = dev_alloc_skb(tot_len)) == NULL ) { printk(KERN_ERR "isdn_mppp: cannot allocate sk buff " - "of size %d\n", tot_len); - - found_start = 0; - skb_queue_walk_safe(&mp->frags, walk, tmp) { - if (walk == from) - found_start = 1; - if (!found_start) - continue; + "of size %d\n", tot_len); + isdn_ppp_mp_discard(mp, from, to); + return; + } - if (skb) { - unsigned int len = walk->len - MP_HEADER_LEN; - skb_copy_from_linear_data_offset(walk, MP_HEADER_LEN, - skb_put(skb, len), - len); - } - __skb_unlink(walk, &mp->frags); - isdn_ppp_mp_free_skb(mp, walk); + while( from != to ) { + unsigned int len = from->len - MP_HEADER_LEN; - if (walk == to) - break; + skb_copy_from_linear_data_offset(from, MP_HEADER_LEN, + skb_put(skb,len), + len); + frag = from->next; + isdn_ppp_mp_free_skb(mp, from); + from = frag; } } - if (!skb) - return; - proto = isdn_ppp_strip_proto(skb); isdn_ppp_push_higher(net_dev, lp, skb, proto); } -static void isdn_ppp_mp_free_skb(ippp_bundle *mp, struct sk_buff *skb) +static void isdn_ppp_mp_free_skb(ippp_bundle * mp, struct sk_buff * skb) { dev_kfree_skb(skb); mp->frames--; --- linux-mvl-dove-2.6.31.orig/drivers/ata/sata_nv.c +++ linux-mvl-dove-2.6.31/drivers/ata/sata_nv.c @@ -1594,9 +1594,21 @@ !ata_dev_enabled(link->device)) sata_link_hardreset(link, sata_deb_timing_hotplug, deadline, NULL, NULL); - else if (!(ehc->i.flags & ATA_EHI_QUIET)) - ata_link_printk(link, KERN_INFO, - "nv: skipping hardreset on occupied port\n"); + else { + const unsigned long *timing = sata_ehc_deb_timing(ehc); + int rc; + + if (!(ehc->i.flags & ATA_EHI_QUIET)) + ata_link_printk(link, KERN_INFO, "nv: skipping " + "hardreset on occupied port\n"); + + /* make sure the link is online */ + rc = sata_link_resume(link, timing, deadline); + /* whine about phy resume failure but proceed */ + if (rc && rc != -EOPNOTSUPP) + ata_link_printk(link, KERN_WARNING, "failed to resume " + "link (errno=%d)\n", rc); + } /* device signature acquisition is unreliable */ return -EAGAIN; --- linux-mvl-dove-2.6.31.orig/drivers/ata/sata_via.c +++ linux-mvl-dove-2.6.31/drivers/ata/sata_via.c @@ -93,7 +93,6 @@ { PCI_VDEVICE(VIA, 0x7372), vt6420 }, { PCI_VDEVICE(VIA, 0x5287), vt8251 }, /* 2 sata chnls (Master/Slave) */ { PCI_VDEVICE(VIA, 0x9000), vt8251 }, - { PCI_VDEVICE(VIA, 0x9040), vt8251 }, { } /* terminate list */ }; --- linux-mvl-dove-2.6.31.orig/drivers/ata/pata_hpt37x.c +++ linux-mvl-dove-2.6.31/drivers/ata/pata_hpt37x.c @@ -24,7 +24,7 @@ #include #define DRV_NAME "pata_hpt37x" -#define DRV_VERSION "0.6.12" +#define DRV_VERSION "0.6.14" struct hpt_clock { u8 xfer_speed; @@ -404,9 +404,8 @@ pci_read_config_dword(pdev, addr1, ®); mode = hpt37x_find_mode(ap, adev->pio_mode); - mode &= ~0x8000000; /* No FIFO in PIO */ - mode &= ~0x30070000; /* Leave config bits alone */ - reg &= 0x30070000; /* Strip timing bits */ + mode &= 0xCFC3FFFF; /* Leave DMA bits alone */ + reg &= ~0xCFC3FFFF; /* Strip timing bits */ pci_write_config_dword(pdev, addr1, reg | mode); } @@ -423,8 +422,7 @@ { struct pci_dev *pdev = to_pci_dev(ap->host->dev); u32 addr1, addr2; - u32 reg; - u32 mode; + u32 reg, mode, mask; u8 fast; addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); @@ -436,11 +434,12 @@ fast |= 0x01; pci_write_config_byte(pdev, addr2, fast); + mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000; + pci_read_config_dword(pdev, addr1, ®); mode = hpt37x_find_mode(ap, adev->dma_mode); - mode |= 0x8000000; /* FIFO in MWDMA or UDMA */ - mode &= ~0xC0000000; /* Leave config bits alone */ - reg &= 0xC0000000; /* Strip timing bits */ + mode &= mask; + reg &= ~mask; pci_write_config_dword(pdev, addr1, reg | mode); } @@ -508,9 +507,8 @@ mode = hpt37x_find_mode(ap, adev->pio_mode); printk("Find mode for %d reports %X\n", adev->pio_mode, mode); - mode &= ~0x80000000; /* No FIFO in PIO */ - mode &= ~0x30070000; /* Leave config bits alone */ - reg &= 0x30070000; /* Strip timing bits */ + mode &= 0xCFC3FFFF; /* Leave DMA bits alone */ + reg &= ~0xCFC3FFFF; /* Strip timing bits */ pci_write_config_dword(pdev, addr1, reg | mode); } @@ -527,8 +525,7 @@ { struct pci_dev *pdev = to_pci_dev(ap->host->dev); u32 addr1, addr2; - u32 reg; - u32 mode; + u32 reg, mode, mask; u8 fast; addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); @@ -539,12 +536,13 @@ fast &= ~0x07; pci_write_config_byte(pdev, addr2, fast); + mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000; + pci_read_config_dword(pdev, addr1, ®); mode = hpt37x_find_mode(ap, adev->dma_mode); printk("Find mode for DMA %d reports %X\n", adev->dma_mode, mode); - mode &= ~0xC0000000; /* Leave config bits alone */ - mode |= 0x80000000; /* FIFO in MWDMA or UDMA */ - reg &= 0xC0000000; /* Strip timing bits */ + mode &= mask; + reg &= ~mask; pci_write_config_dword(pdev, addr1, reg | mode); } --- linux-mvl-dove-2.6.31.orig/drivers/ata/pata_cmd64x.c +++ linux-mvl-dove-2.6.31/drivers/ata/pata_cmd64x.c @@ -219,7 +219,7 @@ regU |= udma_data[adev->dma_mode - XFER_UDMA_0] << shift; /* Merge the control bits */ regU |= 1 << adev->devno; /* UDMA on */ - if (adev->dma_mode > 2) /* 15nS timing */ + if (adev->dma_mode > XFER_UDMA_2) /* 15nS timing */ regU |= 4 << adev->devno; } else { regU &= ~ (1 << adev->devno); /* UDMA off */ --- linux-mvl-dove-2.6.31.orig/drivers/ata/ahci.c +++ linux-mvl-dove-2.6.31/drivers/ata/ahci.c @@ -433,7 +433,8 @@ [board_ahci_sb600] = { AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | - AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255), + AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI | + AHCI_HFLAG_SECT255), .flags = AHCI_FLAG_COMMON, .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, @@ -2602,51 +2603,6 @@ } } -/* - * SB600 ahci controller on ASUS M2A-VM can't do 64bit DMA with older - * BIOS. The oldest version known to be broken is 0901 and working is - * 1501 which was released on 2007-10-26. Force 32bit DMA on anything - * older than 1501. Please read bko#9412 for more info. - */ -static bool ahci_asus_m2a_vm_32bit_only(struct pci_dev *pdev) -{ - static const struct dmi_system_id sysids[] = { - { - .ident = "ASUS M2A-VM", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, - "ASUSTeK Computer INC."), - DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), - }, - }, - { } - }; - const char *cutoff_mmdd = "10/26"; - const char *date; - int year; - - if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || - !dmi_check_system(sysids)) - return false; - - /* - * Argh.... both version and date are free form strings. - * Let's hope they're using the same date format across - * different versions. - */ - date = dmi_get_system_info(DMI_BIOS_DATE); - year = dmi_get_year(DMI_BIOS_DATE); - if (date && strlen(date) >= 10 && date[2] == '/' && date[5] == '/' && - (year > 2007 || - (year == 2007 && strncmp(date, cutoff_mmdd, 5) >= 0))) - return false; - - dev_printk(KERN_WARNING, &pdev->dev, "ASUS M2A-VM: BIOS too old, " - "forcing 32bit DMA, update BIOS\n"); - - return true; -} - static bool ahci_broken_system_poweroff(struct pci_dev *pdev) { static const struct dmi_system_id broken_systems[] = { @@ -2857,12 +2813,8 @@ if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; - /* apply ASUS M2A_VM quirk */ - if (ahci_asus_m2a_vm_32bit_only(pdev)) - hpriv->flags |= AHCI_HFLAG_32BIT_ONLY; - - if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) - pci_enable_msi(pdev); + if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev)) + pci_intx(pdev, 1); /* save initial config */ ahci_save_initial_config(pdev, hpriv); --- linux-mvl-dove-2.6.31.orig/drivers/ata/libata-core.c +++ linux-mvl-dove-2.6.31/drivers/ata/libata-core.c @@ -139,7 +139,7 @@ module_param_named(fua, libata_fua, int, 0444); MODULE_PARM_DESC(fua, "FUA support (0=off [default], 1=on)"); -static int ata_ignore_hpa; +static int ata_ignore_hpa = 1; module_param_named(ignore_hpa, ata_ignore_hpa, int, 0644); MODULE_PARM_DESC(ignore_hpa, "Ignore HPA limit (0=keep BIOS limits, 1=ignore limits, using full disk)"); @@ -709,7 +709,13 @@ head = tf->device & 0xf; sect = tf->lbal; - block = (cyl * dev->heads + head) * dev->sectors + sect; + if (!sect) { + ata_dev_printk(dev, KERN_WARNING, "device reported " + "invalid CHS sector 0\n"); + sect = 1; /* oh well */ + } + + block = (cyl * dev->heads + head) * dev->sectors + sect - 1; } return block; @@ -4295,6 +4301,7 @@ { "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, }, { "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ, }, { "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, }, + { "FUJITSU MHW2160BH PL", "0084001E", ATA_HORKAGE_NONCQ, }, /* devices which puke on READ_NATIVE_MAX */ { "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA, }, @@ -5002,12 +5009,14 @@ qc->flags |= ATA_QCFLAG_FAILED; if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) { - if (!ata_tag_internal(qc->tag)) { - /* always fill result TF for failed qc */ - fill_result_tf(qc); + /* always fill result TF for failed qc */ + fill_result_tf(qc); + + if (!ata_tag_internal(qc->tag)) ata_qc_schedule_eh(qc); - return; - } + else + __ata_qc_complete(qc); + return; } /* read result TF if requested */ --- linux-mvl-dove-2.6.31.orig/drivers/ata/sata_mv.c +++ linux-mvl-dove-2.6.31/drivers/ata/sata_mv.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -548,6 +549,10 @@ u32 irq_cause_offset; u32 irq_mask_offset; u32 unmask_all_irqs; + +#if defined(CONFIG_HAVE_CLK) + struct clk *clk; +#endif /* * These consistent DMA memory pools give us guaranteed * alignment for hardware-accessed data structures, @@ -3368,7 +3373,7 @@ ZERO(0x024); /* respq outp */ ZERO(0x020); /* respq inp */ ZERO(0x02c); /* test control */ - writel(0xbc, port_mmio + EDMA_IORDY_TMOUT); + writel(0x800, port_mmio + EDMA_IORDY_TMOUT); } #undef ZERO @@ -4016,6 +4021,14 @@ res->end - res->start + 1); hpriv->base -= SATAHC0_REG_BASE; +#if defined(CONFIG_HAVE_CLK) + hpriv->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(hpriv->clk)) + dev_notice(&pdev->dev, "cannot get clkdev\n"); + else + clk_enable(hpriv->clk); +#endif + /* * (Re-)program MBUS remapping windows if we are asked to. */ @@ -4024,12 +4037,12 @@ rc = mv_create_dma_pools(hpriv, &pdev->dev); if (rc) - return rc; + goto err; /* initialize adapter */ rc = mv_init_host(host, chip_soc); if (rc) - return rc; + goto err; dev_printk(KERN_INFO, &pdev->dev, "slots %u ports %d\n", (unsigned)MV_MAX_Q_DEPTH, @@ -4037,6 +4050,15 @@ return ata_host_activate(host, platform_get_irq(pdev, 0), mv_interrupt, IRQF_SHARED, &mv6_sht); +err: +#if defined(CONFIG_HAVE_CLK) + if (!IS_ERR(hpriv->clk)) { + clk_disable(hpriv->clk); + clk_put(hpriv->clk); + } +#endif + + return rc; } /* @@ -4051,14 +4073,66 @@ { struct device *dev = &pdev->dev; struct ata_host *host = dev_get_drvdata(dev); - +#if defined(CONFIG_HAVE_CLK) + struct mv_host_priv *hpriv = host->private_data; +#endif ata_host_detach(host); + +#if defined(CONFIG_HAVE_CLK) + if (!IS_ERR(hpriv->clk)) { + clk_disable(hpriv->clk); + clk_put(hpriv->clk); + } +#endif return 0; } +#ifdef CONFIG_PM +static int mv_platform_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct ata_host *host = dev_get_drvdata(&pdev->dev); + if (host) + return ata_host_suspend(host, state); + else + return 0; +} + +static int mv_platform_resume(struct platform_device *pdev) +{ + struct ata_host *host = dev_get_drvdata(&pdev->dev); + int ret; + + if (host) { + struct mv_host_priv *hpriv = host->private_data; + const struct mv_sata_platform_data *mv_platform_data = \ + pdev->dev.platform_data; + /* + * (Re-)program MBUS remapping windows if we are asked to. + */ + if (mv_platform_data->dram != NULL) + mv_conf_mbus_windows(hpriv, mv_platform_data->dram); + + /* initialize adapter */ + ret = mv_init_host(host, chip_soc); + if (ret) { + printk(KERN_ERR DRV_NAME ": Error during HW init\n"); + return ret; + } + ata_host_resume(host); + } + + return 0; +} +#else +#define mv_platform_suspend NULL +#define mv_platform_resume NULL +#endif + static struct platform_driver mv_platform_driver = { .probe = mv_platform_probe, .remove = __devexit_p(mv_platform_remove), + .suspend = mv_platform_suspend, + .resume = mv_platform_resume, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, --- linux-mvl-dove-2.6.31.orig/drivers/ata/pata_sc1200.c +++ linux-mvl-dove-2.6.31/drivers/ata/pata_sc1200.c @@ -235,8 +235,7 @@ .udma_mask = ATA_UDMA2, .port_ops = &sc1200_port_ops }; - /* Can't enable port 2 yet, see top comments */ - const struct ata_port_info *ppi[] = { &info, }; + const struct ata_port_info *ppi[] = { &info, NULL }; return ata_pci_sff_init_one(dev, ppi, &sc1200_sht, NULL); } --- linux-mvl-dove-2.6.31.orig/drivers/ata/pata_hpt3x2n.c +++ linux-mvl-dove-2.6.31/drivers/ata/pata_hpt3x2n.c @@ -8,7 +8,7 @@ * Copyright (C) 1999-2003 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. * Portions Copyright (C) 2003 Red Hat Inc - * Portions Copyright (C) 2005-2007 MontaVista Software, Inc. + * Portions Copyright (C) 2005-2009 MontaVista Software, Inc. * * * TODO @@ -25,7 +25,7 @@ #include #define DRV_NAME "pata_hpt3x2n" -#define DRV_VERSION "0.3.4" +#define DRV_VERSION "0.3.8" enum { HPT_PCI_FAST = (1 << 31), @@ -185,9 +185,8 @@ pci_read_config_dword(pdev, addr1, ®); mode = hpt3x2n_find_mode(ap, adev->pio_mode); - mode &= ~0x8000000; /* No FIFO in PIO */ - mode &= ~0x30070000; /* Leave config bits alone */ - reg &= 0x30070000; /* Strip timing bits */ + mode &= 0xCFC3FFFF; /* Leave DMA bits alone */ + reg &= ~0xCFC3FFFF; /* Strip timing bits */ pci_write_config_dword(pdev, addr1, reg | mode); } @@ -204,8 +203,7 @@ { struct pci_dev *pdev = to_pci_dev(ap->host->dev); u32 addr1, addr2; - u32 reg; - u32 mode; + u32 reg, mode, mask; u8 fast; addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); @@ -216,11 +214,12 @@ fast &= ~0x07; pci_write_config_byte(pdev, addr2, fast); + mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000; + pci_read_config_dword(pdev, addr1, ®); mode = hpt3x2n_find_mode(ap, adev->dma_mode); - mode |= 0x8000000; /* FIFO in MWDMA or UDMA */ - mode &= ~0xC0000000; /* Leave config bits alone */ - reg &= 0xC0000000; /* Strip timing bits */ + mode &= mask; + reg &= ~mask; pci_write_config_dword(pdev, addr1, reg | mode); } @@ -263,7 +262,7 @@ static void hpt3x2n_set_clock(struct ata_port *ap, int source) { - void __iomem *bmdma = ap->ioaddr.bmdma_addr; + void __iomem *bmdma = ap->ioaddr.bmdma_addr - ap->port_no * 8; /* Tristate the bus */ iowrite8(0x80, bmdma+0x73); @@ -273,9 +272,9 @@ iowrite8(source, bmdma+0x7B); iowrite8(0xC0, bmdma+0x79); - /* Reset state machines */ - iowrite8(0x37, bmdma+0x70); - iowrite8(0x37, bmdma+0x74); + /* Reset state machines, avoid enabling the disabled channels */ + iowrite8(ioread8(bmdma+0x70) | 0x32, bmdma+0x70); + iowrite8(ioread8(bmdma+0x74) | 0x32, bmdma+0x74); /* Complete reset */ iowrite8(0x00, bmdma+0x79); @@ -285,21 +284,10 @@ iowrite8(0x00, bmdma+0x77); } -/* Check if our partner interface is busy */ - -static int hpt3x2n_pair_idle(struct ata_port *ap) -{ - struct ata_host *host = ap->host; - struct ata_port *pair = host->ports[ap->port_no ^ 1]; - - if (pair->hsm_task_state == HSM_ST_IDLE) - return 1; - return 0; -} - static int hpt3x2n_use_dpll(struct ata_port *ap, int writing) { long flags = (long)ap->host->private_data; + /* See if we should use the DPLL */ if (writing) return USE_DPLL; /* Needed for write */ @@ -308,20 +296,35 @@ return 0; } +static int hpt3x2n_qc_defer(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct ata_port *alt = ap->host->ports[ap->port_no ^ 1]; + int rc, flags = (long)ap->host->private_data; + int dpll = hpt3x2n_use_dpll(ap, qc->tf.flags & ATA_TFLAG_WRITE); + + /* First apply the usual rules */ + rc = ata_std_qc_defer(qc); + if (rc != 0) + return rc; + + if ((flags & USE_DPLL) != dpll && alt->qc_active) + return ATA_DEFER_PORT; + return 0; +} + static unsigned int hpt3x2n_qc_issue(struct ata_queued_cmd *qc) { - struct ata_taskfile *tf = &qc->tf; struct ata_port *ap = qc->ap; int flags = (long)ap->host->private_data; + int dpll = hpt3x2n_use_dpll(ap, qc->tf.flags & ATA_TFLAG_WRITE); - if (hpt3x2n_pair_idle(ap)) { - int dpll = hpt3x2n_use_dpll(ap, (tf->flags & ATA_TFLAG_WRITE)); - if ((flags & USE_DPLL) != dpll) { - if (dpll == 1) - hpt3x2n_set_clock(ap, 0x21); - else - hpt3x2n_set_clock(ap, 0x23); - } + if ((flags & USE_DPLL) != dpll) { + flags &= ~USE_DPLL; + flags |= dpll; + ap->host->private_data = (void *)(long)flags; + + hpt3x2n_set_clock(ap, dpll ? 0x21 : 0x23); } return ata_sff_qc_issue(qc); } @@ -338,6 +341,8 @@ .inherits = &ata_bmdma_port_ops, .bmdma_stop = hpt3x2n_bmdma_stop, + + .qc_defer = hpt3x2n_qc_defer, .qc_issue = hpt3x2n_qc_issue, .cable_detect = hpt3x2n_cable_detect, @@ -455,7 +460,7 @@ unsigned int f_low, f_high; int adjust; unsigned long iobase = pci_resource_start(dev, 4); - void *hpriv = NULL; + void *hpriv = (void *)USE_DPLL; int rc; rc = pcim_enable_device(dev); @@ -543,7 +548,7 @@ /* Set our private data up. We only need a few flags so we use it directly */ if (pci_mhz > 60) { - hpriv = (void *)PCI66; + hpriv = (void *)(PCI66 | USE_DPLL); /* * On HPT371N, if ATA clock is 66 MHz we must set bit 2 in * the MISC. register to stretch the UltraDMA Tss timing. --- linux-mvl-dove-2.6.31.orig/drivers/ata/pata_amd.c +++ linux-mvl-dove-2.6.31/drivers/ata/pata_amd.c @@ -307,6 +307,9 @@ limit |= ATA_MASK_PIO; if (!(limit & (ATA_MASK_MWDMA | ATA_MASK_UDMA))) limit |= ATA_MASK_MWDMA | ATA_MASK_UDMA; + /* PIO4, MWDMA2, UDMA2 should always be supported regardless of + cable detection result */ + limit |= ata_pack_xfermask(ATA_PIO4, ATA_MWDMA2, ATA_UDMA2); ata_port_printk(ap, KERN_DEBUG, "nv_mode_filter: 0x%lx&0x%lx->0x%lx, " "BIOS=0x%lx (0x%x) ACPI=0x%lx%s\n", --- linux-mvl-dove-2.6.31.orig/drivers/ata/pata_via.c +++ linux-mvl-dove-2.6.31/drivers/ata/pata_via.c @@ -111,7 +111,7 @@ { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_SATA_PATA }, { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES }, - { "vt6415", PCI_DEVICE_ID_VIA_6415, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES }, + { "vt6415", PCI_DEVICE_ID_VIA_6415, 0x00, 0xff, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES }, { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, --- linux-mvl-dove-2.6.31.orig/drivers/ata/libata-eh.c +++ linux-mvl-dove-2.6.31/drivers/ata/libata-eh.c @@ -2541,14 +2541,14 @@ dev->pio_mode = XFER_PIO_0; dev->flags &= ~ATA_DFLAG_SLEEPING; - if (!ata_phys_link_offline(ata_dev_phys_link(dev))) { - /* apply class override */ - if (lflags & ATA_LFLAG_ASSUME_ATA) - classes[dev->devno] = ATA_DEV_ATA; - else if (lflags & ATA_LFLAG_ASSUME_SEMB) - classes[dev->devno] = ATA_DEV_SEMB_UNSUP; - } else - classes[dev->devno] = ATA_DEV_NONE; + if (ata_phys_link_offline(ata_dev_phys_link(dev))) + continue; + + /* apply class override */ + if (lflags & ATA_LFLAG_ASSUME_ATA) + classes[dev->devno] = ATA_DEV_ATA; + else if (lflags & ATA_LFLAG_ASSUME_SEMB) + classes[dev->devno] = ATA_DEV_SEMB_UNSUP; } /* record current link speed */ @@ -2581,34 +2581,48 @@ slave->eh_info.serror = 0; spin_unlock_irqrestore(link->ap->lock, flags); - /* Make sure onlineness and classification result correspond. + /* + * Make sure onlineness and classification result correspond. * Hotplug could have happened during reset and some * controllers fail to wait while a drive is spinning up after * being hotplugged causing misdetection. By cross checking - * link onlineness and classification result, those conditions - * can be reliably detected and retried. + * link on/offlineness and classification result, those + * conditions can be reliably detected and retried. */ nr_unknown = 0; ata_for_each_dev(dev, link, ALL) { - /* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */ - if (classes[dev->devno] == ATA_DEV_UNKNOWN) { - classes[dev->devno] = ATA_DEV_NONE; - if (ata_phys_link_online(ata_dev_phys_link(dev))) + if (ata_phys_link_online(ata_dev_phys_link(dev))) { + if (classes[dev->devno] == ATA_DEV_UNKNOWN) { + ata_dev_printk(dev, KERN_DEBUG, "link online " + "but device misclassifed\n"); + classes[dev->devno] = ATA_DEV_NONE; nr_unknown++; + } + } else if (ata_phys_link_offline(ata_dev_phys_link(dev))) { + if (ata_class_enabled(classes[dev->devno])) + ata_dev_printk(dev, KERN_DEBUG, "link offline, " + "clearing class %d to NONE\n", + classes[dev->devno]); + classes[dev->devno] = ATA_DEV_NONE; + } else if (classes[dev->devno] == ATA_DEV_UNKNOWN) { + ata_dev_printk(dev, KERN_DEBUG, "link status unknown, " + "clearing UNKNOWN to NONE\n"); + classes[dev->devno] = ATA_DEV_NONE; } } if (classify && nr_unknown) { if (try < max_tries) { ata_link_printk(link, KERN_WARNING, "link online but " - "device misclassified, retrying\n"); + "%d devices misclassified, retrying\n", + nr_unknown); failed_link = link; rc = -EAGAIN; goto fail; } ata_link_printk(link, KERN_WARNING, - "link online but device misclassified, " - "device detection might fail\n"); + "link online but %d devices misclassified, " + "device detection might fail\n", nr_unknown); } /* reset successful, schedule revalidation */ @@ -2835,12 +2849,14 @@ * device detection messages backwards. */ ata_for_each_dev(dev, link, ALL) { - if (!(new_mask & (1 << dev->devno)) || - dev->class == ATA_DEV_PMP) + if (!(new_mask & (1 << dev->devno))) continue; dev->class = ehc->classes[dev->devno]; + if (dev->class == ATA_DEV_PMP) + continue; + ehc->i.flags |= ATA_EHI_PRINTINFO; rc = ata_dev_configure(dev); ehc->i.flags &= ~ATA_EHI_PRINTINFO; --- linux-mvl-dove-2.6.31.orig/drivers/message/fusion/mptbase.c +++ linux-mvl-dove-2.6.31/drivers/message/fusion/mptbase.c @@ -1015,9 +1015,9 @@ { SGESimple64_t *pSge = (SGESimple64_t *) pAddr; pSge->Address.Low = cpu_to_le32 - (lower_32_bits((unsigned long)(dma_addr))); + (lower_32_bits(dma_addr)); pSge->Address.High = cpu_to_le32 - (upper_32_bits((unsigned long)dma_addr)); + (upper_32_bits(dma_addr)); pSge->FlagsLength = cpu_to_le32 ((flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING)); } @@ -1038,8 +1038,8 @@ u32 tmp; pSge->Address.Low = cpu_to_le32 - (lower_32_bits((unsigned long)(dma_addr))); - tmp = (u32)(upper_32_bits((unsigned long)dma_addr)); + (lower_32_bits(dma_addr)); + tmp = (u32)(upper_32_bits(dma_addr)); /* * 1078 errata workaround for the 36GB limitation @@ -1101,7 +1101,7 @@ pChain->NextChainOffset = next; pChain->Address.Low = cpu_to_le32(tmp); - tmp = (u32)(upper_32_bits((unsigned long)dma_addr)); + tmp = (u32)(upper_32_bits(dma_addr)); pChain->Address.High = cpu_to_le32(tmp); } @@ -3266,6 +3266,16 @@ pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus); pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo); pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices); + /* + * VMware emulation is broken, its PortFact's MaxDevices reports value + * programmed by IOC Init, so if you program IOC Init to 256 (which is 0, + * as that field is only 8 bit), it reports back 0 in port facts, instead + * of 256... And unfortunately using 256 triggers another bug in the + * code (parallel SCSI can have only 16 devices). + */ + if (pfacts->MaxDevices == 0) { + pfacts->MaxDevices = 16; + } pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID); pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags); pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers); --- linux-mvl-dove-2.6.31.orig/drivers/spi/orion_spi.c +++ linux-mvl-dove-2.6.31/drivers/spi/orion_spi.c @@ -29,12 +29,17 @@ #define ORION_SPI_DATA_OUT_REG 0x08 #define ORION_SPI_DATA_IN_REG 0x0c #define ORION_SPI_INT_CAUSE_REG 0x10 +#define ORION_SPI_INT_CAUSE_MASK_REG 0x14 +#define ORION_SPI_CLK_OPTIONAL_DIV_MASK (0x3 << 11) #define ORION_SPI_IF_8_16_BIT_MODE (1 << 5) #define ORION_SPI_CLK_PRESCALE_MASK 0x1F +#define ORION_SPI_CLK_MAX_PRESCALE 30 + struct orion_spi { struct work_struct work; + struct completion done; /* Lock access to transfer list. */ spinlock_t lock; @@ -45,6 +50,7 @@ unsigned int max_speed; unsigned int min_speed; struct orion_spi_info *spi_info; + int irq; }; static struct workqueue_struct *orion_spi_wq; @@ -105,6 +111,7 @@ tclk_hz = orion_spi->spi_info->tclk; + reg = readl(spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG)); /* * the supported rates are: 4,6,8...30 * round up as we look for equal or less speed @@ -112,8 +119,30 @@ rate = DIV_ROUND_UP(tclk_hz, speed); rate = roundup(rate, 2); + + if (orion_spi->spi_info->optional_div) + { + u32 optional_div = (rate + (ORION_SPI_CLK_MAX_PRESCALE - 1))\ + /ORION_SPI_CLK_MAX_PRESCALE; + + /* check if requested speed is too small */ + if (optional_div > 16) + return -EINVAL; + + if (optional_div > 0) + optional_div--; + + optional_div = fls(optional_div); + reg = reg & ~ORION_SPI_CLK_OPTIONAL_DIV_MASK; + reg |= optional_div << 11; + + /* recalculate rate with optional div*/ + tclk_hz = DIV_ROUND_UP(tclk_hz, (1 << optional_div)); + rate = DIV_ROUND_UP(tclk_hz, speed); + rate = roundup(rate, 2); + } /* check if requested speed is too small */ - if (rate > 30) + if (rate > ORION_SPI_CLK_MAX_PRESCALE) return -EINVAL; if (rate < 4) @@ -122,7 +151,6 @@ /* Convert the rate to SPI clock divisor value. */ prescale = 0x10 + rate/2; - reg = readl(spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG)); reg = ((reg & ~ORION_SPI_CLK_PRESCALE_MASK) | prescale); writel(reg, spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG)); @@ -165,16 +193,19 @@ static inline int orion_spi_wait_till_ready(struct orion_spi *orion_spi) { - int i; + if (orion_spi->irq < 0) { /* polling mode*/ + int i; - for (i = 0; i < ORION_SPI_WAIT_RDY_MAX_LOOP; i++) { - if (readl(spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG))) - return 1; - else - udelay(1); - } - - return -1; + for (i = 0; i < ORION_SPI_WAIT_RDY_MAX_LOOP; i++) { + if (readl(spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG))) + return 1; + else + udelay(1); + } + return -1; + } else + wait_for_completion(&orion_spi->done); + return 1; } static inline int @@ -189,8 +220,10 @@ rx_reg = spi_reg(orion_spi, ORION_SPI_DATA_IN_REG); int_reg = spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG); - /* clear the interrupt cause register */ - writel(0x0, int_reg); + if (orion_spi->irq < 0) { /* polling mode*/ + /* clear the interrupt cause register */ + writel(0x0, int_reg); + } if (tx_buf && *tx_buf) writel(*(*tx_buf)++, tx_reg); @@ -220,8 +253,10 @@ rx_reg = spi_reg(orion_spi, ORION_SPI_DATA_IN_REG); int_reg = spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG); - /* clear the interrupt cause register */ - writel(0x0, int_reg); + if (orion_spi->irq < 0) { /* polling mode*/ + /* clear the interrupt cause register */ + writel(0x0, int_reg); + } if (tx_buf && *tx_buf) writel(__cpu_to_le16(get_unaligned((*tx_buf)++)), tx_reg); @@ -248,6 +283,10 @@ orion_spi = spi_master_get_devdata(spi->master); word_len = spi->bits_per_word; + + if(xfer->bits_per_word) + word_len = xfer->bits_per_word; + count = xfer->len; if (word_len == 8) { @@ -274,6 +313,22 @@ return xfer->len - count; } +static irqreturn_t orion_spi_irq(int irq, void *dev) +{ + struct orion_spi *orion_spi = dev; + + if (!(readl(spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG)) & 0x01)) + { + printk("spi not ready for tx?\n"); + complete(&orion_spi->done); + goto irq_done; + } + + writel(0x00, spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG)); + complete(&orion_spi->done); + irq_done: + return IRQ_HANDLED; +} static void orion_spi_work(struct work_struct *work) { @@ -377,6 +432,7 @@ * baudrate & width will be set orion_spi_setup_transfer */ return 0; + } static int orion_spi_transfer(struct spi_device *spi, struct spi_message *m) @@ -480,8 +536,15 @@ spi->master = master; spi->spi_info = spi_info; + spi->max_speed = DIV_ROUND_UP(spi_info->tclk, 4); - spi->min_speed = DIV_ROUND_UP(spi_info->tclk, 30); + if (spi_info->optional_div) + /* if the controller have optional division up to 16 after + * the pre-scaler + */ + spi->min_speed = DIV_ROUND_UP(spi_info->tclk, ORION_SPI_CLK_MAX_PRESCALE * 16); + else + spi->min_speed = DIV_ROUND_UP(spi_info->tclk, ORION_SPI_CLK_MAX_PRESCALE); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (r == NULL) { @@ -504,21 +567,39 @@ if (orion_spi_reset(spi) < 0) goto out_rel_mem; + init_completion(&spi->done); + + if (spi_info->use_interrupt) { + dev_info(&pdev->dev, "use interrupt mode\n"); + spi->irq = platform_get_irq(pdev, 0); + /* clean and unmask the interrupt */ + writel(0, spi_reg(spi, ORION_SPI_INT_CAUSE_REG)); + writel(1, spi_reg(spi, ORION_SPI_INT_CAUSE_MASK_REG)); + + status = devm_request_irq(&pdev->dev, spi->irq, orion_spi_irq, + 0, pdev->name, spi); + if (status < 0) { + dev_err(&pdev->dev, "Cannot claim IRQ\n"); + writel(0, spi_reg(spi, ORION_SPI_INT_CAUSE_MASK_REG)); + goto out_rel_mem; + } + } else { + spi->irq = -1; + dev_info(&pdev->dev, "use polling mode\n"); + } status = spi_register_master(master); if (status < 0) - goto out_rel_mem; + goto out_rel_mem; return status; out_rel_mem: release_mem_region(r->start, (r->end - r->start) + 1); - out: spi_master_put(master); return status; } - static int __exit orion_spi_remove(struct platform_device *pdev) { struct spi_master *master; @@ -533,11 +614,24 @@ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(r->start, (r->end - r->start) + 1); + writel(0, spi_reg(spi, ORION_SPI_INT_CAUSE_MASK_REG)); + spi_unregister_master(master); return 0; } +static int orion_spi_resume(struct platform_device *pdev) +{ + struct spi_master *master; + struct orion_spi *spi; + + master = dev_get_drvdata(&pdev->dev); + spi = spi_master_get_devdata(master); + + return orion_spi_reset(spi); +} + MODULE_ALIAS("platform:" DRIVER_NAME); static struct platform_driver orion_spi_driver = { @@ -546,6 +640,7 @@ .owner = THIS_MODULE, }, .remove = __exit_p(orion_spi_remove), + .resume = orion_spi_resume, }; static int __init orion_spi_init(void) --- linux-mvl-dove-2.6.31.orig/drivers/spi/mv_spi.c +++ linux-mvl-dove-2.6.31/drivers/spi/mv_spi.c @@ -0,0 +1,626 @@ +/* + * mv_spi.c -- Marvell SPI controller driver + * + * Author: Saeed Bishara + * Copyright (C) 2007-2008 Marvell Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "mv_spi" + +#define MV_NUM_CHIPSELECTS 2 /* only one slave is supported*/ +#define MV_SPI_WAIT_RDY_MAX_LOOP 10000 /* in usec */ +#define MV_SPI_MAX_TRANS_SIZE 32 +#define MV_SPI_CTRL_REG 0x180 +#define MV_SPI_CTRL_START (1 << 0) /* start transfer */ +#define MV_SPI_CTRL_3W4W (1 << 1) /* 0 - 4 wire, 1 - 3 wire */ +#define MV_SPI_CTRL_SEL (1 << 2) /* SPI slave select */ +#define MV_SPI_CTRL_ENABLE (1 << 3) /* SPI enable */ +#define MV_SPI_CTRL_TX_LSB (1 << 4) /* 1 - tx from bit 0 to higher */ +#define MV_SPI_CTRL_RX_LSB (1 << 5) /* 1 - rx from bit 0 to higher */ +#define MV_SPI_CTRL_PHA (1 << 7) /* 1 - sample at falling edge */ +#define MV_SPI_CTRL_TX_BITS (0xFF << 8) /* tx bits */ +#define MV_SPI_CTRL_RX_BITS (0xFF << 16) /* rx bits */ +#define MV_SPI_CTRL_CLKDIV (0xFF << 24) /* Clock Divider */ + +#define MV_SPI_TX_DATA_REG 0x184 +#define MV_SPI_RX_DATA_REG 0x140 +#define MV_LCD_CLK_DIV_REG 0x1A8 +#define MV_LCD_CLK_DIV_MASK 0xFFFF +#define MV_LCD_INT_STATUS_REG 0x1c4 +#define MV_LCD_INT_STATUS_SPI_DONE (1 << 18) + + +struct mv_spi { + struct work_struct work; + + /* Lock access to transfer list. */ + spinlock_t lock; + + struct list_head msg_queue; + struct spi_master *master; + void __iomem *base; + unsigned int max_speed; + unsigned int min_speed; + struct mv_spi_info *spi_info; +}; + +static struct workqueue_struct *mv_spi_wq; + +static inline void __iomem *spi_reg(struct mv_spi *mv_spi, u32 reg) +{ + return mv_spi->base + reg; +} + +static inline void +mv_spi_setbits(struct mv_spi *mv_spi, u32 reg, u32 mask) +{ + void __iomem *reg_addr = spi_reg(mv_spi, reg); + u32 val; + + val = readl(reg_addr); + val |= mask; + writel(val, reg_addr); +} + +static inline void +mv_spi_clrbits(struct mv_spi *mv_spi, u32 reg, u32 mask) +{ + void __iomem *reg_addr = spi_reg(mv_spi, reg); + u32 val; + + val = readl(reg_addr); + val &= ~mask; + writel(val, reg_addr); +} + +static int mv_spi_baudrate_set(struct spi_device *spi, unsigned int speed) +{ + u32 clk_hz; + u32 rate; + u32 reg; + unsigned int lcd_clk_div; + struct mv_spi *mv_spi; + + mv_spi = spi_master_get_devdata(spi->master); + + clk_hz = mv_spi->spi_info->clk; + /* the spi clock drived from LCD fast clock/CLK_INT_DIV */ + lcd_clk_div = readl(spi_reg(mv_spi, MV_LCD_CLK_DIV_REG)); + lcd_clk_div &= MV_LCD_CLK_DIV_MASK; + clk_hz /= lcd_clk_div; + + + /* + * the supported clock div value from 2 up to 0xFF + * round up as we look for equal or less speed + */ + rate = DIV_ROUND_UP(clk_hz, speed); + + /* check if requested speed is too small */ + if (rate > 0xFF) + return -EINVAL; + + if (rate < 2) + rate = 2; + + reg = readl(spi_reg(mv_spi, MV_SPI_CTRL_REG)); + reg = ((reg & ~MV_SPI_CTRL_CLKDIV) | (rate << 24)); + writel(reg, spi_reg(mv_spi, MV_SPI_CTRL_REG)); + + return 0; +} + +/* + * called only when no transfer is active on the bus + */ +static int +mv_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) +{ + struct mv_spi *mv_spi; + unsigned int speed = spi->max_speed_hz; + unsigned int bits_per_word = spi->bits_per_word; + int rc; + + mv_spi = spi_master_get_devdata(spi->master); + + if ((t != NULL) && t->speed_hz) + speed = t->speed_hz; + + if ((t != NULL) && t->bits_per_word) + bits_per_word = t->bits_per_word; + + rc = mv_spi_baudrate_set(spi, speed); + + return rc; +} + +static void mv_spi_set_cs(struct mv_spi *mv_spi, int enable) +{ + if (enable) + mv_spi_setbits(mv_spi, MV_SPI_CTRL_REG, MV_SPI_CTRL_SEL); + else + mv_spi_clrbits(mv_spi, MV_SPI_CTRL_REG, MV_SPI_CTRL_SEL); + +} + +static inline int mv_spi_wait_till_ready(struct mv_spi *mv_spi) +{ + int i; + + for (i = 0; i < MV_SPI_WAIT_RDY_MAX_LOOP; i++) { + u32 int_status = readl(spi_reg(mv_spi, MV_LCD_INT_STATUS_REG)); + + if (int_status & MV_LCD_INT_STATUS_SPI_DONE) + return 1; + else + udelay(1); + } + + return -1; +} + +static inline int +mv_spi_write_read_8bit(struct spi_device *spi, + const u8 **tx_buf, u8 **rx_buf) +{ + void __iomem *tx_reg, *rx_reg, *int_reg; + struct mv_spi *mv_spi; + + mv_spi = spi_master_get_devdata(spi->master); + tx_reg = spi_reg(mv_spi, MV_SPI_TX_DATA_REG); + rx_reg = spi_reg(mv_spi, MV_SPI_RX_DATA_REG); + int_reg = spi_reg(mv_spi, MV_LCD_INT_STATUS_REG); + + /* clear the interrupt cause register */ + writel(~MV_LCD_INT_STATUS_SPI_DONE, int_reg); + + if (tx_buf && *tx_buf) { + writel(*(*tx_buf)++ , tx_reg); + mv_spi_setbits(mv_spi, MV_SPI_CTRL_REG, 0x7 << 8); + } + else + mv_spi_clrbits(mv_spi, MV_SPI_CTRL_REG, 0xFF << 8); + + if (rx_buf && *rx_buf) + mv_spi_setbits(mv_spi, MV_SPI_CTRL_REG, 0x7 << 16); + else + mv_spi_clrbits(mv_spi, MV_SPI_CTRL_REG, 0xFF << 16); + + mv_spi_setbits(mv_spi, MV_SPI_CTRL_REG, MV_SPI_CTRL_START); + + if (mv_spi_wait_till_ready(mv_spi) < 0) { + dev_err(&spi->dev, "TXS timed out\n"); + dev_err(&spi->dev, "SPI CTRL %x\n", + readl(spi_reg(mv_spi, MV_SPI_CTRL_REG))); + return -1; + } + mv_spi_clrbits(mv_spi, MV_SPI_CTRL_REG, MV_SPI_CTRL_START); + /* clear the interrupt cause register */ + writel(~MV_LCD_INT_STATUS_SPI_DONE, int_reg); + if (rx_buf && *rx_buf) + *(*rx_buf)++ = readl(rx_reg); + + return 1; +} +#if 0 +static inline int +mv_spi_write_read_16bit(struct spi_device *spi, + const u16 **tx_buf, u16 **rx_buf) +{ + void __iomem *tx_reg, *rx_reg, *int_reg; + struct mv_spi *mv_spi; + + mv_spi = spi_master_get_devdata(spi->master); + tx_reg = spi_reg(mv_spi, MV_SPI_TX_DATA_REG); + rx_reg = spi_reg(mv_spi, MV_SPI_RX_DATA_REG); + int_reg = spi_reg(mv_spi, MV_LCD_INT_STATUS_REG); + + + /* clear the interrupt cause register */ + writel(MV_LCD_INT_STATUS_SPI_DONE, int_reg); + + if (tx_buf && *tx_buf) { + writel(*(*tx_buf)++ , tx_reg); + mv_spi_setbits(mv_spi, MV_SPI_CTRL_REG, 0xf << 8); + } + else { + mv_spi_clrbits(mv_spi, MV_SPI_CTRL_REG, 0xFF << 8); + } + + if (rx_buf && *rx_buf) { + mv_spi_setbits(mv_spi, MV_SPI_CTRL_REG, 0xf << 16); + } + else { + mv_spi_clrbits(mv_spi, MV_SPI_CTRL_REG, 0xFF << 16); + } + + mv_spi_setbits(mv_spi, MV_SPI_CTRL_REG, MV_SPI_CTRL_START); + + if (mv_spi_wait_till_ready(mv_spi) < 0) { + dev_err(&spi->dev, "TXS timed out\n"); + dev_err(&spi->dev, "SPI CTRL %x\n", readl(spi_reg(mv_spi, MV_SPI_CTRL_REG)) ); + return -1; + } + mv_spi_clrbits(mv_spi, MV_SPI_CTRL_REG, MV_SPI_CTRL_START); + if (rx_buf && *rx_buf) { + u16 data = readl(rx_reg); + + mdelay(10); + *(*rx_buf)++ = be16_to_cpu(data); + } + + return 1; +} +#endif +static unsigned int +mv_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) +{ + struct mv_spi *mv_spi; + unsigned int count; + int word_len; + + mv_spi = spi_master_get_devdata(spi->master); + word_len = spi->bits_per_word; + count = xfer->len; + + if(xfer->bits_per_word) + word_len = xfer->bits_per_word; + + if (word_len == 8) { + const u8 *tx = xfer->tx_buf; + u8 *rx = xfer->rx_buf; + + do { + if (mv_spi_write_read_8bit(spi, &tx, &rx) < 0) + goto out; + count--; + } while (count); + } +#if 0 + else if (word_len == 16) { + const u16 *tx = xfer->tx_buf; + u16 *rx = xfer->rx_buf; + + do { + if (mv_spi_write_read_16bit(spi, &tx, &rx) < 0) + goto out; + count -= 2; + } while (count); + } +#endif +out: + return xfer->len - count; +} + + +static void mv_spi_work(struct work_struct *work) +{ + struct mv_spi *mv_spi = + container_of(work, struct mv_spi, work); + + spin_lock_irq(&mv_spi->lock); + while (!list_empty(&mv_spi->msg_queue)) { + struct spi_message *m; + struct spi_device *spi; + struct spi_transfer *t = NULL; + int par_override = 0; + int status = 0; + int cs_active = 0; + + m = container_of(mv_spi->msg_queue.next, struct spi_message, + queue); + + list_del_init(&m->queue); + spin_unlock_irq(&mv_spi->lock); + + spi = m->spi; + + /* Load defaults */ + status = mv_spi_setup_transfer(spi, NULL); + + if (status < 0) + goto msg_done; + + list_for_each_entry(t, &m->transfers, transfer_list) { + if (par_override || t->speed_hz || t->bits_per_word) { + par_override = 1; + status = mv_spi_setup_transfer(spi, t); + if (status < 0) + break; + if (!t->speed_hz && !t->bits_per_word) + par_override = 0; + } + + if (!cs_active) { + mv_spi_set_cs(mv_spi, 0); + cs_active = 1; + } + + if (t->len) + m->actual_length += + mv_spi_write_read(spi, t); + + if (t->delay_usecs) + udelay(t->delay_usecs); + + if (t->cs_change) { + mv_spi_set_cs(mv_spi, 0); + cs_active = 0; + } + } + +msg_done: + if (cs_active) + mv_spi_set_cs(mv_spi, 0); + + m->status = status; + m->complete(m->context); + + spin_lock_irq(&mv_spi->lock); + } + + spin_unlock_irq(&mv_spi->lock); +} + +static int __devinit mv_spi_reset(struct mv_spi *mv_spi) +{ + /* Verify that the CS is deasserted */ + mv_spi_set_cs(mv_spi, 0); + + return 0; +} + +static int mv_spi_setup(struct spi_device *spi) +{ + struct mv_spi *mv_spi; + + mv_spi = spi_master_get_devdata(spi->master); + + if (spi->mode) { + dev_err(&spi->dev, "setup: unsupported mode bits %x\n", + spi->mode); + return -EINVAL; + } + + if (spi->bits_per_word == 0) + spi->bits_per_word = 8; + + if ((spi->max_speed_hz == 0) + || (spi->max_speed_hz > mv_spi->max_speed)) + spi->max_speed_hz = mv_spi->max_speed; + + if (spi->max_speed_hz < mv_spi->min_speed) { + dev_err(&spi->dev, "setup: requested speed too low %d Hz " + "(min speed %d Hz)\n", spi->max_speed_hz, + mv_spi->min_speed); + return -EINVAL; + } + + /* + * baudrate & width will be set mv_spi_setup_transfer + */ + return 0; +} + +static int mv_spi_transfer(struct spi_device *spi, struct spi_message *m) +{ + struct mv_spi *mv_spi; + struct spi_transfer *t = NULL; + unsigned long flags; + + m->actual_length = 0; + m->status = 0; + + /* reject invalid messages and transfers */ + if (list_empty(&m->transfers) || !m->complete) + return -EINVAL; + + mv_spi = spi_master_get_devdata(spi->master); + + list_for_each_entry(t, &m->transfers, transfer_list) { + unsigned int bits_per_word = spi->bits_per_word; + + if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { + dev_err(&spi->dev, + "message rejected : " + "invalid transfer data buffers\n"); + goto msg_rejected; + } + + if ((t != NULL) && t->bits_per_word) + bits_per_word = t->bits_per_word; + + if ((bits_per_word != 8) /*&& (bits_per_word != 16)*/) { + dev_err(&spi->dev, + "message rejected : " + "invalid transfer bits_per_word (%d bits)\n", + bits_per_word); + goto msg_rejected; + } + + if (t->speed_hz && t->speed_hz < mv_spi->min_speed) { + dev_err(&spi->dev, + "message rejected : " + "device min speed (%d Hz) exceeds " + "required transfer speed (%d Hz)\n", + mv_spi->min_speed, t->speed_hz); + goto msg_rejected; + } + } + + + spin_lock_irqsave(&mv_spi->lock, flags); + list_add_tail(&m->queue, &mv_spi->msg_queue); + queue_work(mv_spi_wq, &mv_spi->work); + spin_unlock_irqrestore(&mv_spi->lock, flags); + + return 0; +msg_rejected: + /* Message rejected and not queued */ + m->status = -EINVAL; + if (m->complete) + m->complete(m->context); + return -EINVAL; +} + +int __devinit mv_spi_probe(struct platform_device *pdev) +{ + struct spi_master *master; + struct mv_spi *spi; + struct resource *r; + struct mv_spi_info *spi_info; + int status = 0; + unsigned int lcd_clk_div; + + spi_info = pdev->dev.platform_data; + + master = spi_alloc_master(&pdev->dev, sizeof *spi); + if (master == NULL) { + dev_dbg(&pdev->dev, "master allocation failed\n"); + return -ENOMEM; + } + + if (pdev->id != -1) + master->bus_num = pdev->id; + + master->setup = mv_spi_setup; + master->transfer = mv_spi_transfer; + master->num_chipselect = MV_NUM_CHIPSELECTS; + + dev_set_drvdata(&pdev->dev, master); + + spi = spi_master_get_devdata(master); + spi->master = master; + spi->spi_info = spi_info; + + if (spi_info->clk == 0) { + pr_debug("mv_spi: Bad Clk value.\n"); + status = -EINVAL; + goto out; + } +#if 0 + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (r == NULL) { + status = -ENODEV; + goto out; + } +#endif +#if 0 + if (!request_mem_region(r->start, (r->end - r->start) + 1, + pdev->dev.bus_id)) { + status = -EBUSY; + printk("request_mem_region failed\n"); + goto out; + } +#endif + spi->base = ioremap(0xf1820000, SZ_1K); + printk("ioremap: %p\n", spi->base); + if(spi->base == 0){ + status = -EBUSY; + printk("ioremap failed\n"); + goto out; + } + lcd_clk_div = readl(spi_reg(spi, MV_LCD_CLK_DIV_REG)); + lcd_clk_div &= MV_LCD_CLK_DIV_MASK; + + if (lcd_clk_div == 0){ + status = -EBUSY; + printk("lcd clk div not set. check if lcd driver loaded \n"); + goto out; + + } + spi->max_speed = DIV_ROUND_UP(spi_info->clk/lcd_clk_div, 2); + spi->min_speed = DIV_ROUND_UP(spi_info->clk/lcd_clk_div, 0xFF); + + INIT_WORK(&spi->work, mv_spi_work); + + spin_lock_init(&spi->lock); + INIT_LIST_HEAD(&spi->msg_queue); + + if (mv_spi_reset(spi) < 0) + goto out_rel_mem; + + writel(MV_SPI_CTRL_ENABLE | /*MV_SPI_CTRL_PHA |*/ 0xFF << 24, + spi_reg(spi, MV_SPI_CTRL_REG)); + + status = spi_register_master(master); + if (status < 0) + goto out_rel_mem; + + return status; + +out_rel_mem: + printk("error while loading mv_spi driver \n"); +// release_mem_region(r->start, (r->end - r->start) + 1); + +out: + spi_master_put(master); + return status; +} + + +static int __exit mv_spi_remove(struct platform_device *pdev) +{ + struct spi_master *master; + struct mv_spi *spi; + struct resource *r; + + master = dev_get_drvdata(&pdev->dev); + spi = spi_master_get_devdata(master); + + cancel_work_sync(&spi->work); + +// r = platform_get_resource(pdev, IORESOURCE_MEM, 0); +// release_mem_region(r->start, (r->end - r->start) + 1); + + spi_unregister_master(master); + + return 0; +} + +MODULE_ALIAS("platform:" DRIVER_NAME); + +struct platform_driver mv_spi_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, + .remove = __exit_p(mv_spi_remove), +}; + +int __devinit mv_spi_init(void) +{ + mv_spi_wq = create_singlethread_workqueue( + mv_spi_driver.driver.name); + if (mv_spi_wq == NULL) + return -ENOMEM; + + return platform_driver_probe(&mv_spi_driver, mv_spi_probe); +} +//module_init(mv_spi_init); + +void __exit mv_spi_exit(void) +{ + flush_workqueue(mv_spi_wq); + platform_driver_unregister(&mv_spi_driver); + + destroy_workqueue(mv_spi_wq); +} +//module_exit(mv_spi_exit); + +MODULE_DESCRIPTION("Marvell SPI driver"); +MODULE_AUTHOR("Saeed Bishara "); +MODULE_LICENSE("GPL"); --- linux-mvl-dove-2.6.31.orig/drivers/spi/Kconfig +++ linux-mvl-dove-2.6.31/drivers/spi/Kconfig @@ -178,6 +178,12 @@ controller. If you have an embedded system with an AMBA(R) bus and a PL022 controller, say Y or M here. +config SPI_MV + tristate "Marvell SPI master (EXPERIMENTAL)" + depends on PLAT_ORION && EXPERIMENTAL + help + This enables using the SPI master controller on the Marvell chips. + config SPI_PXA2XX tristate "PXA2xx SSP SPI master" depends on ARCH_PXA && EXPERIMENTAL --- linux-mvl-dove-2.6.31.orig/drivers/spi/Makefile +++ linux-mvl-dove-2.6.31/drivers/spi/Makefile @@ -19,6 +19,8 @@ obj-$(CONFIG_SPI_GPIO) += spi_gpio.o obj-$(CONFIG_SPI_IMX) += spi_imx.o obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o +obj-$(CONFIG_SPI_ORION) += orion_spi.o +obj-$(CONFIG_SPI_MV) += mv_spi.o obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o --- linux-mvl-dove-2.6.31.orig/drivers/media/common/tuners/tda18271-fe.c +++ linux-mvl-dove-2.6.31/drivers/media/common/tuners/tda18271-fe.c @@ -595,13 +595,13 @@ case RF2: map[i].rf_a1 = (prog_cal[RF2] - prog_tab[RF2] - prog_cal[RF1] + prog_tab[RF1]) / - ((rf_freq[RF2] - rf_freq[RF1]) / 1000); + (s32)((rf_freq[RF2] - rf_freq[RF1]) / 1000); map[i].rf2 = rf_freq[RF2] / 1000; break; case RF3: map[i].rf_a2 = (prog_cal[RF3] - prog_tab[RF3] - prog_cal[RF2] + prog_tab[RF2]) / - ((rf_freq[RF3] - rf_freq[RF2]) / 1000); + (s32)((rf_freq[RF3] - rf_freq[RF2]) / 1000); map[i].rf_b2 = prog_cal[RF2] - prog_tab[RF2]; map[i].rf3 = rf_freq[RF3] / 1000; break; @@ -963,12 +963,12 @@ struct tda18271_std_map_item *map; char *mode; int ret; - u32 freq = params->frequency * 62500; + u32 freq = params->frequency * 125 * + ((params->mode == V4L2_TUNER_RADIO) ? 1 : 1000) / 2; priv->mode = TDA18271_ANALOG; if (params->mode == V4L2_TUNER_RADIO) { - freq = freq / 1000; map = &std_map->fm_radio; mode = "fm"; } else if (params->std & V4L2_STD_MN) { --- linux-mvl-dove-2.6.31.orig/drivers/media/common/tuners/mxl5007t.c +++ linux-mvl-dove-2.6.31/drivers/media/common/tuners/mxl5007t.c @@ -196,7 +196,7 @@ i = j = 0; while (reg_pair1[i].reg || reg_pair1[i].val) { - while (reg_pair2[j].reg || reg_pair2[j].reg) { + while (reg_pair2[j].reg || reg_pair2[j].val) { if (reg_pair1[i].reg != reg_pair2[j].reg) { j++; continue; --- linux-mvl-dove-2.6.31.orig/drivers/media/video/s2255drv.c +++ linux-mvl-dove-2.6.31/drivers/media/video/s2255drv.c @@ -598,11 +598,6 @@ buf = list_entry(dma_q->active.next, struct s2255_buffer, vb.queue); - if (!waitqueue_active(&buf->vb.done)) { - /* no one active */ - rc = -1; - goto unlock; - } list_del(&buf->vb.queue); do_gettimeofday(&buf->vb.ts); dprintk(100, "[%p/%d] wakeup\n", buf, buf->vb.i); --- linux-mvl-dove-2.6.31.orig/drivers/media/video/cafe_ccic.c +++ linux-mvl-dove-2.6.31/drivers/media/video/cafe_ccic.c @@ -20,7 +20,7 @@ * This file may be distributed under the terms of the GNU General * Public License, version 2. */ - +#define DEBUG #include #include #include @@ -30,11 +30,14 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #include #include #include @@ -42,19 +45,21 @@ #include #include +#include #include #include #include "cafe_ccic-regs.h" -#define CAFE_VERSION 0x000002 +#define DRV_NAME "cafe1000-ccic" +#define CAFE_VERSION 0x000004 /* * Parameters. */ MODULE_AUTHOR("Jonathan Corbet "); -MODULE_DESCRIPTION("Marvell 88ALP01 CMOS Camera Controller driver"); +MODULE_DESCRIPTION("Marvell Cafe CMOS Camera Controller driver"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("Video"); @@ -151,6 +156,7 @@ * Subsystem structures. */ struct pci_dev *pdev; + struct device *dev; struct video_device vdev; struct i2c_adapter i2c_adapter; struct v4l2_subdev *sensor; @@ -187,6 +193,16 @@ /* Misc */ wait_queue_head_t smbus_wait; /* Waiting on i2c events */ wait_queue_head_t iowait; /* Waiting on frame data */ + +#if defined(CONFIG_HAVE_CLK) + struct clk *clk; +#endif + unsigned int powered_on; + /* Board info */ + u32 power_down; /* value to set into GPR to power down the sensor*/ + u32 reset; /* value to set into GPR to reset the senser */ + int numbered_i2c_bus; + unsigned int i2c_bus_id; }; /* @@ -240,11 +256,13 @@ * Debugging and related. */ #define cam_err(cam, fmt, arg...) \ - dev_err(&(cam)->pdev->dev, fmt, ##arg); + dev_err((cam)->dev, fmt, ##arg); #define cam_warn(cam, fmt, arg...) \ - dev_warn(&(cam)->pdev->dev, fmt, ##arg); + dev_warn((cam)->dev, fmt, ##arg); +#define cam_notice(cam, fmt, arg...) \ + dev_notice((cam)->dev, fmt, ##arg); #define cam_dbg(cam, fmt, arg...) \ - dev_dbg(&(cam)->pdev->dev, fmt, ##arg); + dev_dbg((cam)->dev, fmt, ##arg); /* ---------------------------------------------------------------------*/ @@ -287,7 +305,8 @@ } - +static void cafe_ctlr_power_up(struct cafe_camera *cam); +static void cafe_ctlr_power_down(struct cafe_camera *cam); /* -------------------------------------------------------------------- */ /* * The I2C/SMBUS interface to the camera itself starts here. The @@ -318,6 +337,7 @@ { unsigned int rval; unsigned long flags; + int max_count = HZ; DEFINE_WAIT(the_wait); spin_lock_irqsave(&cam->dev_lock, flags); @@ -326,7 +346,9 @@ /* * Marvell sez set clkdiv to all 1's for now. */ + rval |= TWSIC0_CLKDIV; + cafe_reg_write(cam, REG_TWSIC0, rval); (void) cafe_reg_read(cam, REG_TWSIC1); /* force write */ rval = value | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR); @@ -349,6 +371,13 @@ TASK_UNINTERRUPTIBLE); schedule_timeout(1); /* even 1 jiffy is too long */ finish_wait(&cam->smbus_wait, &the_wait); +#if 1 + if(max_count-- <= 0) { + cam_err(cam, "SMBUS write (%02x/%02x/%02x) timed out\n", addr, + command, value); + return -EIO; + } +#endif } while (!cafe_smbus_write_done(cam)); #ifdef IF_THE_CAFE_HARDWARE_WORKED_RIGHT @@ -406,6 +435,7 @@ * Marvel sez set clkdiv to all 1's for now. */ rval |= TWSIC0_CLKDIV; + cafe_reg_write(cam, REG_TWSIC0, rval); (void) cafe_reg_read(cam, REG_TWSIC1); /* force write */ rval = TWSIC1_READ | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR); @@ -442,6 +472,7 @@ struct v4l2_device *v4l2_dev = i2c_get_adapdata(adapter); struct cafe_camera *cam = to_cam(v4l2_dev); int ret = -EINVAL; + int power_off = 0; /* * This interface would appear to only do byte data ops. OK @@ -451,11 +482,19 @@ cam_err(cam, "funky xfer size %d\n", size); return -EINVAL; } + if (cam->powered_on == 0) { + cafe_ctlr_power_up(cam); + power_off = 1; + } if (rw == I2C_SMBUS_WRITE) ret = cafe_smbus_write_data(cam, addr, command, data->byte); else if (rw == I2C_SMBUS_READ) ret = cafe_smbus_read_data(cam, addr, command, &data->byte); + + if (power_off) + cafe_ctlr_power_down(cam); + return ret; } @@ -494,9 +533,15 @@ adap->owner = THIS_MODULE; adap->algo = &cafe_smbus_algo; strcpy(adap->name, "cafe_ccic"); - adap->dev.parent = &cam->pdev->dev; + adap->dev.parent = cam->dev; i2c_set_adapdata(adap, &cam->v4l2_dev); - ret = i2c_add_adapter(adap); + + if(cam->numbered_i2c_bus == 0) + ret = i2c_add_adapter(adap); + else { + adap->nr = cam->i2c_bus_id; + ret = i2c_add_numbered_adapter(adap); + } if (ret) printk(KERN_ERR "Unable to register cafe i2c adapter\n"); return ret; @@ -533,7 +578,9 @@ } else cafe_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS); - cafe_reg_write(cam, REG_UBAR, 0); /* 32 bits only for now */ + + if(cam->pdev) + cafe_reg_write(cam, REG_UBAR, 0); /* 32 bits only for now */ } static void cafe_ctlr_image(struct cafe_camera *cam) @@ -638,26 +685,31 @@ /* * Added magic to bring up the hardware on the B-Test board */ - cafe_reg_write(cam, 0x3038, 0x8); - cafe_reg_write(cam, 0x315c, 0x80008); - /* - * Go through the dance needed to wake the device up. - * Note that these registers are global and shared - * with the NAND and SD devices. Interaction between the - * three still needs to be examined. - */ - cafe_reg_write(cam, REG_GL_CSR, GCSR_SRS|GCSR_MRS); /* Needed? */ - cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRC); - cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRS); - /* - * Here we must wait a bit for the controller to come around. - */ - spin_unlock_irqrestore(&cam->dev_lock, flags); - msleep(5); - spin_lock_irqsave(&cam->dev_lock, flags); - cafe_reg_write(cam, REG_GL_CSR, GCSR_CCIC_EN|GCSR_SRC|GCSR_MRC); - cafe_reg_set_bit(cam, REG_GL_IMASK, GIMSK_CCIC_EN); + if(cam->pdev){ + cafe_reg_write(cam, 0x3038, 0x8); + cafe_reg_write(cam, 0x315c, 0x80008); + + /* + * Go through the dance needed to wake the device up. + * Note that these registers are global and shared + * with the NAND and SD devices. Interaction between the + * three still needs to be examined. + */ + cafe_reg_write(cam, REG_GL_CSR, GCSR_SRS|GCSR_MRS); /* Needed?*/ + cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRC); + cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRS); + /* + * Here we must wait a bit for the controller to come around. + */ + spin_unlock_irqrestore(&cam->dev_lock, flags); + msleep(5); + spin_lock_irqsave(&cam->dev_lock, flags); + + cafe_reg_write(cam, REG_GL_CSR, GCSR_CCIC_EN|GCSR_SRC|GCSR_MRC); + cafe_reg_set_bit(cam, REG_GL_IMASK, GIMSK_CCIC_EN); + } + /* * Make sure it's not powered down. */ @@ -675,7 +727,14 @@ * Clock the sensor appropriately. Controller clock should * be 48MHz, sensor "typical" value is half that. */ - cafe_reg_write_mask(cam, REG_CLKCTRL, 2, CLK_DIV_MASK); + if(cam->pdev) + cafe_reg_write_mask(cam, REG_CLKCTRL, 2, CLK_DIV_MASK); + else + /* core clock is 50, set div to 2 to have 25 MHz and + * the sensor will use its own PLL to get 12.5MHz + */ + cafe_reg_write_mask(cam, REG_CLKCTRL, 2, CLK_DIV_MASK); + spin_unlock_irqrestore(&cam->dev_lock, flags); } @@ -721,8 +780,10 @@ * Part one of the sensor dance: turn the global * GPIO signal on. */ - cafe_reg_write(cam, REG_GL_FCR, GFCR_GPIO_ON); - cafe_reg_write(cam, REG_GL_GPIOR, GGPIO_OUT|GGPIO_VAL); + if(cam->pdev){ + cafe_reg_write(cam, REG_GL_FCR, GFCR_GPIO_ON); + cafe_reg_write(cam, REG_GL_GPIOR, GGPIO_OUT|GGPIO_VAL); + } /* * Put the sensor into operational mode (assumes OLPC-style * wiring). Control 0 is reset - set to 1 to operate. @@ -730,8 +791,9 @@ */ cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */ /* mdelay(1); */ /* Marvell says 1ms will do it */ - cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0); + cafe_reg_write(cam, REG_GPR, GPR_C1EN | GPR_C0EN | cam->reset); /* mdelay(1); */ /* Enough? */ + cam->powered_on = 1; spin_unlock_irqrestore(&cam->dev_lock, flags); msleep(5); /* Just to be sure */ } @@ -741,10 +803,14 @@ unsigned long flags; spin_lock_irqsave(&cam->dev_lock, flags); - cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C1); - cafe_reg_write(cam, REG_GL_FCR, GFCR_GPIO_ON); - cafe_reg_write(cam, REG_GL_GPIOR, GGPIO_OUT); + + cafe_reg_write(cam, REG_GPR, GPR_C1EN | GPR_C0EN | cam->power_down); + if(cam->pdev){ + cafe_reg_write(cam, REG_GL_FCR, GFCR_GPIO_ON); + cafe_reg_write(cam, REG_GL_GPIOR, GGPIO_OUT); + } cafe_reg_set_bit(cam, REG_CTRL1, C1_PWRDWN); + cam->powered_on = 0; spin_unlock_irqrestore(&cam->dev_lock, flags); } @@ -781,7 +847,8 @@ if (ret) goto out; cam->sensor_type = chip.ident; - if (cam->sensor_type != V4L2_IDENT_OV7670) { + if ((cam->sensor_type != V4L2_IDENT_OV7670) && + (cam->sensor_type != V4L2_IDENT_OV7680)) { cam_err(cam, "Unsupported sensor type 0x%x", cam->sensor_type); ret = -EINVAL; goto out; @@ -851,7 +918,7 @@ cam->nbufs = 0; for (i = 0; i < n_dma_bufs; i++) { - cam->dma_bufs[i] = dma_alloc_coherent(&cam->pdev->dev, + cam->dma_bufs[i] = dma_alloc_coherent(cam->dev, cam->dma_buf_size, cam->dma_handles + i, GFP_KERNEL); if (cam->dma_bufs[i] == NULL) { @@ -865,7 +932,7 @@ switch (cam->nbufs) { case 1: - dma_free_coherent(&cam->pdev->dev, cam->dma_buf_size, + dma_free_coherent(cam->dev, cam->dma_buf_size, cam->dma_bufs[0], cam->dma_handles[0]); cam->nbufs = 0; case 0: @@ -885,7 +952,7 @@ int i; for (i = 0; i < cam->nbufs; i++) { - dma_free_coherent(&cam->pdev->dev, cam->dma_buf_size, + dma_free_coherent(cam->dev, cam->dma_buf_size, cam->dma_bufs[i], cam->dma_handles[i]); cam->dma_bufs[i] = NULL; } @@ -1376,7 +1443,7 @@ filp->private_data = cam; - mutex_lock(&cam->s_mutex); +// mutex_lock(&cam->s_mutex); if (cam->users == 0) { cafe_ctlr_power_up(cam); __cafe_cam_reset(cam); @@ -1384,7 +1451,7 @@ /* FIXME make sure this is complete */ } (cam->users)++; - mutex_unlock(&cam->s_mutex); +// mutex_unlock(&cam->s_mutex); return 0; } @@ -1887,12 +1954,8 @@ /* -------------------------------------------------------------------------- */ -/* - * PCI interface stuff. - */ -static int cafe_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) +static struct cafe_camera *alloc_init_cam_struct(struct device *dev) { int ret; struct cafe_camera *cam; @@ -1904,7 +1967,7 @@ cam = kzalloc(sizeof(struct cafe_camera), GFP_KERNEL); if (cam == NULL) goto out; - ret = v4l2_device_register(&pdev->dev, &cam->v4l2_dev); + ret = v4l2_device_register(dev, &cam->v4l2_dev); if (ret) goto out_free; @@ -1915,29 +1978,24 @@ cafe_set_config_needed(cam, 1); init_waitqueue_head(&cam->smbus_wait); init_waitqueue_head(&cam->iowait); - cam->pdev = pdev; + cam->dev = dev; cam->pix_format = cafe_def_pix_format; INIT_LIST_HEAD(&cam->dev_list); INIT_LIST_HEAD(&cam->sb_avail); INIT_LIST_HEAD(&cam->sb_full); tasklet_init(&cam->s_tasklet, cafe_frame_tasklet, (unsigned long) cam); - /* - * Get set up on the PCI bus. - */ - ret = pci_enable_device(pdev); - if (ret) - goto out_unreg; - pci_set_master(pdev); - ret = -EIO; - cam->regs = pci_iomap(pdev, 0, 0); - if (! cam->regs) { - printk(KERN_ERR "Unable to ioremap cafe-ccic regs\n"); - goto out_unreg; - } - ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam); - if (ret) - goto out_iounmap; + return cam; +out_free: + kfree(cam); +out: + return NULL; +} + +static int cafe_init_cam(struct cafe_camera *cam) +{ + int ret; + /* * Initialize the controller and leave it powered up. It will * stay that way until the sensor driver shows up. @@ -1952,14 +2010,19 @@ mutex_unlock(&cam->s_mutex); /* attach can deadlock */ ret = cafe_smbus_setup(cam); if (ret) - goto out_freeirq; + goto out; - cam->sensor_addr = 0x42; + cam->sensor_addr = 0x21; cam->sensor = v4l2_i2c_new_subdev(&cam->v4l2_dev, &cam->i2c_adapter, "ov7670", "ov7670", cam->sensor_addr); if (cam->sensor == NULL) { - ret = -ENODEV; - goto out_smbus; + cam->sensor = v4l2_i2c_new_subdev(&cam->v4l2_dev, + &cam->i2c_adapter, "ov7680", "ov7680", + cam->sensor_addr); + if (cam->sensor == NULL) { + ret = -ENODEV; + goto out_smbus; + } } ret = cafe_cam_init(cam); if (ret) @@ -1992,20 +2055,11 @@ out_smbus: cafe_smbus_shutdown(cam); -out_freeirq: - cafe_ctlr_power_down(cam); - free_irq(pdev->irq, cam); -out_iounmap: - pci_iounmap(pdev, cam->regs); -out_free: - v4l2_device_unregister(&cam->v4l2_dev); -out_unreg: - kfree(cam); out: + cafe_ctlr_power_down(cam); return ret; } - /* * Shut down an initialized device */ @@ -2019,21 +2073,12 @@ cafe_ctlr_power_down(cam); cafe_smbus_shutdown(cam); cafe_free_dma_bufs(cam); - free_irq(cam->pdev->irq, cam); - pci_iounmap(cam->pdev, cam->regs); video_unregister_device(&cam->vdev); } -static void cafe_pci_remove(struct pci_dev *pdev) +static void cam_remove(struct cafe_camera *cam) { - struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); - struct cafe_camera *cam = to_cam(v4l2_dev); - - if (cam == NULL) { - printk(KERN_WARNING "pci_remove on unknown pdev %p\n", pdev); - return; - } mutex_lock(&cam->s_mutex); if (cam->users > 0) cam_warn(cam, "Removing a device with users!\n"); @@ -2043,11 +2088,199 @@ /* No unlock - it no longer exists */ } +static int cafe_platform_probe(struct platform_device *pdev) +{ + struct resource *res; + int irq; + int ret; + struct cafe_camera *cam; + + /* + * Start putting together one of our big camera structures. + */ + ret = -ENOMEM; + cam = alloc_init_cam_struct(&pdev->dev); + if (cam == NULL) + return ret; + + platform_set_drvdata(pdev, cam); + /* we are not pci device */ + cam->pdev = NULL; + /* + * Get set up on the PCI bus. + */ + ret = -EIO; + /* + * Get the register base first + */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) + return -EINVAL; + + cam->regs = devm_ioremap(&pdev->dev, res->start, + res->end - res->start + 1); + if (! cam->regs) { + dev_err(&pdev->dev, "Unable to ioremap cafe-ccic regs\n"); + return ret; + } + + irq = platform_get_irq(pdev, 0); + if (res < 0) { + dev_err(&pdev->dev, "no IRQ resource defined\n"); + return -ENODEV; + } + + ret = devm_request_irq(&pdev->dev, irq, cafe_irq, 0, + "cafe-ccic", cam); + if (ret) + return ret; + + if (pdev->dev.platform_data) { + const struct cafe_cam_platform_data *platform_data = + (struct cafe_cam_platform_data *)pdev->dev.platform_data; + cam->power_down = platform_data->power_down; + cam->reset = platform_data->reset; + cam->numbered_i2c_bus = platform_data->numbered_i2c_bus; + cam->i2c_bus_id = platform_data->i2c_bus_id; + } else { + cam->power_down = GPR_C1; + cam->reset = GPR_C0; + cam->numbered_i2c_bus = 0; + } +#if defined(CONFIG_HAVE_CLK) + cam->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(cam->clk)) + dev_notice(&pdev->dev, "cannot get clkdev\n"); + else + clk_enable(cam->clk); +#endif + + return cafe_init_cam(cam); +} + +static int cafe_platform_remove(struct platform_device *pdev) +{ + struct cafe_camera *cam = platform_get_drvdata(pdev); +#if defined(CONFIG_HAVE_CLK) + struct clk *clk = cam->clk; +#endif + + cam_remove(cam); + +#if defined(CONFIG_HAVE_CLK) + if (!IS_ERR(clk)) { + clk_disable(clk); + clk_put(clk); + } +#endif + + return 0; +} + +/* ------------------------------------------------------------------------*/ +/* + * PCI interface stuff. + */ + +static int cafe_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + int ret; + struct cafe_camera *cam; + + /* + * Start putting together one of our big camera structures. + */ + ret = -ENOMEM; + cam = alloc_init_cam_struct(&pdev->dev); + if (cam == NULL) + return ret; + + pci_set_drvdata(pdev, cam); + cam->pdev = pdev; + /* + * Get set up on the PCI bus. + */ + ret = pci_enable_device(pdev); + if (ret) + return ret; + + pci_set_master(pdev); + + ret = -EIO; + cam->regs = pcim_iomap(pdev, 0, 0); + if (! cam->regs) { + printk(KERN_ERR "Unable to ioremap cafe-ccic regs\n"); + return ret; + } + ret = devm_request_irq(&pdev->dev, pdev->irq, cafe_irq, IRQF_SHARED, + "cafe-ccic", cam); + if (ret) + return ret; + +/* + * OLPC-style wiring. Control 0 is reset. + * Control 1 is power down. + */ + cam->power_down = GPR_C1; + cam->reset = GPR_C0; + cam->numbered_i2c_bus = 0; + return cafe_init_cam(cam); +} + +static void cafe_pci_remove(struct pci_dev *pdev) +{ + struct cafe_camera *cam = pci_get_drvdata(pdev); + + cam_remove(cam); +} + #ifdef CONFIG_PM /* * Basic power management. */ +static int cafe_resume(struct cafe_camera *cam) +{ + int ret = 0; + + cafe_ctlr_init(cam); + cafe_ctlr_power_down(cam); + + mutex_lock(&cam->s_mutex); + if (cam->users > 0) { + cafe_ctlr_power_up(cam); + __cafe_cam_reset(cam); + } + mutex_unlock(&cam->s_mutex); + + set_bit(CF_CONFIG_NEEDED, &cam->flags); + if (cam->state == S_SPECREAD) + cam->state = S_IDLE; /* Don't bother restarting */ + else if (cam->state == S_SINGLEREAD || cam->state == S_STREAMING) + ret = cafe_read_setup(cam, cam->state); + return ret; +} + +static int cafe_platform_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct cafe_camera *cam = platform_get_drvdata(pdev); + enum cafe_state cstate; + + cstate = cam->state; /* HACK - stop_dma sets to idle */ + cafe_ctlr_stop_dma(cam); + cafe_ctlr_power_down(cam); + cam->state = cstate; + return 0; +} + +static int cafe_platform_resume(struct platform_device *pdev) +{ + struct cafe_camera *cam = platform_get_drvdata(pdev); + + return cafe_resume(cam); +} + static int cafe_pci_suspend(struct pci_dev *pdev, pm_message_t state) { struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); @@ -2082,21 +2315,8 @@ cam_warn(cam, "Unable to re-enable device on resume!\n"); return ret; } - cafe_ctlr_init(cam); - cafe_ctlr_power_down(cam); - - mutex_lock(&cam->s_mutex); - if (cam->users > 0) { - cafe_ctlr_power_up(cam); - __cafe_cam_reset(cam); - } - mutex_unlock(&cam->s_mutex); - set_bit(CF_CONFIG_NEEDED, &cam->flags); - if (cam->state == S_SPECREAD) - cam->state = S_IDLE; /* Don't bother restarting */ - else if (cam->state == S_SINGLEREAD || cam->state == S_STREAMING) - ret = cafe_read_setup(cam, cam->state); + ret = cafe_resume(cam); return ret; } @@ -2112,7 +2332,7 @@ MODULE_DEVICE_TABLE(pci, cafe_ids); static struct pci_driver cafe_pci_driver = { - .name = "cafe1000-ccic", + .name = DRV_NAME, .id_table = cafe_ids, .probe = cafe_pci_probe, .remove = cafe_pci_remove, @@ -2122,6 +2342,18 @@ #endif }; +static struct platform_driver cafe_platform_driver = { + .probe = cafe_platform_probe, + .remove = cafe_platform_remove, + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, +#ifdef CONFIG_PM + .suspend = cafe_platform_suspend, + .resume = cafe_platform_resume, +#endif +}; @@ -2132,13 +2364,17 @@ printk(KERN_NOTICE "Marvell M88ALP01 'CAFE' Camera Controller version %d\n", CAFE_VERSION); ret = pci_register_driver(&cafe_pci_driver); - if (ret) { - printk(KERN_ERR "Unable to register cafe_ccic driver\n"); - goto out; + if (ret < 0) { + printk(KERN_ERR "Unable to register pci cafe_ccic driver\n"); + return ret; + } + ret = platform_driver_register(&cafe_platform_driver); + if (ret < 0) { + printk(KERN_ERR "Unable to register platform cafe_ccic driver\n"); + pci_unregister_driver(&cafe_pci_driver); + return ret; } - ret = 0; - out: return ret; } @@ -2146,6 +2382,7 @@ static void __exit cafe_exit(void) { pci_unregister_driver(&cafe_pci_driver); + platform_driver_unregister(&cafe_platform_driver); } module_init(cafe_init); --- linux-mvl-dove-2.6.31.orig/drivers/media/video/ov7680.c +++ linux-mvl-dove-2.6.31/drivers/media/video/ov7680.c @@ -0,0 +1,1051 @@ +/* + * A V4L2 driver for OmniVision OV7680 cameras. + * + * This file may be distributed under the terms of the GNU General + * Public License, version 2. + */ +#include +#include +#include +#include +#include +#include +#include +#include + + +MODULE_DESCRIPTION("A low-level driver for OmniVision ov7680 sensors"); +MODULE_LICENSE("GPL"); + +static int debug; +module_param(debug, bool, 0644); +MODULE_PARM_DESC(debug, "Debug level (0-1)"); + +/* + * Use a more agressive configuration instead of the default one. + */ +#define ALT_CONFIG_SET + +/* + * Basic window sizes. These probably belong somewhere more globally + * useful. + */ +#define VGA_WIDTH 640 +#define VGA_HEIGHT 480 +#define QVGA_WIDTH 320 +#define QVGA_HEIGHT 240 +#define CIF_WIDTH 352 +#define CIF_HEIGHT 288 +#define QCIF_WIDTH 176 +#define QCIF_HEIGHT 144 + +/* + * Our nominal (default) frame rate. + */ +#define OV7680_FRAME_RATE 30 + +/* + * The 7680 sits on i2c with ID 0x42 + */ +#define OV7680_I2C_ADDR 0x42 + +/* Registers */ +#define REG_CLKRC 0x11 /* Clocl control */ +#define CLK_EXT 0x40 /* Use external clock directly */ +#define CLK_SCALE 0x3f /* Mask for internal clock scale */ + +#define REG_COM12 0x12 /* Control 12 */ +#define COM12_RESET 0x80 /* Register reset */ + +#define REG_PIDH 0xA +#define REG_PIDL 0xB + +#define REG_0C 0xC +#define REG_0C_HFLIP (1 << 6) +#define REG_0C_VFLIP (1 << 7) +#define REG_MIDH 0x1C +#define REG_MIDL 0x1D + +/* + * Information we maintain about a known sensor. + */ +struct ov7680_format_struct; /* coming later */ +struct ov7680_info { + struct v4l2_subdev sd; + struct ov7680_format_struct *fmt; /* Current format */ + unsigned char sat; /* Saturation value */ + int hue; /* Hue value */ +}; + +static inline struct ov7680_info *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct ov7680_info, sd); +} + + + +/* + * The default register settings, as obtained from OmniVision. There + * is really no making sense of most of these - lots of "reserved" values + * and such. + * + * These settings give VGA YUYV. + */ + +struct regval_list { + unsigned char reg_num; + unsigned char value; +}; + +static struct regval_list ov7680_default_regs[] = { + {REG_COM12, COM12_RESET }, + + /* Clock */ + {0x11, 0x00}, /* out=int/2 */ + {0x29, 0x0a}, + + {REG_COM12, 0x0}, + {0x1e, 0x91}, + {0x14, 0xb2}, + {0x63, 0x0b}, + {0x64, 0x0f}, + {0x65, 0x07}, + {0x0c, 0x06}, + {0x82, 0x9a}, + {0x22, 0x40}, + {0x23, 0x20}, + {0x40, 0x10}, + {0x4a, 0x42}, +#ifdef ALT_CONFIG_SET + {0x4b, 0x64}, +#else + {0x4b, 0x42}, +#endif + {0x67, 0x50}, + {0x6b, 0x00}, + {0x6c, 0x00}, + {0x6d, 0x00}, + {0x6e, 0x00}, + {0x83, 0x00}, + {0x0c, 0x16}, + {0x82, 0x98}, + {0x3e, 0x30}, + {0x81, 0x06}, + + {0x42, 0x4a}, + {0x45, 0x40}, + {0x3f, 0x46}, + {0x48, 0x20}, + {0x21, 0x23}, + {0x5a, 0x10}, +#ifdef ALT_CONFIG_SET + {0x5c, 0xe0}, +#endif + {0x27, 0x33}, + {0x4d, 0x1d}, + {0x42, 0x4a}, + {0x4e, 0x54}, /* IO2.8v */ + + /* awb */ +#ifdef ALT_CONFIG_SET + {0x8F, 0x54}, + {0x90, 0x69}, + {0x91, 0x0f}, + {0x92, 0x99}, + {0x93, 0x98}, + {0x94, 0x0f}, + {0x95, 0x0f}, + {0x96, 0xff}, + {0x97, 0x00}, + {0x98, 0x10}, + {0x99, 0x20}, + {0x65, 0x87}, + {0x66, 0x02}, + {0x67, 0x5c}, + {0x32, 0xa0}, + {0x33, 0x00}, + {0x2f, 0x16}, + {0x30, 0x2a}, + {0x38, 0x84}, + {0x55, 0x86}, + {0x58, 0x83}, + {0x13, 0xb7}, + {0x38, 0x84}, + {0x59, 0x0e}, + {0x5f, 0x20}, + {0x56, 0x40}, + {0x51, 0x00}, + {0x57, 0x22}, + {0x59, 0x07}, + {0x5f, 0xa3}, + {0x59, 0x08}, + {0x5f, 0x54}, + {0x52, 0x30}, + {0x56, 0x29}, + {0x53, 0x20}, + {0x54, 0x30}, + {0x59, 0x00}, + {0x5f, 0xf0}, + {0x59, 0x01}, + {0x5f, 0xf0}, + {0x59, 0x0f}, + {0x5f, 0x20}, + {0x5f, 0x00}, + {0x59, 0x10}, + {0x5f, 0x7e}, + {0x59, 0x0a}, + {0x5f, 0x80}, + {0x59, 0x0b}, + {0x5f, 0x01}, + {0x59, 0x0C}, + {0x5f, 0x07}, + {0x5f, 0x0f}, + {0x59, 0x0d}, + {0x5f, 0x20}, + {0x59, 0x09}, + {0x5f, 0x30}, + {0x59, 0x02}, + {0x5f, 0x80}, + {0x59, 0x03}, + {0x5f, 0x60}, + {0x59, 0x04}, + {0x5f, 0xf0}, + {0x59, 0x05}, + {0x5f, 0x80}, + {0x59, 0x06}, + {0x5f, 0x04}, + {0x59, 0x26}, + {0x59, 0x0b}, + {0x5f, 0x31}, + {0x55, 0xa8}, + {0x27, 0xb3}, + {0x40, 0x23}, + {0x4d, 0x1d}, +#else + {0x97, 0x02}, + {0x96, 0xf8}, + {0x98, 0x37}, + {0x9a, 0x52}, + {0x99, 0x33}, + {0x9b, 0x42}, + {0x94, 0x0e}, + {0x92, 0x8c}, + {0x93, 0x96}, + {0x95, 0x0e}, + {0x8f, 0x55}, + {0x90, 0x58}, + {0x91, 0x0c}, + {0x89, 0x5c}, + {0x8b, 0x12}, + + {0x65, 0x87}, + /* {0x66, 0x02}, */ + {0x67, 0x5c}, + {0x32, 0xa0}, + {0x33, 0x00}, + {0x2f, 0x16}, + {0x30, 0x2a}, + {0x38, 0x84}, + {0x55, 0x86}, + {0x58, 0x83}, + {0x13, 0xff}, /* ;f7 */ + {0x38, 0x84}, + + {0x56, 0x40}, + {0x22, 0x70}, + {0x51, 0x00}, + {0x57, 0x2c}, + {0x59, 0x07}, + {0x5f, 0xa2}, + {0x59, 0x08}, + {0x5f, 0x54}, + {0x52, 0x30}, + {0x53, 0x20}, + {0x54, 0x30}, + {0x59, 0x00}, + {0x5f, 0xf0}, + {0x59, 0x01}, + {0x5f, 0xf0}, + {0x59, 0x0f}, + {0x5f, 0x20}, + {0x5f, 0x00}, + {0x59, 0x10}, + {0x5f, 0x7e}, + {0x59, 0x0a}, + {0x5f, 0x80}, + {0x59, 0x0b}, + {0x5f, 0x01}, + {0x59, 0x0c}, + {0x5f, 0x07}, + {0x5f, 0x0f}, + {0x59, 0x0d}, + {0x5f, 0x20}, + {0x59, 0x0e}, + {0x5f, 0x20}, + {0x59, 0x09}, + {0x5f, 0x30}, + {0x59, 0x02}, + {0x5f, 0x80}, + {0x59, 0x03}, + {0x5f, 0x60}, + {0x59, 0x04}, + {0x5f, 0xf0}, + {0x59, 0x05}, + {0x5f, 0x80}, + {0x59, 0x06}, + {0x5f, 0x04}, + {0x59, 0x26}, + {0x59, 0x0b}, + {0x5f, 0x31}, + {0x55, 0xa8}, + {0x56, 0x29}, + + {0x27, 0xb3}, + {0x40, 0x23}, + {0x4d, 0x2d}, +#endif + + /* Color Matrix */ +#ifdef ALT_CONFIG_SET + {0xb7, 0x98}, + {0xb8, 0x98}, + {0xb9, 0x00}, + {0xba, 0x28}, + {0xbb, 0x70}, + {0xbc, 0x98}, + {0xbd, 0x5a}, +#else + {0xba, 0x18}, + {0xbb, 0x80}, + {0xbc, 0x98}, + {0xb7, 0x90}, + {0xb8, 0x8f}, + {0xb9, 0x01}, + {0xbd, 0x5a}, +#endif + + {0xbe, 0xb0}, + {0xbf, 0x9d}, + {0xc0, 0x13}, + {0xc1, 0x16}, + {0xc2, 0x7b}, + {0xc3, 0x91}, + {0xc4, 0x1e}, + {0xc5, 0x9d}, + {0xc6, 0x9a}, + {0xc7, 0x03}, + {0xc8, 0x2e}, + {0xc9, 0x91}, + {0xca, 0xbf}, + {0xcb, 0x1e}, + + /* Gamma */ +#ifdef ALT_CONFIG_SET + {0xaf, 0x1e}, + {0xa0, 0x06}, + {0xa1, 0x18}, + {0xa2, 0x2a}, + {0xa3, 0x50}, + {0xa4, 0x5f}, + {0xa5, 0x6c}, + {0xa6, 0x79}, + {0xa7, 0x84}, + {0xa8, 0x8d}, + {0xa9, 0x96}, + {0xaa, 0xa5}, + {0xab, 0xb0}, + {0xac, 0xc6}, + {0xad, 0xd4}, + {0xae, 0xea}, +#else + {0xaf, 0x30}, + {0xa0, 0x01}, + {0xa1, 0x0f}, + {0xa2, 0x1d}, + {0xa3, 0x3c}, + {0xa4, 0x4a}, + {0xa5, 0x5a}, + {0xa6, 0x69}, + {0xa7, 0x77}, + {0xa8, 0x83}, + {0xa9, 0x8e}, + {0xaa, 0x9f}, + {0xab, 0xac}, + {0xac, 0xc1}, + {0xad, 0xcc}, + {0xae, 0xd0}, +#endif + + {0x89, 0x5c}, + {0x8a, 0x11}, +#ifdef ALT_CONFIG_SET + {0x8b, 0x92}, +#else + {0x8b, 0x12}, +#endif + {0x8c, 0x11}, + {0x8d, 0x52}, +#ifdef ALT_CONFIG_SET + {0x96, 0xff}, + {0x97, 0x00}, + {0x9c, 0xf0}, +#else + {0x96, 0xf8}, + {0x97, 0x02}, + {0x9c, 0x64}, +#endif + {0x9d, 0xf0}, + {0x9e, 0xf0}, + +#ifdef ALT_CONFIG_SET + {0xb2, 0x06}, + {0xb3, 0x03}, + {0xb4, 0x05}, + {0xb5, 0x04}, + {0xb6, 0x02}, /* ; 03 */ + + {0xd5, 0x06}, + {0xd6, 0x10}, +#else + {0xb2, 0x03}, + {0xb3, 0x02}, + {0xb4, 0x65}, + {0xb5, 0x02}, + {0xb6, 0x02}, +#endif + {0xdb, 0x40}, + {0xdc, 0x40}, + {0xdf, 0x09}, + +#ifdef ALT_CONFIG_SET + {0x11, 0x00}, +#endif + {0x24, 0x40}, +#ifdef ALT_CONFIG_SET + {0x25, 0x30}, + {0x26, 0x81}, +#else + {0x25, 0x38}, + {0x26, 0x82}, + {0x4f, 0x4d}, + {0x50, 0x40}, +#endif + + {0x5a, 0x14}, +#ifdef ALT_CONFIG_SET + {0x5b, 0xe7}, + {0x5c, 0x1f}, +#else + {0x5b, 0x00}, + {0x5c, 0x1c}, +#endif + {0x5d, 0x30}, + {0x81, 0x07}, + + /* Lens Correction */ +#ifdef ALT_CONFIG_SET + {0x31, 0x0f}, + {0x32, 0x00}, + {0x35, 0x15}, + {0x37, 0x5d}, /* for color R */ + {0x34, 0x48}, /* for color G */ + {0x36, 0x50}, /* for color B */ +#else + {0x31, 0x0f}, + {0x32, 0x8c}, + {0x33, 0x37}, + {0x35, 0x10}, + {0x37, 0x48}, + {0x34, 0x3b}, + {0x36, 0x3a}, +#endif + + {0x84, 0x02}, + + /* 30fps */ + {0x2a, 0xb0}, + {0x2b, 0x0b}, + {0x4f, 0x9a}, /* banding value */ + {0x50, 0x80}, + {0x21, 0x23}, /* banding step */ + + /* General control */ + {0x14, 0xa0}, /* 8x max gain */ + {0x15, 0x64}, /* disable night mode */ + +#ifndef ALT_CONFIG_SET + /* Contrast adjustment */ + {0xd5, 0x06}, + {0xd6, 0x00}, + {0xd7, 0x25}, + {0xdf, 0x01}, + {0xdb, 0x4c}, + {0xdc, 0x40}, + + /* AE Range */ + {0x24, 0x50}, + {0x25, 0x40}, + {0x26, 0x83}, + + /* Black level */ + {0x66, 0x02}, /* BLC */ + {0x80, 0x7f}, + {0x85, 0x01}, +#endif + + { 0xff, 0xff }, /* END MARKER */ +}; + + +/* + * Here we'll try to encapsulate the changes for just the output + * video format. + * + * RGB656 and YUV422 come from OV; RGB444 is homebrewed. + * + * IMPORTANT RULE: the first entry must be for COM7, see ov7680_s_fmt for why. + */ + + +static struct regval_list ov7680_fmt_yuv422[] = { + { REG_COM12, 0x0 }, /* Selects YUV mode */ + { 0x0c, 0x16 }, + { 0xff, 0xff }, +}; + + +/* + * Low-level register I/O. + */ + +static int ov7680_read(struct v4l2_subdev *sd, unsigned char reg, + unsigned char *value) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret >= 0) { + *value = (unsigned char)ret; + ret = 0; + } + return ret; +} + + +static int ov7680_write(struct v4l2_subdev *sd, unsigned char reg, + unsigned char value) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret = i2c_smbus_write_byte_data(client, reg, value); + + if (reg == REG_COM12 && (value & COM12_RESET)) + msleep(2); /* Wait for reset to run */ + return ret; +} + + +/* + * Write a list of register settings; ff/ff stops the process. + */ +static int ov7680_write_array(struct v4l2_subdev *sd, struct regval_list *vals) +{ + while (vals->reg_num != 0xff || vals->value != 0xff) { + int ret = ov7680_write(sd, vals->reg_num, vals->value); + if (ret < 0) + return ret; + vals++; + } + return 0; +} + + +/* + * Stuff that knows about the sensor. + */ +static int ov7680_reset(struct v4l2_subdev *sd, u32 val) +{ + ov7680_write(sd, REG_COM12, COM12_RESET); + msleep(1); + return 0; +} + + +static int ov7680_init(struct v4l2_subdev *sd, u32 val) +{ + return ov7680_write_array(sd, ov7680_default_regs); +} + + + +static int ov7680_detect(struct v4l2_subdev *sd) +{ + unsigned char v; + int ret; + + ret = ov7680_read(sd, REG_MIDH, &v); + if (ret < 0) + return ret; + if (v != 0x7f) /* OV manuf. id. */ + return -ENODEV; + ret = ov7680_read(sd, REG_MIDL, &v); + if (ret < 0) + return ret; + if (v != 0xa2) + return -ENODEV; + /* + * OK, we know we have an OmniVision chip...but which one? + */ + ret = ov7680_read(sd, REG_PIDH, &v); + if (ret < 0) + return ret; + if (v != 0x76) /* PIDH = 0x76 */ + return -ENODEV; + ret = ov7680_read(sd, REG_PIDL, &v); + if (ret < 0) + return ret; + if (v != 0x80) /* PIDL = 0x80 */ + return -ENODEV; + + ret = ov7680_init(sd, 0); + + return ret; +} + + +/* + * Store information about the video data format. The color matrix + * is deeply tied into the format, so keep the relevant values here. + * The magic matrix nubmers come from OmniVision. + */ +static struct ov7680_format_struct { + __u8 *desc; + __u32 pixelformat; + struct regval_list *regs; + int bpp; /* Bytes per pixel */ +} ov7680_formats[] = { + { + .desc = "YUYV 4:2:2", + .pixelformat = V4L2_PIX_FMT_YUYV, + .regs = ov7680_fmt_yuv422, + .bpp = 2, + }, +}; +#define N_OV7680_FMTS ARRAY_SIZE(ov7680_formats) + +static struct regval_list ov7680_vga_regs[] = { + { 0x81, 0x07 }, + { 0x84, 0x62 }, + { 0xd0, 0xa4 }, + { 0xd1, 0x78 }, + { 0xd2, 0xa0 }, + { 0xd3, 0x78 }, + { 0xd4, 0x20 }, + { 0xff, 0xff }, +}; + +static struct regval_list ov7680_cif_regs[] = { + { 0x81, 0xff }, + { 0x84, 0x02 }, + { 0xd0, 0xa4 }, + { 0xd1, 0x78 }, + { 0xd2, 0x58 }, + { 0xd3, 0x48 }, + { 0xd4, 0x20 }, + { 0xff, 0xff }, +}; + +/* + * Then there is the issue of window sizes. Try to capture the info here. + */ +static struct ov7680_win_size { + int width; + int height; + int hstart; /* Start/size values for the camera. Note */ + int hsize; /* that they do not always make complete */ + int vstart; /* sense to humans, but evidently the sensor */ + int vsize; /* will do the right thing... */ + struct regval_list *regs; /* Regs to tweak */ +/* h/vref stuff */ +} ov7680_win_sizes[] = { + /* VGA */ + { + .width = VGA_WIDTH, + .height = VGA_HEIGHT, + .hstart = 104, /* Value from Omnivision */ + .hsize = ((VGA_WIDTH+16)/4), + .vstart = 14, + .vsize = ((VGA_HEIGHT+8)/2), + .regs = ov7680_vga_regs, + }, + /* CIF */ + { + .width = CIF_WIDTH, + .height = CIF_HEIGHT, + .hstart = 104, /* Value from Omnivision */ + .hsize = ((VGA_WIDTH+16)/4), + .vstart = 14, + .vsize = ((VGA_HEIGHT+8)/2), + .regs = ov7680_cif_regs, + }, +}; + +#define N_WIN_SIZES (ARRAY_SIZE(ov7680_win_sizes)) + +static int ov7680_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) +{ + struct ov7680_format_struct *ofmt; + + if (fmt->index >= N_OV7680_FMTS) + return -EINVAL; + + ofmt = ov7680_formats + fmt->index; + fmt->flags = 0; + strcpy(fmt->description, ofmt->desc); + fmt->pixelformat = ofmt->pixelformat; + return 0; +} + + +static int ov7680_try_fmt_internal(struct v4l2_subdev *sd, + struct v4l2_format *fmt, + struct ov7680_format_struct **ret_fmt, + struct ov7680_win_size **ret_wsize) +{ + int index; + struct ov7680_win_size *wsize; + struct v4l2_pix_format *pix = &fmt->fmt.pix; + + for (index = 0; index < N_OV7680_FMTS; index++) + if (ov7680_formats[index].pixelformat == pix->pixelformat) + break; + if (index >= N_OV7680_FMTS) { + /* default to first format */ + index = 0; + pix->pixelformat = ov7680_formats[0].pixelformat; + } + if (ret_fmt != NULL) + *ret_fmt = ov7680_formats + index; + /* + * Fields: the OV devices claim to be progressive. + */ + pix->field = V4L2_FIELD_NONE; + /* + * Round requested image size down to the nearest + * we support, but not below the smallest. + */ + for (wsize = ov7680_win_sizes; wsize < ov7680_win_sizes + N_WIN_SIZES; + wsize++) + if (pix->width >= wsize->width && pix->height >= wsize->height) + break; + if (wsize >= ov7680_win_sizes + N_WIN_SIZES) + wsize--; /* Take the smallest one */ + if (ret_wsize != NULL) + *ret_wsize = wsize; + /* + * Note the size we'll actually handle. + */ + pix->width = wsize->width; + pix->height = wsize->height; + pix->bytesperline = pix->width*ov7680_formats[index].bpp; + pix->sizeimage = pix->height*pix->bytesperline; + return 0; +} + +static int ov7680_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + return ov7680_try_fmt_internal(sd, fmt, NULL, NULL); +} + +/* + * Set a format. + */ +static int ov7680_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + int ret; + struct ov7680_format_struct *ovfmt; + struct ov7680_win_size *wsize; + struct ov7680_info *info = to_state(sd); + + ret = ov7680_try_fmt_internal(sd, fmt, &ovfmt, &wsize); + if (ret) + return ret; + /* + * write the array. + */ + if (wsize->regs) + ret += ov7680_write_array(sd, wsize->regs); + ret += ov7680_write_array(sd, ovfmt->regs); + info->fmt = ovfmt; + return ret; +} + +/* + * Implement G/S_PARM. There is a "high quality" mode we could try + * to do someday; for now, we just do the frame rate tweak. + */ +static int ov7680_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) +{ + struct v4l2_captureparm *cp = &parms->parm.capture; + unsigned char clkrc; + int ret; + + if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + ret = ov7680_read(sd, REG_CLKRC, &clkrc); + if (ret < 0) + return ret; + memset(cp, 0, sizeof(struct v4l2_captureparm)); + cp->capability = V4L2_CAP_TIMEPERFRAME; + cp->timeperframe.numerator = 1; + cp->timeperframe.denominator = OV7680_FRAME_RATE; + if ((clkrc & CLK_EXT) == 0 && (clkrc & CLK_SCALE) > 1) + cp->timeperframe.denominator /= (clkrc & CLK_SCALE); + return 0; +} + +static int ov7680_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) +{ + struct v4l2_captureparm *cp = &parms->parm.capture; + struct v4l2_fract *tpf = &cp->timeperframe; + unsigned char clkrc; + int ret, div; + + if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (cp->extendedmode != 0) + return -EINVAL; + /* + * CLKRC has a reserved bit, so let's preserve it. + */ + ret = ov7680_read(sd, REG_CLKRC, &clkrc); + if (ret < 0) + return ret; + if (tpf->numerator == 0 || tpf->denominator == 0) + div = 1; /* Reset to full rate */ + else + div = (tpf->numerator*OV7680_FRAME_RATE)/tpf->denominator; + if (div == 0) + div = 1; + else if (div > CLK_SCALE) + div = CLK_SCALE; + clkrc = (clkrc & 0xc0) | div; + tpf->numerator = 1; + tpf->denominator = OV7680_FRAME_RATE/div; + return ov7680_write(sd, REG_CLKRC, clkrc); +} + + + +/* + * Code for dealing with controls. + */ +static int ov7680_g_hflip(struct v4l2_subdev *sd, __s32 *value) +{ + int ret; + unsigned char v = 0; + + ret = ov7680_read(sd, REG_0C, &v); + *value = (v & REG_0C_HFLIP) == REG_0C_HFLIP; + return ret; +} + + +static int ov7680_s_hflip(struct v4l2_subdev *sd, int value) +{ + unsigned char v = 0; + int ret; + + ret = ov7680_read(sd, REG_0C, &v); + if (value) + v |= REG_0C_HFLIP; + else + v &= ~REG_0C_HFLIP; + msleep(10); /* FIXME */ + ret += ov7680_write(sd, REG_0C, v); + return ret; +} + + + +static int ov7680_g_vflip(struct v4l2_subdev *sd, __s32 *value) +{ + int ret; + unsigned char v = 0; + + ret = ov7680_read(sd, REG_0C, &v); + *value = (v & REG_0C_VFLIP) == REG_0C_VFLIP; + return ret; +} + + +static int ov7680_s_vflip(struct v4l2_subdev *sd, int value) +{ + unsigned char v = 0; + int ret; + + ret = ov7680_read(sd, REG_0C, &v); + if (value) + v |= REG_0C_VFLIP; + else + v &= ~REG_0C_VFLIP; + msleep(10); /* FIXME */ + ret += ov7680_write(sd, REG_0C, v); + return ret; +} + +static int ov7680_queryctrl(struct v4l2_subdev *sd, + struct v4l2_queryctrl *qc) +{ + /* Fill in min, max, step and default value for these controls. */ + switch (qc->id) { + case V4L2_CID_VFLIP: + case V4L2_CID_HFLIP: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); + } + return -EINVAL; +} + +static int ov7680_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_VFLIP: + return ov7680_g_vflip(sd, &ctrl->value); + case V4L2_CID_HFLIP: + return ov7680_g_hflip(sd, &ctrl->value); + } + return -EINVAL; +} + +static int ov7680_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_VFLIP: + return ov7680_s_vflip(sd, ctrl->value); + case V4L2_CID_HFLIP: + return ov7680_s_hflip(sd, ctrl->value); + } + return -EINVAL; +} + +static int ov7680_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV7680, 0); +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int ov7680_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + unsigned char val = 0; + int ret; + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + ret = ov7680_read(sd, reg->reg & 0xff, &val); + reg->val = val; + reg->size = 1; + return ret; +} + +static int ov7680_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client, ®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + ov7680_write(sd, reg->reg & 0xff, reg->val & 0xff); + return 0; +} +#endif + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops ov7680_core_ops = { + .g_chip_ident = ov7680_g_chip_ident, + .g_ctrl = ov7680_g_ctrl, + .s_ctrl = ov7680_s_ctrl, + .queryctrl = ov7680_queryctrl, + .reset = ov7680_reset, + .init = ov7680_init, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = ov7680_g_register, + .s_register = ov7680_s_register, +#endif +}; + +static const struct v4l2_subdev_video_ops ov7680_video_ops = { + .enum_fmt = ov7680_enum_fmt, + .try_fmt = ov7680_try_fmt, + .s_fmt = ov7680_s_fmt, + .s_parm = ov7680_s_parm, + .g_parm = ov7680_g_parm, +}; + +static const struct v4l2_subdev_ops ov7680_ops = { + .core = &ov7680_core_ops, + .video = &ov7680_video_ops, +}; + +/* ----------------------------------------------------------------------- */ + +static int ov7680_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct v4l2_subdev *sd; + struct ov7680_info *info; + int ret; + + info = kzalloc(sizeof (struct ov7680_info), GFP_KERNEL); + if (info == NULL) + return -ENOMEM; + sd = &info->sd; + v4l2_i2c_subdev_init(sd, client, &ov7680_ops); + + /* Make sure it's an ov7680 */ + ret = ov7680_detect(sd); + if (ret) { + v4l_dbg(1, debug, client, + "chip found @ 0x%x (%s) is not an ov7680 chip.\n", + client->addr << 1, client->adapter->name); + kfree(info); + return ret; + } + v4l_info(client, "chip found @ 0x%02x (%s)\n", + client->addr << 1, client->adapter->name); + + info->fmt = &ov7680_formats[0]; + info->sat = 128; /* Review this */ + + return 0; +} + + +static int ov7680_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); + return 0; +} + +static const struct i2c_device_id ov7680_id[] = { + { "ov7680", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ov7680_id); + +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "ov7680", + .probe = ov7680_probe, + .remove = ov7680_remove, + .id_table = ov7680_id, +}; --- linux-mvl-dove-2.6.31.orig/drivers/media/video/Kconfig +++ linux-mvl-dove-2.6.31/drivers/media/video/Kconfig @@ -312,6 +312,13 @@ OV7670 VGA camera. It currently only works with the M88ALP01 controller. +config VIDEO_OV7680 + tristate "OmniVision OV7680 sensor support" + depends on I2C && VIDEO_V4L2 + ---help--- + This is a Video4Linux2 sensor-level driver for the OmniVision + OV7680 VGA camera. + config VIDEO_MT9V011 tristate "Micron mt9v011 sensor support" depends on I2C && VIDEO_V4L2 @@ -711,8 +718,9 @@ config VIDEO_CAFE_CCIC tristate "Marvell 88ALP01 (Cafe) CMOS Camera Controller support" - depends on PCI && I2C && VIDEO_V4L2 + depends on I2C && VIDEO_V4L2 select VIDEO_OV7670 + select VIDEO_OV7680 ---help--- This is a video4linux2 driver for the Marvell 88ALP01 integrated CMOS camera controller. This is the controller found on first- --- linux-mvl-dove-2.6.31.orig/drivers/media/video/cafe_ccic-regs.h +++ linux-mvl-dove-2.6.31/drivers/media/video/cafe_ccic-regs.h @@ -120,7 +120,7 @@ #define TWSIC0_EN 0x00000001 /* TWSI enable */ #define TWSIC0_MODE 0x00000002 /* 1 = 16-bit, 0 = 8-bit */ #define TWSIC0_SID 0x000003fc /* Slave ID */ -#define TWSIC0_SID_SHIFT 2 +#define TWSIC0_SID_SHIFT 3 #define TWSIC0_CLKDIV 0x0007fc00 /* Clock divider */ #define TWSIC0_MASKACK 0x00400000 /* Mask ack from sensor */ #define TWSIC0_OVMAGIC 0x00800000 /* Make it work on OV sensors */ @@ -134,9 +134,10 @@ #define TWSIC1_RVALID 0x04000000 /* Read data valid */ #define TWSIC1_ERROR 0x08000000 /* Something screwed up */ - +/* The following register exist in pci devices only */ #define REG_UBAR 0xc4 /* Upper base address register */ + /* * Here's the weird global control registers which are said to live * way up here. --- linux-mvl-dove-2.6.31.orig/drivers/media/video/v4l1-compat.c +++ linux-mvl-dove-2.6.31/drivers/media/video/v4l1-compat.c @@ -565,10 +565,9 @@ break; } chan->norm = 0; - err = drv(file, VIDIOC_G_STD, &sid); - if (err < 0) - dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %ld\n", err); - if (err == 0) { + /* Note: G_STD might not be present for radio receivers, + * so we should ignore any errors. */ + if (drv(file, VIDIOC_G_STD, &sid) == 0) { if (sid & V4L2_STD_PAL) chan->norm = VIDEO_MODE_PAL; if (sid & V4L2_STD_NTSC) @@ -777,10 +776,9 @@ tun->flags |= VIDEO_TUNER_SECAM; } - err = drv(file, VIDIOC_G_STD, &sid); - if (err < 0) - dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %ld\n", err); - if (err == 0) { + /* Note: G_STD might not be present for radio receivers, + * so we should ignore any errors. */ + if (drv(file, VIDIOC_G_STD, &sid) == 0) { if (sid & V4L2_STD_PAL) tun->mode = VIDEO_MODE_PAL; if (sid & V4L2_STD_NTSC) --- linux-mvl-dove-2.6.31.orig/drivers/media/video/Makefile +++ linux-mvl-dove-2.6.31/drivers/media/video/Makefile @@ -116,6 +116,10 @@ obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o +obj-$(CONFIG_VIDEO_OV7670) += ov7670.o +obj-$(CONFIG_VIDEO_OV7680) += ov7680.o + +obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o obj-$(CONFIG_USB_DABUSB) += dabusb.o obj-$(CONFIG_USB_OV511) += ov511.o --- linux-mvl-dove-2.6.31.orig/drivers/media/video/ov511.c +++ linux-mvl-dove-2.6.31/drivers/media/video/ov511.c @@ -5878,7 +5878,7 @@ goto error; } - mutex_lock(&ov->lock); + mutex_unlock(&ov->lock); return 0; --- linux-mvl-dove-2.6.31.orig/drivers/media/video/ov7670.c +++ linux-mvl-dove-2.6.31/drivers/media/video/ov7670.c @@ -47,9 +47,9 @@ #define OV7670_FRAME_RATE 30 /* - * The 7670 sits on i2c with ID 0x42 + * The 7670 sits on i2c with ID 0x21 */ -#define OV7670_I2C_ADDR 0x42 +#define OV7670_I2C_ADDR 0x21 /* Registers */ #define REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ @@ -474,10 +474,8 @@ unsigned char v; int ret; - ret = ov7670_init(sd, 0); - if (ret < 0) - return ret; ret = ov7670_read(sd, REG_MIDH, &v); + if (ret < 0) return ret; if (v != 0x7f) /* OV manuf. id. */ @@ -500,7 +498,9 @@ return ret; if (v != 0x73) /* PID + VER = 0x76 / 0x73 */ return -ENODEV; - return 0; + + ret = ov7670_init(sd, 0); + return ret; } --- linux-mvl-dove-2.6.31.orig/drivers/media/video/cx88/cx88.h +++ linux-mvl-dove-2.6.31/drivers/media/video/cx88/cx88.h @@ -237,6 +237,7 @@ #define CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII 79 #define CX88_BOARD_HAUPPAUGE_IRONLY 80 #define CX88_BOARD_WINFAST_DTV1800H 81 +#define CX88_BOARD_WINFAST_DTV2000H_J 82 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, --- linux-mvl-dove-2.6.31.orig/drivers/media/video/cx88/cx88-cards.c +++ linux-mvl-dove-2.6.31/drivers/media/video/cx88/cx88-cards.c @@ -1283,6 +1283,51 @@ }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_WINFAST_DTV2000H_J] = { + .name = "WinFast DTV2000 H rev. J", + .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x00017300, + .gpio1 = 0x00008207, + .gpio2 = 0x00000000, + .gpio3 = 0x02000000, + },{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x00018300, + .gpio1 = 0x0000f207, + .gpio2 = 0x00017304, + .gpio3 = 0x02000000, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x00018301, + .gpio1 = 0x0000f207, + .gpio2 = 0x00017304, + .gpio3 = 0x02000000, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x00018301, + .gpio1 = 0x0000f207, + .gpio2 = 0x00017304, + .gpio3 = 0x02000000, + }}, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x00015702, + .gpio1 = 0x0000f207, + .gpio2 = 0x00015702, + .gpio3 = 0x02000000, + }, + .mpeg = CX88_MPEG_DVB, + }, [CX88_BOARD_GENIATECH_DVBS] = { .name = "Geniatech DVB-S", .tuner_type = TUNER_ABSENT, @@ -2282,6 +2327,10 @@ .subdevice = 0x665e, .card = CX88_BOARD_WINFAST_DTV2000H, },{ + .subvendor = 0x107d, + .subdevice = 0x6f2b, + .card = CX88_BOARD_WINFAST_DTV2000H_J, + },{ .subvendor = 0x18ac, .subdevice = 0xd800, /* FusionHDTV 3 Gold (original revision) */ .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q, --- linux-mvl-dove-2.6.31.orig/drivers/media/video/cx88/cx88-dvb.c +++ linux-mvl-dove-2.6.31/drivers/media/video/cx88/cx88-dvb.c @@ -696,6 +696,7 @@ } break; case CX88_BOARD_WINFAST_DTV2000H: + case CX88_BOARD_WINFAST_DTV2000H_J: case CX88_BOARD_HAUPPAUGE_HVR1100: case CX88_BOARD_HAUPPAUGE_HVR1100LP: case CX88_BOARD_HAUPPAUGE_HVR1300: --- linux-mvl-dove-2.6.31.orig/drivers/media/video/cx88/cx88-input.c +++ linux-mvl-dove-2.6.31/drivers/media/video/cx88/cx88-input.c @@ -225,6 +225,7 @@ ir->sampling = 1; break; case CX88_BOARD_WINFAST_DTV2000H: + case CX88_BOARD_WINFAST_DTV2000H_J: case CX88_BOARD_WINFAST_DTV1800H: ir_codes = ir_codes_winfast; ir->gpio_addr = MO_GP0_IO; --- linux-mvl-dove-2.6.31.orig/drivers/media/video/saa7134/saa7134-cards.c +++ linux-mvl-dove-2.6.31/drivers/media/video/saa7134/saa7134-cards.c @@ -3373,6 +3373,7 @@ .tuner_config = 3, .mpeg = SAA7134_MPEG_DVB, .ts_type = SAA7134_MPEG_TS_SERIAL, + .ts_force_val = 1, .gpiomask = 0x0800100, /* GPIO 21 is an INPUT */ .inputs = {{ .name = name_tv, --- linux-mvl-dove-2.6.31.orig/drivers/media/video/saa7134/saa7134-input.c +++ linux-mvl-dove-2.6.31/drivers/media/video/saa7134/saa7134-input.c @@ -684,8 +684,6 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) { - struct i2c_board_info info; - struct IR_i2c_init_data init_data; const unsigned short addr_list[] = { 0x7a, 0x47, 0x71, 0x2d, I2C_CLIENT_END @@ -705,32 +703,32 @@ return; } - memset(&info, 0, sizeof(struct i2c_board_info)); - memset(&init_data, 0, sizeof(struct IR_i2c_init_data)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + memset(&dev->info, 0, sizeof(dev->info)); + memset(&dev->init_data, 0, sizeof(dev->init_data)); + strlcpy(dev->info.type, "ir_video", I2C_NAME_SIZE); switch (dev->board) { case SAA7134_BOARD_PINNACLE_PCTV_110i: case SAA7134_BOARD_PINNACLE_PCTV_310i: - init_data.name = "Pinnacle PCTV"; + dev->init_data.name = "Pinnacle PCTV"; if (pinnacle_remote == 0) { - init_data.get_key = get_key_pinnacle_color; - init_data.ir_codes = ir_codes_pinnacle_color; + dev->init_data.get_key = get_key_pinnacle_color; + dev->init_data.ir_codes = ir_codes_pinnacle_color; } else { - init_data.get_key = get_key_pinnacle_grey; - init_data.ir_codes = ir_codes_pinnacle_grey; + dev->init_data.get_key = get_key_pinnacle_grey; + dev->init_data.ir_codes = ir_codes_pinnacle_grey; } break; case SAA7134_BOARD_UPMOST_PURPLE_TV: - init_data.name = "Purple TV"; - init_data.get_key = get_key_purpletv; - init_data.ir_codes = ir_codes_purpletv; + dev->init_data.name = "Purple TV"; + dev->init_data.get_key = get_key_purpletv; + dev->init_data.ir_codes = ir_codes_purpletv; break; case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: - init_data.name = "MSI TV@nywhere Plus"; - init_data.get_key = get_key_msi_tvanywhere_plus; - init_data.ir_codes = ir_codes_msi_tvanywhere_plus; - info.addr = 0x30; + dev->init_data.name = "MSI TV@nywhere Plus"; + dev->init_data.get_key = get_key_msi_tvanywhere_plus; + dev->init_data.ir_codes = ir_codes_msi_tvanywhere_plus; + dev->info.addr = 0x30; /* MSI TV@nywhere Plus controller doesn't seem to respond to probes unless we read something from an existing device. Weird... @@ -741,9 +739,9 @@ (1 == rc) ? "yes" : "no"); break; case SAA7134_BOARD_HAUPPAUGE_HVR1110: - init_data.name = "HVR 1110"; - init_data.get_key = get_key_hvr1110; - init_data.ir_codes = ir_codes_hauppauge_new; + dev->init_data.name = "HVR 1110"; + dev->init_data.get_key = get_key_hvr1110; + dev->init_data.ir_codes = ir_codes_hauppauge_new; break; case SAA7134_BOARD_BEHOLD_607FM_MK3: case SAA7134_BOARD_BEHOLD_607FM_MK5: @@ -757,26 +755,26 @@ case SAA7134_BOARD_BEHOLD_M63: case SAA7134_BOARD_BEHOLD_M6_EXTRA: case SAA7134_BOARD_BEHOLD_H6: - init_data.name = "BeholdTV"; - init_data.get_key = get_key_beholdm6xx; - init_data.ir_codes = ir_codes_behold; + dev->init_data.name = "BeholdTV"; + dev->init_data.get_key = get_key_beholdm6xx; + dev->init_data.ir_codes = ir_codes_behold; break; case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: - info.addr = 0x40; + dev->info.addr = 0x40; break; } - if (init_data.name) - info.platform_data = &init_data; + if (dev->init_data.name) + dev->info.platform_data = &dev->init_data; /* No need to probe if address is known */ - if (info.addr) { - i2c_new_device(&dev->i2c_adap, &info); + if (dev->info.addr) { + i2c_new_device(&dev->i2c_adap, &dev->info); return; } /* Address not known, fallback to probing */ - i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); + i2c_new_probed_device(&dev->i2c_adap, &dev->info, addr_list); } static int saa7134_rc5_irq(struct saa7134_dev *dev) --- linux-mvl-dove-2.6.31.orig/drivers/media/video/saa7134/saa7134.h +++ linux-mvl-dove-2.6.31/drivers/media/video/saa7134/saa7134.h @@ -355,6 +355,7 @@ enum saa7134_mpeg_type mpeg; enum saa7134_mpeg_ts_type ts_type; unsigned int vid_port_opts; + unsigned int ts_force_val:1; }; #define card_has_radio(dev) (NULL != saa7134_boards[dev->board].radio.name) @@ -584,6 +585,10 @@ int nosignal; unsigned int insuspend; + /* I2C keyboard data */ + struct i2c_board_info info; + struct IR_i2c_init_data init_data; + /* SAA7134_MPEG_* */ struct saa7134_ts ts; struct saa7134_dmaqueue ts_q; --- linux-mvl-dove-2.6.31.orig/drivers/media/video/saa7134/saa7134-ts.c +++ linux-mvl-dove-2.6.31/drivers/media/video/saa7134/saa7134-ts.c @@ -262,11 +262,13 @@ switch (saa7134_boards[dev->board].ts_type) { case SAA7134_MPEG_TS_PARALLEL: saa_writeb(SAA7134_TS_SERIAL0, 0x40); - saa_writeb(SAA7134_TS_PARALLEL, 0xec); + saa_writeb(SAA7134_TS_PARALLEL, 0xec | + (saa7134_boards[dev->board].ts_force_val << 4)); break; case SAA7134_MPEG_TS_SERIAL: saa_writeb(SAA7134_TS_SERIAL0, 0xd8); - saa_writeb(SAA7134_TS_PARALLEL, 0x6c); + saa_writeb(SAA7134_TS_PARALLEL, 0x6c | + (saa7134_boards[dev->board].ts_force_val << 4)); saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 0xbc); saa_writeb(SAA7134_TS_SERIAL1, 0x02); break; --- linux-mvl-dove-2.6.31.orig/drivers/media/video/em28xx/em28xx-audio.c +++ linux-mvl-dove-2.6.31/drivers/media/video/em28xx/em28xx-audio.c @@ -383,6 +383,11 @@ static int snd_em28xx_prepare(struct snd_pcm_substream *substream) { + struct em28xx *dev = snd_pcm_substream_chip(substream); + + dev->adev.hwptr_done_capture = 0; + dev->adev.capture_transfer_done = 0; + return 0; } --- linux-mvl-dove-2.6.31.orig/drivers/media/video/em28xx/em28xx-cards.c +++ linux-mvl-dove-2.6.31/drivers/media/video/em28xx/em28xx-cards.c @@ -2170,8 +2170,6 @@ /* ----------------------------------------------------------------------- */ void em28xx_register_i2c_ir(struct em28xx *dev) { - struct i2c_board_info info; - struct IR_i2c_init_data init_data; const unsigned short addr_list[] = { 0x30, 0x47, I2C_CLIENT_END }; @@ -2179,9 +2177,9 @@ if (disable_ir) return; - memset(&info, 0, sizeof(struct i2c_board_info)); - memset(&init_data, 0, sizeof(struct IR_i2c_init_data)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + memset(&dev->info, 0, sizeof(&dev->info)); + memset(&dev->init_data, 0, sizeof(dev->init_data)); + strlcpy(dev->info.type, "ir_video", I2C_NAME_SIZE); /* detect & configure */ switch (dev->model) { @@ -2191,19 +2189,19 @@ break; case (EM2800_BOARD_TERRATEC_CINERGY_200): case (EM2820_BOARD_TERRATEC_CINERGY_250): - init_data.ir_codes = ir_codes_em_terratec; - init_data.get_key = em28xx_get_key_terratec; - init_data.name = "i2c IR (EM28XX Terratec)"; + dev->init_data.ir_codes = ir_codes_em_terratec; + dev->init_data.get_key = em28xx_get_key_terratec; + dev->init_data.name = "i2c IR (EM28XX Terratec)"; break; case (EM2820_BOARD_PINNACLE_USB_2): - init_data.ir_codes = ir_codes_pinnacle_grey; - init_data.get_key = em28xx_get_key_pinnacle_usb_grey; - init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; + dev->init_data.ir_codes = ir_codes_pinnacle_grey; + dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey; + dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; break; case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): - init_data.ir_codes = ir_codes_hauppauge_new; - init_data.get_key = em28xx_get_key_em_haup; - init_data.name = "i2c IR (EM2840 Hauppauge)"; + dev->init_data.ir_codes = ir_codes_hauppauge_new; + dev->init_data.get_key = em28xx_get_key_em_haup; + dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; break; case (EM2820_BOARD_MSI_VOX_USB_2): break; @@ -2215,9 +2213,9 @@ break; } - if (init_data.name) - info.platform_data = &init_data; - i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); + if (dev->init_data.name) + dev->info.platform_data = &dev->init_data; + i2c_new_probed_device(&dev->i2c_adap, &dev->info, addr_list); } void em28xx_card_setup(struct em28xx *dev) --- linux-mvl-dove-2.6.31.orig/drivers/media/video/em28xx/em28xx.h +++ linux-mvl-dove-2.6.31/drivers/media/video/em28xx/em28xx.h @@ -595,6 +595,10 @@ struct delayed_work sbutton_query_work; struct em28xx_dvb *dvb; + + /* I2C keyboard data */ + struct i2c_board_info info; + struct IR_i2c_init_data init_data; }; struct em28xx_ops { --- linux-mvl-dove-2.6.31.orig/drivers/media/video/zc0301/zc0301_sensor.h +++ linux-mvl-dove-2.6.31/drivers/media/video/zc0301/zc0301_sensor.h @@ -62,7 +62,6 @@ #define ZC0301_ID_TABLE \ static const struct usb_device_id zc0301_id_table[] = { \ { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */ \ - { ZC0301_USB_DEVICE(0x0ac8, 0x303b, 0xff), }, /* PB-0330 */ \ { } \ }; #else --- linux-mvl-dove-2.6.31.orig/drivers/media/video/bt8xx/bttv-driver.c +++ linux-mvl-dove-2.6.31/drivers/media/video/bt8xx/bttv-driver.c @@ -1299,7 +1299,7 @@ tvnorm = &bttv_tvnorms[norm]; - if (!memcmp(&bttv_tvnorms[btv->tvnorm].cropcap, &tvnorm->cropcap, + if (memcmp(&bttv_tvnorms[btv->tvnorm].cropcap, &tvnorm->cropcap, sizeof (tvnorm->cropcap))) { bttv_crop_reset(&btv->crop[0], norm); btv->crop[1] = btv->crop[0]; /* current = default */ @@ -3798,11 +3798,34 @@ if (!V4L2_FIELD_HAS_BOTH(item->vb.field) && (item->vb.queue.next != &btv->capture)) { item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue); + /* Mike Isely - Only check + * and set up the bottom field in the logic + * below. Don't ever do the top field. This + * of course means that if we set up the + * bottom field in the above code that we'll + * actually skip a field. But that's OK. + * Having processed only a single buffer this + * time, then the next time around the first + * available buffer should be for a top field. + * That will then cause us here to set up a + * top then a bottom field in the normal way. + * The alternative to this understanding is + * that we set up the second available buffer + * as a top field, but that's out of order + * since this driver always processes the top + * field first - the effect will be the two + * buffers being returned in the wrong order, + * with the second buffer also being delayed + * by one field time (owing to the fifo nature + * of videobuf). Worse still, we'll be stuck + * doing fields out of order now every time + * until something else causes a field to be + * dropped. By effectively forcing a field to + * drop this way then we always get back into + * sync within a single frame time. (Out of + * order fields can screw up deinterlacing + * algorithms.) */ if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) { - if (NULL == set->top && - V4L2_FIELD_TOP == item->vb.field) { - set->top = item; - } if (NULL == set->bottom && V4L2_FIELD_BOTTOM == item->vb.field) { set->bottom = item; --- linux-mvl-dove-2.6.31.orig/drivers/media/video/uvc/uvc_driver.c +++ linux-mvl-dove-2.6.31/drivers/media/video/uvc/uvc_driver.c @@ -1983,6 +1983,15 @@ .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_MINMAX | UVC_QUIRK_IGNORE_SELECTOR_UNIT }, + /* COMPAL JHL90 */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x064e, + .idProduct = 0xa115, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_MINMAX }, /* Generic USB Video Class */ { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, {} --- linux-mvl-dove-2.6.31.orig/drivers/media/video/gspca/sonixj.c +++ linux-mvl-dove-2.6.31/drivers/media/video/gspca/sonixj.c @@ -727,7 +727,7 @@ {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10}, /* Outformat = rawRGB */ {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */ - {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10}, + {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10}, /* GAIN BLUE RED VREF */ {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10}, /* COM 1 BAVE GEAVE AECHH */ @@ -783,7 +783,7 @@ {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */ {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */ {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */ - {0xb1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10}, /****** (some exchanges in the win trace) ******/ {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */ /* bits[3..0]reserved */ @@ -1145,17 +1145,12 @@ reg_w1(gspca_dev, 0x01, 0x42); break; case SENSOR_OV7660: - reg_w1(gspca_dev, 0x01, 0x61); - reg_w1(gspca_dev, 0x17, 0x20); - reg_w1(gspca_dev, 0x01, 0x60); - reg_w1(gspca_dev, 0x01, 0x40); - break; case SENSOR_SP80708: reg_w1(gspca_dev, 0x01, 0x63); reg_w1(gspca_dev, 0x17, 0x20); reg_w1(gspca_dev, 0x01, 0x62); reg_w1(gspca_dev, 0x01, 0x42); - mdelay(100); + msleep(100); reg_w1(gspca_dev, 0x02, 0x62); break; /* case SENSOR_HV7131R: */ @@ -1624,6 +1619,8 @@ static void setinfrared(struct sd *sd) { + if (sd->gspca_dev.ctrl_dis & (1 << INFRARED_IDX)) + return; /*fixme: different sequence for StarCam Clip and StarCam 370i */ /* Clip */ i2c_w1(&sd->gspca_dev, 0x02, /* gpio */ @@ -1637,16 +1634,19 @@ if (gspca_dev->ctrl_dis & (1 << FREQ_IDX)) return; if (sd->sensor == SENSOR_OV7660) { + u8 com8; + + com8 = 0xdf; /* auto gain/wb/expo */ switch (sd->freq) { case 0: /* Banding filter disabled */ - i2c_w1(gspca_dev, 0x13, 0xdf); + i2c_w1(gspca_dev, 0x13, com8 | 0x20); break; case 1: /* 50 hz */ - i2c_w1(gspca_dev, 0x13, 0xff); + i2c_w1(gspca_dev, 0x13, com8); i2c_w1(gspca_dev, 0x3b, 0x0a); break; case 2: /* 60 hz */ - i2c_w1(gspca_dev, 0x13, 0xff); + i2c_w1(gspca_dev, 0x13, com8); i2c_w1(gspca_dev, 0x3b, 0x02); break; } @@ -1796,12 +1796,6 @@ reg_w1(gspca_dev, 0x99, 0x60); break; case SENSOR_OV7660: - reg_w1(gspca_dev, 0x9a, 0x05); - if (sd->bridge == BRIDGE_SN9C105) - reg_w1(gspca_dev, 0x99, 0xff); - else - reg_w1(gspca_dev, 0x99, 0x5b); - break; case SENSOR_SP80708: reg_w1(gspca_dev, 0x9a, 0x05); reg_w1(gspca_dev, 0x99, 0x59); @@ -2325,18 +2319,19 @@ {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)}, /* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */ {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)}, -/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */ +/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6802, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */ {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)}, /* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */ {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)}, - {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)}, #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE + {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)}, {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)}, #endif {USB_DEVICE(0x0c45, 0x6100), BSI(SN9C120, MI0360, 0x5d)}, /*sn9c128*/ -/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */ +/* {USB_DEVICE(0x0c45, 0x6102), BSI(SN9C120, PO2030N, ??)}, */ +/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6802, 0x21)}, */ {USB_DEVICE(0x0c45, 0x610a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c128*/ {USB_DEVICE(0x0c45, 0x610b), BSI(SN9C120, OV7660, 0x21)}, /*sn9c128*/ {USB_DEVICE(0x0c45, 0x610c), BSI(SN9C120, HV7131R, 0x11)}, /*sn9c128*/ @@ -2352,6 +2347,7 @@ #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)}, #endif +/* {USB_DEVICE(0x0c45, 0x6132), BSI(SN9C120, OV7670, 0x21)}, */ {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)}, {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x21)}, #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE @@ -2359,7 +2355,9 @@ #endif {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)}, {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x21)}, - {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)}, +/* {USB_DEVICE(0x0c45, 0x6142), BSI(SN9C120, PO2030N, ??)}, *sn9c120b*/ + {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)}, /*sn9c120b*/ + {USB_DEVICE(0x0c45, 0x6148), BSI(SN9C120, OM6802, 0x21)}, /*sn9c120b*/ {} }; MODULE_DEVICE_TABLE(usb, device_table); --- linux-mvl-dove-2.6.31.orig/drivers/media/video/gspca/ov519.c +++ linux-mvl-dove-2.6.31/drivers/media/video/gspca/ov519.c @@ -1056,6 +1056,8 @@ sd->gspca_dev.usb_buf, 1, 500); if (ret < 0) PDEBUG(D_ERR, "Write reg [%02x] %02x failed", index, value); + + msleep(1); return ret; } @@ -1076,6 +1078,8 @@ ret = sd->gspca_dev.usb_buf[0]; else PDEBUG(D_ERR, "Read reg [0x%02x] failed", index); + + msleep(1); return ret; } @@ -1095,6 +1099,8 @@ ret = sd->gspca_dev.usb_buf[0]; else PDEBUG(D_ERR, "Read reg 8 [0x%02x] failed", index); + + msleep(1); return ret; } @@ -1453,6 +1459,7 @@ if (i2c_r(sd, 0x00) < 0) return -EIO; } + PDEBUG(D_PROBE, "init_ov_sensor failed after %d attempt(s)", i); return -EIO; } @@ -3364,6 +3371,7 @@ {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4064), .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, + {USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x4068), .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, --- linux-mvl-dove-2.6.31.orig/drivers/media/video/gspca/vc032x.c +++ linux-mvl-dove-2.6.31/drivers/media/video/gspca/vc032x.c @@ -424,208 +424,92 @@ static const __u8 mi1310_socinitVGA_JPG[][4] = { {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc}, - {0xb3, 0x00, 0x24, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, - {0xb3, 0x05, 0x01, 0xcc}, - {0xb3, 0x06, 0x03, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, + {0xb3, 0x00, 0x64, 0xcc}, + {0xb3, 0x00, 0x65, 0xcc}, + {0xb3, 0x05, 0x00, 0xcc}, + {0xb3, 0x06, 0x00, 0xcc}, {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc}, {0xb3, 0x35, 0xdd, 0xcc}, + {0xb3, 0x02, 0x00, 0xcc}, {0xb3, 0x03, 0x0a, 0xcc}, - {0xb3, 0x04, 0x0d, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x01, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, + {0xb3, 0x22, 0x03, 0xcc}, + {0xb3, 0x23, 0xc0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x02, 0xcc}, - {0xb3, 0x17, 0x7f, 0xcc}, - {0xb8, 0x01, 0x7d, 0xcc}, - {0xb8, 0x81, 0x09, 0xcc}, - {0xb8, 0x27, 0x20, 0xcc}, - {0xb8, 0x26, 0x80, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, - {0xb8, 0x00, 0x13, 0xcc}, - {0xbc, 0x00, 0x71, 0xcc}, - {0xb8, 0x81, 0x01, 0xcc}, - {0xb8, 0x2c, 0x5a, 0xcc}, - {0xb8, 0x2d, 0xff, 0xcc}, - {0xb8, 0x2e, 0xee, 0xcc}, - {0xb8, 0x2f, 0xfb, 0xcc}, - {0xb8, 0x30, 0x52, 0xcc}, - {0xb8, 0x31, 0xf8, 0xcc}, - {0xb8, 0x32, 0xf1, 0xcc}, - {0xb8, 0x33, 0xff, 0xcc}, - {0xb8, 0x34, 0x54, 0xcc}, - {0xb8, 0x35, 0x00, 0xcc}, - {0xb8, 0x36, 0x00, 0xcc}, - {0xb8, 0x37, 0x00, 0xcc}, + {0xb3, 0x16, 0x04, 0xcc}, + {0xb3, 0x17, 0xff, 0xcc}, + {0xb3, 0x00, 0x65, 0xcc}, + {0xb8, 0x00, 0x00, 0xcc}, + {0xbc, 0x00, 0xd0, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, + {0xf0, 0x00, 0x02, 0xbb}, + {0xc8, 0x9f, 0x0b, 0xbb}, + {0x5b, 0x00, 0x01, 0xbb}, + {0x2f, 0xde, 0x20, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, - {0x00, 0x01, 0x00, 0xdd}, - {0x0d, 0x00, 0x09, 0xbb}, - {0x0d, 0x00, 0x08, 0xbb}, + {0x20, 0x03, 0x02, 0xbb}, {0xf0, 0x00, 0x01, 0xbb}, - {0x00, 0x01, 0x00, 0xdd}, - {0x06, 0x00, 0x14, 0xbb}, - {0x3a, 0x10, 0x00, 0xbb}, - {0x00, 0x00, 0x10, 0xdd}, - {0x9b, 0x10, 0x00, 0xbb}, - {0x00, 0x00, 0x10, 0xdd}, + {0x05, 0x00, 0x07, 0xbb}, + {0x34, 0x00, 0x00, 0xbb}, + {0x35, 0xff, 0x00, 0xbb}, + {0xdc, 0x07, 0x02, 0xbb}, + {0xdd, 0x3c, 0x18, 0xbb}, + {0xde, 0x92, 0x6d, 0xbb}, + {0xdf, 0xcd, 0xb1, 0xbb}, + {0xe0, 0xff, 0xe7, 0xbb}, + {0x06, 0xf0, 0x0d, 0xbb}, + {0x06, 0x70, 0x0e, 0xbb}, + {0x4c, 0x00, 0x01, 0xbb}, + {0x4d, 0x00, 0x01, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x2e, 0x0c, 0x55, 0xbb}, + {0x21, 0xb6, 0x6e, 0xbb}, + {0x36, 0x30, 0x10, 0xbb}, + {0x37, 0x00, 0xc1, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, - {0x00, 0x01, 0x00, 0xdd}, - {0x2b, 0x00, 0x28, 0xbb}, - {0x2c, 0x00, 0x30, 0xbb}, - {0x2d, 0x00, 0x30, 0xbb}, - {0x2e, 0x00, 0x28, 0xbb}, - {0x41, 0x00, 0xd7, 0xbb}, - {0x09, 0x02, 0x3a, 0xbb}, - {0x0c, 0x00, 0x00, 0xbb}, - {0x20, 0x00, 0x00, 0xbb}, - {0x05, 0x00, 0x8c, 0xbb}, - {0x06, 0x00, 0x32, 0xbb}, - {0x07, 0x00, 0xc6, 0xbb}, - {0x08, 0x00, 0x19, 0xbb}, - {0x24, 0x80, 0x6f, 0xbb}, - {0xc8, 0x00, 0x0f, 0xbb}, - {0x20, 0x00, 0x0f, 0xbb}, + {0x07, 0x00, 0x84, 0xbb}, + {0x08, 0x02, 0x4a, 0xbb}, + {0x05, 0x01, 0x10, 0xbb}, + {0x06, 0x00, 0x39, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x58, 0x02, 0x67, 0xbb}, + {0x57, 0x02, 0x00, 0xbb}, + {0x5a, 0x02, 0x67, 0xbb}, + {0x59, 0x02, 0x00, 0xbb}, + {0x5c, 0x12, 0x0d, 0xbb}, + {0x5d, 0x16, 0x11, 0xbb}, + {0x39, 0x06, 0x18, 0xbb}, + {0x3a, 0x06, 0x18, 0xbb}, + {0x3b, 0x06, 0x18, 0xbb}, + {0x3c, 0x06, 0x18, 0xbb}, + {0x64, 0x7b, 0x5b, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x36, 0x30, 0x10, 0xbb}, + {0x37, 0x00, 0xc0, 0xbb}, + {0xbc, 0x0e, 0x00, 0xcc}, + {0xbc, 0x0f, 0x05, 0xcc}, + {0xbc, 0x10, 0xc0, 0xcc}, + {0xbc, 0x11, 0x03, 0xcc}, {0xb6, 0x00, 0x00, 0xcc}, {0xb6, 0x03, 0x02, 0xcc}, {0xb6, 0x02, 0x80, 0xcc}, {0xb6, 0x05, 0x01, 0xcc}, {0xb6, 0x04, 0xe0, 0xcc}, - {0xb6, 0x12, 0x78, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb6, 0x13, 0x25, 0xcc}, {0xb6, 0x18, 0x02, 0xcc}, {0xb6, 0x17, 0x58, 0xcc}, {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc}, {0xb6, 0x23, 0x0b, 0xcc}, - {0xb3, 0x02, 0x02, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc}, {0xbf, 0xc1, 0x04, 0xcc}, - {0xbf, 0xcc, 0x10, 0xcc}, - {0xb9, 0x12, 0x00, 0xcc}, - {0xb9, 0x13, 0x0a, 0xcc}, - {0xb9, 0x14, 0x0a, 0xcc}, - {0xb9, 0x15, 0x0a, 0xcc}, - {0xb9, 0x16, 0x0a, 0xcc}, - {0xb9, 0x18, 0x00, 0xcc}, - {0xb9, 0x19, 0x0f, 0xcc}, - {0xb9, 0x1a, 0x0f, 0xcc}, - {0xb9, 0x1b, 0x0f, 0xcc}, - {0xb9, 0x1c, 0x0f, 0xcc}, - {0xb8, 0x8e, 0x00, 0xcc}, - {0xb8, 0x8f, 0xff, 0xcc}, - {0xb3, 0x01, 0x41, 0xcc}, - {0x03, 0x03, 0xc0, 0xbb}, - {0x06, 0x00, 0x10, 0xbb}, - {0xb6, 0x12, 0xf8, 0xcc}, - {0xb8, 0x0c, 0x20, 0xcc}, - {0xb8, 0x0d, 0x70, 0xcc}, - {0xb6, 0x13, 0x13, 0xcc}, - {0x2f, 0x00, 0xC0, 0xbb}, - {0xb8, 0xa0, 0x12, 0xcc}, - {}, -}; -static const __u8 mi1310_socinitQVGA_JPG[][4] = { - {0xb0, 0x03, 0x19, 0xcc}, - {0xb0, 0x04, 0x02, 0xcc}, - {0xb3, 0x00, 0x24, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, - {0xb3, 0x05, 0x01, 0xcc}, - {0xb3, 0x06, 0x03, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x34, 0x02, 0xcc}, - {0xb3, 0x35, 0xdd, 0xcc}, - {0xb3, 0x03, 0x0a, 0xcc}, - {0xb3, 0x04, 0x0d, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x01, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x02, 0xcc}, - {0xb3, 0x17, 0x7f, 0xcc}, - {0xb8, 0x01, 0x7d, 0xcc}, - {0xb8, 0x81, 0x09, 0xcc}, - {0xb8, 0x27, 0x20, 0xcc}, - {0xb8, 0x26, 0x80, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, - {0xb8, 0x00, 0x13, 0xcc}, - {0xbc, 0x00, 0xd1, 0xcc}, - {0xb8, 0x81, 0x01, 0xcc}, - {0xb8, 0x2c, 0x5a, 0xcc}, - {0xb8, 0x2d, 0xff, 0xcc}, - {0xb8, 0x2e, 0xee, 0xcc}, - {0xb8, 0x2f, 0xfb, 0xcc}, - {0xb8, 0x30, 0x52, 0xcc}, - {0xb8, 0x31, 0xf8, 0xcc}, - {0xb8, 0x32, 0xf1, 0xcc}, - {0xb8, 0x33, 0xff, 0xcc}, - {0xb8, 0x34, 0x54, 0xcc}, - {0xb8, 0x35, 0x00, 0xcc}, - {0xb8, 0x36, 0x00, 0xcc}, - {0xb8, 0x37, 0x00, 0xcc}, - {0xf0, 0x00, 0x00, 0xbb}, - {0x00, 0x01, 0x00, 0xdd}, - {0x0d, 0x00, 0x09, 0xbb}, - {0x0d, 0x00, 0x08, 0xbb}, - {0xf0, 0x00, 0x01, 0xbb}, - {0x00, 0x01, 0x00, 0xdd}, - {0x06, 0x00, 0x14, 0xbb}, - {0x3a, 0x10, 0x00, 0xbb}, - {0x00, 0x00, 0x10, 0xdd}, - {0x9b, 0x10, 0x00, 0xbb}, - {0x00, 0x00, 0x10, 0xdd}, - {0xf0, 0x00, 0x00, 0xbb}, - {0x00, 0x01, 0x00, 0xdd}, - {0x2b, 0x00, 0x28, 0xbb}, - {0x2c, 0x00, 0x30, 0xbb}, - {0x2d, 0x00, 0x30, 0xbb}, - {0x2e, 0x00, 0x28, 0xbb}, - {0x41, 0x00, 0xd7, 0xbb}, - {0x09, 0x02, 0x3a, 0xbb}, - {0x0c, 0x00, 0x00, 0xbb}, - {0x20, 0x00, 0x00, 0xbb}, - {0x05, 0x00, 0x8c, 0xbb}, - {0x06, 0x00, 0x32, 0xbb}, - {0x07, 0x00, 0xc6, 0xbb}, - {0x08, 0x00, 0x19, 0xbb}, - {0x24, 0x80, 0x6f, 0xbb}, - {0xc8, 0x00, 0x0f, 0xbb}, - {0x20, 0x00, 0x0f, 0xbb}, - {0xb6, 0x00, 0x00, 0xcc}, - {0xb6, 0x03, 0x01, 0xcc}, - {0xb6, 0x02, 0x40, 0xcc}, - {0xb6, 0x05, 0x00, 0xcc}, - {0xb6, 0x04, 0xf0, 0xcc}, - {0xb6, 0x12, 0x78, 0xcc}, - {0xb6, 0x18, 0x00, 0xcc}, - {0xb6, 0x17, 0x96, 0xcc}, - {0xb6, 0x16, 0x00, 0xcc}, - {0xb6, 0x22, 0x12, 0xcc}, - {0xb6, 0x23, 0x0b, 0xcc}, - {0xb3, 0x02, 0x02, 0xcc}, - {0xbf, 0xc0, 0x39, 0xcc}, - {0xbf, 0xc1, 0x04, 0xcc}, - {0xbf, 0xcc, 0x10, 0xcc}, - {0xb9, 0x12, 0x00, 0xcc}, - {0xb9, 0x13, 0x0a, 0xcc}, - {0xb9, 0x14, 0x0a, 0xcc}, - {0xb9, 0x15, 0x0a, 0xcc}, - {0xb9, 0x16, 0x0a, 0xcc}, - {0xb9, 0x18, 0x00, 0xcc}, - {0xb9, 0x19, 0x0f, 0xcc}, - {0xb9, 0x1a, 0x0f, 0xcc}, - {0xb9, 0x1b, 0x0f, 0xcc}, - {0xb9, 0x1c, 0x0f, 0xcc}, - {0xb8, 0x8e, 0x00, 0xcc}, - {0xb8, 0x8f, 0xff, 0xcc}, + {0xbf, 0xcc, 0x00, 0xcc}, {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc}, {0xbc, 0x04, 0x18, 0xcc}, @@ -636,15 +520,130 @@ {0xbc, 0x0a, 0x10, 0xcc}, {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x80, 0x00, 0x03, 0xbb}, + {0x81, 0xc7, 0x14, 0xbb}, + {0x82, 0xeb, 0xe8, 0xbb}, + {0x83, 0xfe, 0xf4, 0xbb}, + {0x84, 0xcd, 0x10, 0xbb}, + {0x85, 0xf3, 0xee, 0xbb}, + {0x86, 0xff, 0xf1, 0xbb}, + {0x87, 0xcd, 0x10, 0xbb}, + {0x88, 0xf3, 0xee, 0xbb}, + {0x89, 0x01, 0xf1, 0xbb}, + {0x8a, 0xe5, 0x17, 0xbb}, + {0x8b, 0xe8, 0xe2, 0xbb}, + {0x8c, 0xf7, 0xed, 0xbb}, + {0x8d, 0x00, 0xff, 0xbb}, + {0x8e, 0xec, 0x10, 0xbb}, + {0x8f, 0xf0, 0xed, 0xbb}, + {0x90, 0xf9, 0xf2, 0xbb}, + {0x91, 0x00, 0x00, 0xbb}, + {0x92, 0xe9, 0x0d, 0xbb}, + {0x93, 0xf4, 0xf2, 0xbb}, + {0x94, 0xfb, 0xf5, 0xbb}, + {0x95, 0x00, 0xff, 0xbb}, + {0xb6, 0x0f, 0x08, 0xbb}, + {0xb7, 0x3d, 0x16, 0xbb}, + {0xb8, 0x0c, 0x04, 0xbb}, + {0xb9, 0x1c, 0x07, 0xbb}, + {0xba, 0x0a, 0x03, 0xbb}, + {0xbb, 0x1b, 0x09, 0xbb}, + {0xbc, 0x17, 0x0d, 0xbb}, + {0xbd, 0x23, 0x1d, 0xbb}, + {0xbe, 0x00, 0x28, 0xbb}, + {0xbf, 0x11, 0x09, 0xbb}, + {0xc0, 0x16, 0x15, 0xbb}, + {0xc1, 0x00, 0x1b, 0xbb}, + {0xc2, 0x0e, 0x07, 0xbb}, + {0xc3, 0x14, 0x10, 0xbb}, + {0xc4, 0x00, 0x17, 0xbb}, + {0x06, 0x74, 0x8e, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x06, 0xf4, 0x8e, 0xbb}, + {0x00, 0x00, 0x50, 0xdd}, + {0x06, 0x74, 0x8e, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x24, 0x50, 0x20, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, + {0x34, 0x0c, 0x50, 0xbb}, {0xb3, 0x01, 0x41, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x03, 0x03, 0xc0, 0xbb}, + {}, +}; +static const __u8 mi1310_socinitQVGA_JPG[][4] = { + {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc}, + {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc}, + {0xb3, 0x05, 0x00, 0xcc}, {0xb3, 0x06, 0x00, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, {0xb3, 0x35, 0xdd, 0xcc}, + {0xb3, 0x02, 0x00, 0xcc}, {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x03, 0xcc}, + {0xb3, 0x23, 0xc0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, {0xb3, 0x16, 0x04, 0xcc}, + {0xb3, 0x17, 0xff, 0xcc}, {0xb3, 0x00, 0x65, 0xcc}, + {0xb8, 0x00, 0x00, 0xcc}, {0xbc, 0x00, 0xf0, 0xcc}, + {0xbc, 0x01, 0x01, 0xcc}, {0xf0, 0x00, 0x02, 0xbb}, + {0xc8, 0x9f, 0x0b, 0xbb}, {0x5b, 0x00, 0x01, 0xbb}, + {0x2f, 0xde, 0x20, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, + {0x20, 0x03, 0x02, 0xbb}, {0xf0, 0x00, 0x01, 0xbb}, + {0x05, 0x00, 0x07, 0xbb}, {0x34, 0x00, 0x00, 0xbb}, + {0x35, 0xff, 0x00, 0xbb}, {0xdc, 0x07, 0x02, 0xbb}, + {0xdd, 0x3c, 0x18, 0xbb}, {0xde, 0x92, 0x6d, 0xbb}, + {0xdf, 0xcd, 0xb1, 0xbb}, {0xe0, 0xff, 0xe7, 0xbb}, + {0x06, 0xf0, 0x0d, 0xbb}, {0x06, 0x70, 0x0e, 0xbb}, + {0x4c, 0x00, 0x01, 0xbb}, {0x4d, 0x00, 0x01, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, {0x2e, 0x0c, 0x55, 0xbb}, + {0x21, 0xb6, 0x6e, 0xbb}, {0x36, 0x30, 0x10, 0xbb}, + {0x37, 0x00, 0xc1, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, + {0x07, 0x00, 0x84, 0xbb}, {0x08, 0x02, 0x4a, 0xbb}, + {0x05, 0x01, 0x10, 0xbb}, {0x06, 0x00, 0x39, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, {0x58, 0x02, 0x67, 0xbb}, + {0x57, 0x02, 0x00, 0xbb}, {0x5a, 0x02, 0x67, 0xbb}, + {0x59, 0x02, 0x00, 0xbb}, {0x5c, 0x12, 0x0d, 0xbb}, + {0x5d, 0x16, 0x11, 0xbb}, {0x39, 0x06, 0x18, 0xbb}, + {0x3a, 0x06, 0x18, 0xbb}, {0x3b, 0x06, 0x18, 0xbb}, + {0x3c, 0x06, 0x18, 0xbb}, {0x64, 0x7b, 0x5b, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, {0x36, 0x30, 0x10, 0xbb}, + {0x37, 0x00, 0xc0, 0xbb}, {0xbc, 0x0e, 0x00, 0xcc}, + {0xbc, 0x0f, 0x05, 0xcc}, {0xbc, 0x10, 0xc0, 0xcc}, + {0xbc, 0x11, 0x03, 0xcc}, {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x01, 0xcc}, {0xb6, 0x02, 0x40, 0xcc}, + {0xb6, 0x05, 0x00, 0xcc}, {0xb6, 0x04, 0xf0, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x25, 0xcc}, + {0xb6, 0x18, 0x00, 0xcc}, {0xb6, 0x17, 0x96, 0xcc}, + {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, {0xbf, 0xcc, 0x00, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, {0xf0, 0x00, 0x01, 0xbb}, + {0x80, 0x00, 0x03, 0xbb}, {0x81, 0xc7, 0x14, 0xbb}, + {0x82, 0xeb, 0xe8, 0xbb}, {0x83, 0xfe, 0xf4, 0xbb}, + {0x84, 0xcd, 0x10, 0xbb}, {0x85, 0xf3, 0xee, 0xbb}, + {0x86, 0xff, 0xf1, 0xbb}, {0x87, 0xcd, 0x10, 0xbb}, + {0x88, 0xf3, 0xee, 0xbb}, {0x89, 0x01, 0xf1, 0xbb}, + {0x8a, 0xe5, 0x17, 0xbb}, {0x8b, 0xe8, 0xe2, 0xbb}, + {0x8c, 0xf7, 0xed, 0xbb}, {0x8d, 0x00, 0xff, 0xbb}, + {0x8e, 0xec, 0x10, 0xbb}, {0x8f, 0xf0, 0xed, 0xbb}, + {0x90, 0xf9, 0xf2, 0xbb}, {0x91, 0x00, 0x00, 0xbb}, + {0x92, 0xe9, 0x0d, 0xbb}, {0x93, 0xf4, 0xf2, 0xbb}, + {0x94, 0xfb, 0xf5, 0xbb}, {0x95, 0x00, 0xff, 0xbb}, + {0xb6, 0x0f, 0x08, 0xbb}, {0xb7, 0x3d, 0x16, 0xbb}, + {0xb8, 0x0c, 0x04, 0xbb}, {0xb9, 0x1c, 0x07, 0xbb}, + {0xba, 0x0a, 0x03, 0xbb}, {0xbb, 0x1b, 0x09, 0xbb}, + {0xbc, 0x17, 0x0d, 0xbb}, {0xbd, 0x23, 0x1d, 0xbb}, + {0xbe, 0x00, 0x28, 0xbb}, {0xbf, 0x11, 0x09, 0xbb}, + {0xc0, 0x16, 0x15, 0xbb}, {0xc1, 0x00, 0x1b, 0xbb}, + {0xc2, 0x0e, 0x07, 0xbb}, {0xc3, 0x14, 0x10, 0xbb}, + {0xc4, 0x00, 0x17, 0xbb}, {0x06, 0x74, 0x8e, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, {0x06, 0xf4, 0x8e, 0xbb}, + {0x00, 0x00, 0x50, 0xdd}, {0x06, 0x74, 0x8e, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, {0x24, 0x50, 0x20, 0xbb}, + {0xf0, 0x00, 0x02, 0xbb}, {0x34, 0x0c, 0x50, 0xbb}, + {0xb3, 0x01, 0x41, 0xcc}, {0xf0, 0x00, 0x00, 0xbb}, {0x03, 0x03, 0xc0, 0xbb}, - {0x06, 0x00, 0x10, 0xbb}, - {0xb6, 0x12, 0xf8, 0xcc}, - {0xb8, 0x0c, 0x20, 0xcc}, - {0xb8, 0x0d, 0x70, 0xcc}, - {0xb6, 0x13, 0x13, 0xcc}, - {0x2f, 0x00, 0xC0, 0xbb}, - {0xb8, 0xa0, 0x12, 0xcc}, {}, }; static const u8 mi1310_soc_InitSXGA_JPG[][4] = { @@ -2514,7 +2513,8 @@ break; case SENSOR_MI1310_SOC: cam->cam_mode = vc0323_mode; - cam->nmodes = ARRAY_SIZE(vc0323_mode); + /* TODO: 1280x1024 resolution setting is incorrect, so don't export it now*/ + cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1; break; case SENSOR_MI1320_SOC: cam->cam_mode = bi_mode; @@ -2737,15 +2737,20 @@ put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c); /* set the led on 0x0892 0x0896 */ - if (sd->sensor != SENSOR_PO1200) { - reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); + if (sd->sensor == SENSOR_PO1200) { + setsharpness(gspca_dev); + sethvflip(gspca_dev); + reg_w(gspca_dev->dev, 0x89, 0x0400, 0x1415); + } else if (sd->sensor == SENSOR_MI1310_SOC) { + reg_w(gspca_dev->dev, 0x89, 0x058c, 0x0000); msleep(100); sethvflip(gspca_dev); setlightfreq(gspca_dev); } else { - setsharpness(gspca_dev); + reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); + msleep(100); sethvflip(gspca_dev); - reg_w(gspca_dev->dev, 0x89, 0x0400, 0x1415); + setlightfreq(gspca_dev); } } return 0; @@ -2754,8 +2759,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev) { struct usb_device *dev = gspca_dev->dev; + struct sd *sd = (struct sd *) gspca_dev; - reg_w(dev, 0x89, 0xffff, 0xffff); + if( sd->sensor == SENSOR_MI1310_SOC) + reg_w(dev, 0x89, 0x058c, 0x00ff); + else + reg_w(dev, 0x89, 0xffff, 0xffff); reg_w(dev, 0xa0, 0x01, 0xb301); reg_w(dev, 0xa0, 0x09, 0xb003); } @@ -2764,10 +2773,14 @@ static void sd_stop0(struct gspca_dev *gspca_dev) { struct usb_device *dev = gspca_dev->dev; + struct sd *sd = (struct sd *) gspca_dev; if (!gspca_dev->present) return; - reg_w(dev, 0x89, 0xffff, 0xffff); + if( sd->sensor == SENSOR_MI1310_SOC) + reg_w(dev, 0x89, 0x058c, 0x00ff); + else + reg_w(dev, 0x89, 0xffff, 0xffff); } static void sd_pkt_scan(struct gspca_dev *gspca_dev, --- linux-mvl-dove-2.6.31.orig/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ linux-mvl-dove-2.6.31/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -35,12 +35,25 @@ const struct dmi_system_id s5k4aa_vflip_dmi_table[] = { { + .ident = "BRUNEINIT", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "BRUNENIT"), + DMI_MATCH(DMI_PRODUCT_NAME, "BRUNENIT"), + DMI_MATCH(DMI_BOARD_VERSION, "00030D0000000001") + } + }, { .ident = "Fujitsu-Siemens Amilo Xa 2528", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528") } }, { + .ident = "Fujitsu-Siemens Amilo Xi 2528", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2528") + } + }, { .ident = "Fujitsu-Siemens Amilo Xi 2550", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), @@ -51,6 +64,13 @@ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), DMI_MATCH(DMI_PRODUCT_NAME, "GX700"), + DMI_MATCH(DMI_BIOS_DATE, "12/02/2008") + } + }, { + .ident = "MSI GX700", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), + DMI_MATCH(DMI_PRODUCT_NAME, "GX700"), DMI_MATCH(DMI_BIOS_DATE, "07/26/2007") } }, { --- linux-mvl-dove-2.6.31.orig/drivers/media/video/sn9c102/sn9c102_devtable.h +++ linux-mvl-dove-2.6.31/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -123,8 +123,8 @@ { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), }, #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), }, -#endif { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), }, +#endif { } }; --- linux-mvl-dove-2.6.31.orig/drivers/media/dvb/siano/smsusb.c +++ linux-mvl-dove-2.6.31/drivers/media/dvb/siano/smsusb.c @@ -529,6 +529,12 @@ .driver_info = SMS1XXX_BOARD_SIANO_NICE }, { USB_DEVICE(0x187f, 0x0301), .driver_info = SMS1XXX_BOARD_SIANO_VENICE }, + { USB_DEVICE(0x2040, 0xb900), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0xb910), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0xc000), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, { } /* Terminating entry */ }; --- linux-mvl-dove-2.6.31.orig/drivers/media/dvb/frontends/dib7000p.c +++ linux-mvl-dove-2.6.31/drivers/media/dvb/frontends/dib7000p.c @@ -1344,6 +1344,11 @@ if (dib7000p_identify(st) != 0) goto error; + /* FIXME: make sure the dev.parent field is initialized, or else + request_firmware() will hit an OOPS (this should be moved somewhere + more common) */ + st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent; + dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr); dib7000p_demod_reset(st); --- linux-mvl-dove-2.6.31.orig/drivers/media/dvb/dvb-usb/cinergyT2-fe.c +++ linux-mvl-dove-2.6.31/drivers/media/dvb/dvb-usb/cinergyT2-fe.c @@ -275,6 +275,7 @@ param.tps = cpu_to_le16(compute_tps(fep)); param.freq = cpu_to_le32(fep->frequency / 1000); param.bandwidth = 8 - fep->u.ofdm.bandwidth - BANDWIDTH_8_MHZ; + param.flags = 0; err = dvb_usb_generic_rw(state->d, (char *)¶m, sizeof(param), --- linux-mvl-dove-2.6.31.orig/drivers/media/dvb/dvb-usb/cxusb.c +++ linux-mvl-dove-2.6.31/drivers/media/dvb/dvb-usb/cxusb.c @@ -663,6 +663,14 @@ .parallel_ts = 1, }; +static struct zl10353_config cxusb_zl10353_xc3028_config_no_i2c_gate = { + .demod_address = 0x0f, + .if2 = 45600, + .no_tuner = 1, + .parallel_ts = 1, + .disable_i2c_gate_ctrl = 1, +}; + static struct mt352_config cxusb_mt352_xc3028_config = { .demod_address = 0x0f, .if2 = 4560, @@ -894,7 +902,7 @@ cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); if ((adap->fe = dvb_attach(zl10353_attach, - &cxusb_zl10353_xc3028_config, + &cxusb_zl10353_xc3028_config_no_i2c_gate, &adap->dev->i2c_adap)) == NULL) return -EIO; --- linux-mvl-dove-2.6.31.orig/drivers/media/dvb/dvb-core/dvb_net.c +++ linux-mvl-dove-2.6.31/drivers/media/dvb/dvb-core/dvb_net.c @@ -503,6 +503,7 @@ "bytes left in TS. Resyncing.\n", ts_remain); priv->ule_sndu_len = 0; priv->need_pusi = 1; + ts += TS_SZ; continue; } --- linux-mvl-dove-2.6.31.orig/drivers/media/radio/radio-gemtek-pci.c +++ linux-mvl-dove-2.6.31/drivers/media/radio/radio-gemtek-pci.c @@ -181,12 +181,10 @@ static void gemtek_pci_unmute(struct gemtek_pci *card) { - mutex_lock(&card->lock); if (card->mute) { gemtek_pci_setfrequency(card, card->current_frequency); card->mute = false; } - mutex_unlock(&card->lock); } static int gemtek_pci_getsignal(struct gemtek_pci *card) --- linux-mvl-dove-2.6.31.orig/drivers/char/ds2782.c +++ linux-mvl-dove-2.6.31/drivers/char/ds2782.c @@ -0,0 +1,119 @@ +/* + * + * Marvell Fuel Gauge IC driver + * Maxim DS2782 Fuel Gauge IC + * + * Author: + * Copyright (C) 2008 Marvell Ltd. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include "ds2782.h" + +static struct i2c_driver ds2782_i2c_driver; +static struct i2c_client *ds2782_i2c_client; +static struct i2c_client *get_ds2782_i2c_client(void); + +int ds2782_reg_get(int offset, unsigned char *pDataBuf, int datasize) +{ + int rc; + struct i2c_client *i2c_client; + + if((i2c_client = get_ds2782_i2c_client())) + { + rc = i2c_smbus_read_i2c_block_data(i2c_client, offset, datasize, pDataBuf); + if (rc < 0) + return -EIO; + }else{ + return -ENODEV; + } + return 0; +} +EXPORT_SYMBOL(ds2782_reg_get); + +int ds2782_reg_set(int offset, unsigned char data) +{ + struct i2c_client *i2c_client; + + if((i2c_client = get_ds2782_i2c_client())) + { + i2c_smbus_write_byte_data(i2c_client, offset, data); + + }else{ + return -ENODEV; + } + return 0; +} +EXPORT_SYMBOL(ds2782_reg_set); + +static struct i2c_client *get_ds2782_i2c_client(void) +{ + return ds2782_i2c_client; +} + + +static int ds2782_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int rc; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_I2C_BLOCK)) { + dev_err(&client->dev, "i2c bus does not support the ds2782\n"); + rc = -ENODEV; + goto exit; + } + + ds2782_i2c_client = client; + return 0; + + exit: + return rc; +} + +static int ds2782_remove(struct i2c_client *client) +{ + ds2782_i2c_client = NULL; + return 0; +} + + + +static const struct i2c_device_id ds2782_id[] = { + { "ds2782", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ds2782_id); + +static struct i2c_driver ds2782_i2c_driver = { + .driver = { + .name = "ds2782", + }, + .probe = ds2782_probe, + .remove = ds2782_remove, + .id_table = ds2782_id, +}; + + + +static int __init ds2782_init(void) +{ + return i2c_add_driver(&ds2782_i2c_driver); +} + +static void __exit ds2782_exit(void) +{ + i2c_del_driver(&ds2782_i2c_driver); +} + + +module_init(ds2782_init); +module_exit(ds2782_exit); + + --- linux-mvl-dove-2.6.31.orig/drivers/char/vt_ioctl.c +++ linux-mvl-dove-2.6.31/drivers/char/vt_ioctl.c @@ -36,6 +36,8 @@ #include #include +#define max_font_size 65536 + char vt_dont_switch; extern struct tty_driver *console_driver; @@ -1262,6 +1264,7 @@ static void complete_change_console(struct vc_data *vc) { unsigned char old_vc_mode; + struct vc_data *oldvc = vc_cons[fg_console].d; last_console = fg_console; @@ -1270,9 +1273,31 @@ * KD_TEXT mode or vice versa, which means we need to blank or * unblank the screen later. */ - old_vc_mode = vc_cons[fg_console].d->vc_mode; + old_vc_mode = oldvc->vc_mode; + +#if defined(CONFIG_VGA_CONSOLE) + if (old_vc_mode == KD_TEXT && oldvc->vc_sw == &vga_con && + oldvc->vc_sw->con_font_get) { + if (!oldvc->vc_font.data) + oldvc->vc_font.data = kmalloc(max_font_size, + GFP_KERNEL); + lock_kernel(); + oldvc->vc_sw->con_font_get(oldvc, &oldvc->vc_font); + unlock_kernel(); + } +#endif switch_screen(vc); +#if defined(CONFIG_VGA_CONSOLE) + if (vc->vc_mode == KD_TEXT && vc->vc_sw == &vga_con && + vc->vc_sw->con_font_set) { + if (vc->vc_font.data) { + lock_kernel(); + vc->vc_sw->con_font_set(vc, &vc->vc_font, 0); + unlock_kernel(); + } + } +#endif /* * This can't appear below a successful kill_pid(). If it did, * then the *blank_screen operation could occur while X, having --- linux-mvl-dove-2.6.31.orig/drivers/char/apm-emulation.c +++ linux-mvl-dove-2.6.31/drivers/char/apm-emulation.c @@ -20,9 +20,8 @@ #include #include #include -#include +#include #include -#include #include #include #include @@ -30,9 +29,14 @@ #include #include #include - +#include +#include #include +#if CONFIG_APM_EMU_DS2782 +#include "ds2782.h" +#endif + /* * The apm_bios device is one of the misc char devices. * This is its minor number. @@ -153,14 +157,175 @@ static const char driver_version[] = "1.13"; /* no spaces */ - - /* * Compatibility cruft until the IPAQ people move over to the new * interface. */ static void __apm_get_power_status(struct apm_power_info *info) { +#if CONFIG_APM_EMU_DS2782 + unsigned char data; + unsigned char data2; + unsigned short regValue; + unsigned char status; +// unsigned short vol; + unsigned short curt; + +// ds2782_reg_get(0x7e, &data, 1); + +// printk("=========================================\n"); +// printk("DS2782 addr: %#x\n", data >> 1); + + ds2782_reg_get(DS2782_STATUS_REG, &status, 1); +// printk("DS2782 Status Reg: %#x \n", status); + +// ds2782_reg_get(DS2782_VOLT_REG, &data, 1); +// ds2782_reg_get(DS2782_VOLT_REG+1, &data2, 1); +// vol = ((data << 8) | data2) >> DS2782_VOLT_SHIFT_BIT; +// printk("DS2782 Voltage: %#x * 4.88m V\n", vol); + +// ds2782_reg_get(DS2782_TEMP_REG, &data, 1); +// ds2782_reg_get(DS2782_TEMP_REG+1, &data2, 1); +// regValue = ((data << 8) | data2) >> DS2782_TEMP_SHIFT_BIT; +// printk("DS2782 Temperature: %#x * 0.125 C\n", regValue); + + ds2782_reg_get(DS2782_CURRENT_REG, &data, 1); + ds2782_reg_get(DS2782_CURRENT_REG+1, &data2, 1); + curt = ((data << 8) | data2) >> DS2782_CURRENT_SHIFT_BIT; +// printk("DS2782 Current: %#x * 156.3u A\n", curt); + + //if(curt > 0x10 && curt < 0x4000) + if(curt > 0xb000) + info->ac_line_status = APM_AC_OFFLINE; + else + info->ac_line_status = APM_AC_ONLINE; +// printk("ac line status: 0x%x\n", info->ac_line_status); + +// ds2782_reg_get(DS2782_ACR_REG, &data, 1); +// ds2782_reg_get(DS2782_ACR_REG+1, &data2, 1); +// regValue = ((data << 8) | data2) >> DS2782_ACR_SHIFT_BIT; +// printk("DS2782 Accumulated Current(ACR): %#x * 625u Ahr\n", regValue); + +// ds2782_reg_get(DS2782_IAVG_REG, &data, 1); +// ds2782_reg_get(DS2782_IAVG_REG+1, &data2, 1); +// regValue = ((data << 8) | data2) >> DS2782_IAVG_SHIFT_BIT; +// printk("DS2782 Average Current(IAVG): %#x * 156.25u A\n", regValue); + +// ds2782_reg_get(DS2782_AC_REG, &data, 1); +// ds2782_reg_get(DS2782_AC_REG+1, &data2, 1); +// regValue = ((data << 8) | data2) >> DS2782_AC_SHIFT_BIT; +// printk("DS2782 Aging Cap(AC): (%#x * 6.25)/RSNSP(mOhm) mAhr\n", regValue); + +// ds2782_reg_get(DS2782_AS_REG, &data, 1); +// printk("DS2782 Age Scalar(AS): %#x * 0.78 %\n", data); + +// ds2782_reg_get(DS2782_RSNSP_REG, &data, 1); +// printk("DS2782 Sense Resistor(RSNSP): 1 / %#x Ohm\n", data); + +// ds2782_reg_get(DS2782_VCHG_REG, &data, 1); +// printk("DS2782 Charge Voltage(VCHG): %#x * 19.52m V\n", data); + +// ds2782_reg_get(DS2782_IMIN_REG, &data, 1); +// printk("DS2782 Min Chg Current(IMIN): (%#x * 50)/RSNSP(mOhm) mA\n", data); + +// ds2782_reg_get(DS2782_VAE_REG, &data, 1); +// printk("DS2782 Active Empty Voltage(VAE): %#x * 19.52m V\n", data); + +// ds2782_reg_get(DS2782_IAE_REG, &data, 1); +// printk("DS2782 Active Empty Current(IAE): (%#x * 200)/RSNSP(mOhm) mA\n", data); + +// ds2782_reg_get(DS2782_FULL40_REG, &data, 1); +// ds2782_reg_get(DS2782_FULL40_REG+1, &data2, 1); +// regValue = ((data << 8) | data2) >> DS2782_FULL40_SHIFT_BIT; +// printk("DS2782 FULL(40): (%#x * 6.25)/RSNSP(mOhm) mAhr\n", regValue); + +// ds2782_reg_get(DS2782_FULL_REG, &data, 1); +// ds2782_reg_get(DS2782_FULL_REG+1, &data2, 1); +// regValue = ((data << 8) | data2) >> DS2782_FULL_SHIFT_BIT; +// printk("DS2782 FULL(T): %#x ??? mAhr\n", regValue); + +// ds2782_reg_get(DS2782_AE_REG, &data, 1); +// ds2782_reg_get(DS2782_AE_REG+1, &data2, 1); +// regValue = ((data << 8) | data2) >> DS2782_AE_SHIFT_BIT; +// printk("DS2782 Active Empty AE(T): %#x ??? mAhr\n", regValue); + +// ds2782_reg_get(DS2782_SE_REG, &data, 1); +// ds2782_reg_get(DS2782_SE_REG+1, &data2, 1); +// regValue = ((data << 8) | data2) >> DS2782_SE_SHIFT_BIT; +// printk("DS2782 Standby Empty SE(T): %#x ??? mAhr\n", regValue); + +// ds2782_reg_get(DS2782_RAAC_REG, &data, 1); +// ds2782_reg_get(DS2782_RAAC_REG+1, &data2, 1); +// regValue = ((data << 8) | data2) >> DS2782_RAAC_SHIFT_BIT; +// printk("DS2782 Remaining Active Absolute Capacity (RAAC): %#x ??? mAhr\n", regValue); + +// ds2782_reg_get(DS2782_RSAC_REG, &data, 1); +// ds2782_reg_get(DS2782_RSAC_REG+1, &data2, 1); +// regValue = ((data << 8) | data2) >> DS2782_RSAC_SHIFT_BIT; +// printk("DS2782 Remaining Standby Absolute Capacity (RSAC): %#x ??? mAhr\n", regValue); + + ds2782_reg_get(DS2782_RARC_REG, &data, 1); +// printk("DS2782 Remaining Active Relative Capacity (RARC): %#x %\n", data); + info->battery_life = data; + + if(info->battery_life > 0x1e) { // 30% + if(info->ac_line_status == APM_AC_ONLINE) { + if(status & 0x80) { // charge terminate flag + info->battery_status = APM_BATTERY_STATUS_HIGH; + info->battery_flag = APM_BATTERY_FLAG_HIGH; + } else { + info->battery_status = APM_BATTERY_STATUS_CHARGING; + info->battery_flag = APM_BATTERY_FLAG_CHARGING; + } + } else { + info->battery_status = APM_BATTERY_STATUS_HIGH; + info->battery_flag = APM_BATTERY_FLAG_HIGH; + } + } else if((info->battery_life <= 0x1e)&& (info->battery_life > 0xf)) { // 15% ~ 30% + if(info->ac_line_status == APM_AC_ONLINE) { + if(status & 0x80) { // charge terminate flag + info->battery_status = APM_BATTERY_STATUS_LOW; + info->battery_flag = APM_BATTERY_FLAG_LOW; + } else { + info->battery_status = APM_BATTERY_STATUS_CHARGING; + info->battery_flag = APM_BATTERY_FLAG_CHARGING; + } + } else { + info->battery_status = APM_BATTERY_STATUS_LOW; + info->battery_flag = APM_BATTERY_FLAG_LOW; + } + } else if(info->battery_life <= 0xf) { // 0 ~ 15% + if(info->ac_line_status == APM_AC_ONLINE) { + if(status & 0x80) { // charge terminate flag + info->battery_status = APM_BATTERY_STATUS_CRITICAL; + info->battery_flag = APM_BATTERY_FLAG_CRITICAL; + } else { + info->battery_status = APM_BATTERY_STATUS_CHARGING; + info->battery_flag = APM_BATTERY_FLAG_CHARGING; + } + } else { + info->battery_status = APM_BATTERY_STATUS_CRITICAL; + info->battery_flag = APM_BATTERY_FLAG_CRITICAL; + } + } + +// if(status & 0x4) +// ds2782_reg_set(DS2782_STATUS_REG, ~0x4); +// if(status & 0x2) +// ds2782_reg_set(DS2782_STATUS_REG, ~0x2); +// printk("battery status: 0x%x\n", info->battery_status); +// printk("battery flag: 0x%x\n", info->battery_flag); + + ds2782_reg_get(DS2782_RAAC_REG, &data, 1); + ds2782_reg_get(DS2782_RAAC_REG+1, &data2, 1); + regValue = ((data << 8) | data2) >> DS2782_RAAC_SHIFT_BIT; + + info->units = APM_UNITS_MINS; + info->time = (regValue * 10) / 670 * 6; // Time = RAAC(mAhr) / 670m * 60min + +// ds2782_reg_get(DS2782_RSRC_REG, &data, 1); +// printk("DS2782 Remaining Standby Relative Capacity (RSRC): %#x %\n", data); +#endif } /* @@ -269,6 +434,7 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) { struct apm_user *as = filp->private_data; + unsigned long flags; int err = -EINVAL; if (!as->suser || !as->writer) @@ -300,8 +466,13 @@ /* * Wait for the suspend/resume to complete. If there * are pending acknowledges, we wait here for them. + * + * Note: we need to ensure that the PM subsystem does + * not kick us out of the wait when it suspends the + * threads. */ - freezer_do_not_count(); + flags = current->flags; + current->flags |= PF_NOFREEZE; wait_event(apm_suspend_waitqueue, as->suspend_state == SUSPEND_DONE); @@ -328,6 +499,8 @@ as->suspend_result = pm_suspend(PM_SUSPEND_MEM); } + current->flags = flags; + mutex_lock(&state_lock); err = as->suspend_result; as->suspend_state = SUSPEND_NONE; @@ -448,10 +621,11 @@ * -1: Unknown * 8) min = minutes; sec = seconds */ -static int proc_apm_show(struct seq_file *m, void *v) +static int apm_get_info(char *buf, char **start, off_t fpos, int length) { struct apm_power_info info; char *units; + int ret; info.ac_line_status = 0xff; info.battery_status = 0xff; @@ -469,27 +643,14 @@ case 1: units = "sec"; break; } - seq_printf(m, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n", + ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n", driver_version, APM_32_BIT_SUPPORT, info.ac_line_status, info.battery_status, info.battery_flag, info.battery_life, info.time, units); - return 0; -} - -static int proc_apm_open(struct inode *inode, struct file *file) -{ - return single_open(file, proc_apm_show, NULL); + return ret; } - -static const struct file_operations apm_proc_fops = { - .owner = THIS_MODULE, - .open = proc_apm_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; #endif static int kapmd(void *arg) @@ -651,6 +812,9 @@ static int __init apm_init(void) { int ret; +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *ent; +#endif if (apm_disabled) { printk(KERN_NOTICE "apm: disabled on user request.\n"); @@ -663,15 +827,23 @@ kapmd_tsk = NULL; goto out; } + kapmd_tsk->flags |= PF_NOFREEZE; wake_up_process(kapmd_tsk); #ifdef CONFIG_PROC_FS - proc_create("apm", 0, NULL, &apm_proc_fops); +// create_proc_info_entry("apm", 0, NULL, apm_get_info); + ent = create_proc_entry("apm", 0, NULL); + if (ent) + ent->read_proc = apm_get_info; #endif ret = misc_register(&apm_device); - if (ret) + if (ret){ +#ifdef CONFIG_PROC_FS + remove_proc_entry("apm", NULL); +#endif goto out_stop; + } ret = register_pm_notifier(&apm_notif_block); if (ret) @@ -692,8 +864,9 @@ { unregister_pm_notifier(&apm_notif_block); misc_deregister(&apm_device); +#ifdef CONFIG_PROC_FS remove_proc_entry("apm", NULL); - +#endif kthread_stop(kapmd_tsk); } --- linux-mvl-dove-2.6.31.orig/drivers/char/tty_ldisc.c +++ linux-mvl-dove-2.6.31/drivers/char/tty_ldisc.c @@ -516,7 +516,7 @@ static int tty_ldisc_halt(struct tty_struct *tty) { clear_bit(TTY_LDISC, &tty->flags); - return cancel_delayed_work(&tty->buf.work); + return cancel_delayed_work_sync(&tty->buf.work); } /** @@ -754,12 +754,9 @@ * N_TTY. */ if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { - /* Make sure the old ldisc is quiescent */ - tty_ldisc_halt(tty); - flush_scheduled_work(); - /* Avoid racing set_ldisc or tty_ldisc_release */ mutex_lock(&tty->ldisc_mutex); + tty_ldisc_halt(tty); if (tty->ldisc) { /* Not yet closed */ /* Switch back to N_TTY */ tty_ldisc_reinit(tty); --- linux-mvl-dove-2.6.31.orig/drivers/char/pty.c +++ linux-mvl-dove-2.6.31/drivers/char/pty.c @@ -120,8 +120,10 @@ /* Stuff the data into the input queue of the other end */ c = tty_insert_flip_string(to, buf, c); /* And shovel */ - tty_flip_buffer_push(to); - tty_wakeup(tty); + if (c) { + tty_flip_buffer_push(to); + tty_wakeup(tty); + } } return c; } --- linux-mvl-dove-2.6.31.orig/drivers/char/hvc_xen.c +++ linux-mvl-dove-2.6.31/drivers/char/hvc_xen.c @@ -55,7 +55,7 @@ notify_remote_via_evtchn(xen_start_info->console.domU.evtchn); } -static int write_console(uint32_t vtermno, const char *data, int len) +static int __write_console(const char *data, int len) { struct xencons_interface *intf = xencons_interface(); XENCONS_RING_IDX cons, prod; @@ -76,6 +76,29 @@ return sent; } +static int write_console(uint32_t vtermno, const char *data, int len) +{ + int ret = len; + + /* + * Make sure the whole buffer is emitted, polling if + * necessary. We don't ever want to rely on the hvc daemon + * because the most interesting console output is when the + * kernel is crippled. + */ + while (len) { + int sent = __write_console(data, len); + + data += sent; + len -= sent; + + if (unlikely(len)) + HYPERVISOR_sched_op(SCHEDOP_yield, NULL); + } + + return ret; +} + static int read_console(uint32_t vtermno, char *buf, int len) { struct xencons_interface *intf = xencons_interface(); --- linux-mvl-dove-2.6.31.orig/drivers/char/keyboard.c +++ linux-mvl-dove-2.6.31/drivers/char/keyboard.c @@ -1068,6 +1068,8 @@ int code; switch (keycode) { + case KEY_RESERVED: + break; case KEY_PAUSE: put_queue(vc, 0xe1); put_queue(vc, 0x1d | up_flag); @@ -1125,6 +1127,8 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag) { + if (keycode == KEY_RESERVED) + return 0; if (keycode > 127) return -1; @@ -1249,7 +1253,7 @@ if (keycode >= NR_KEYS) if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8) - keysym = K(KT_BRL, keycode - KEY_BRL_DOT1 + 1); + keysym = U(K(KT_BRL, keycode - KEY_BRL_DOT1 + 1)); else return; else --- linux-mvl-dove-2.6.31.orig/drivers/char/n_tty.c +++ linux-mvl-dove-2.6.31/drivers/char/n_tty.c @@ -272,7 +272,8 @@ * * This is a helper function that handles one output character * (including special characters like TAB, CR, LF, etc.), - * putting the results in the tty driver's write buffer. + * doing OPOST processing and putting the results in the + * tty driver's write buffer. * * Note that Linux currently ignores TABDLY, CRDLY, VTDLY, FFDLY * and NLDLY. They simply aren't relevant in the world today. @@ -350,8 +351,9 @@ * @c: character (or partial unicode symbol) * @tty: terminal device * - * Perform OPOST processing. Returns -1 when the output device is - * full and the character must be retried. + * Output one character with OPOST processing. + * Returns -1 when the output device is full and the character + * must be retried. * * Locking: output_lock to protect column state and space left * (also, this is called from n_tty_write under the @@ -377,8 +379,11 @@ /** * process_output_block - block post processor * @tty: terminal device - * @inbuf: user buffer - * @nr: number of bytes + * @buf: character buffer + * @nr: number of bytes to output + * + * Output a block of characters with OPOST processing. + * Returns the number of characters output. * * This path is used to speed up block console writes, among other * things when processing blocks of output data. It handles only @@ -571,33 +576,23 @@ break; default: - if (iscntrl(op)) { - if (L_ECHOCTL(tty)) { - /* - * Ensure there is enough space - * for the whole ctrl pair. - */ - if (space < 2) { - no_space_left = 1; - break; - } - tty_put_char(tty, '^'); - tty_put_char(tty, op ^ 0100); - tty->column += 2; - space -= 2; - } else { - if (!space) { - no_space_left = 1; - break; - } - tty_put_char(tty, op); - space--; - } - } /* - * If above falls through, this was an - * undefined op. + * If the op is not a special byte code, + * it is a ctrl char tagged to be echoed + * as "^X" (where X is the letter + * representing the control char). + * Note that we must ensure there is + * enough space for the whole ctrl pair. + * */ + if (space < 2) { + no_space_left = 1; + break; + } + tty_put_char(tty, '^'); + tty_put_char(tty, op ^ 0100); + tty->column += 2; + space -= 2; cp += 2; nr -= 2; } @@ -605,12 +600,18 @@ if (no_space_left) break; } else { - int retval; - - retval = do_output_char(c, tty, space); - if (retval < 0) - break; - space -= retval; + if (O_OPOST(tty) && + !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) { + int retval = do_output_char(c, tty, space); + if (retval < 0) + break; + space -= retval; + } else { + if (!space) + break; + tty_put_char(tty, c); + space -= 1; + } cp += 1; nr -= 1; } @@ -798,8 +799,8 @@ * Echo user input back onto the screen. This must be called only when * L_ECHO(tty) is true. Called from the driver receive_buf path. * - * This variant tags control characters to be possibly echoed as - * as "^X" (where X is the letter representing the control char). + * This variant tags control characters to be echoed as "^X" + * (where X is the letter representing the control char). * * Locking: echo_lock to protect the echo buffer */ @@ -812,7 +813,7 @@ add_echo_byte(ECHO_OP_START, tty); add_echo_byte(ECHO_OP_START, tty); } else { - if (iscntrl(c) && c != '\t') + if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') add_echo_byte(ECHO_OP_START, tty); add_echo_byte(c, tty); } --- linux-mvl-dove-2.6.31.orig/drivers/char/tty_io.c +++ linux-mvl-dove-2.6.31/drivers/char/tty_io.c @@ -1184,6 +1184,7 @@ tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); return 0; } +EXPORT_SYMBOL_GPL(tty_init_termios); /** * tty_driver_install_tty() - install a tty entry in the driver @@ -1404,6 +1405,8 @@ list_del_init(&tty->tty_files); file_list_unlock(); + put_pid(tty->pgrp); + put_pid(tty->session); free_tty_struct(tty); } --- linux-mvl-dove-2.6.31.orig/drivers/char/tty_buffer.c +++ linux-mvl-dove-2.6.31/drivers/char/tty_buffer.c @@ -402,28 +402,26 @@ container_of(work, struct tty_struct, buf.work.work); unsigned long flags; struct tty_ldisc *disc; - struct tty_buffer *tbuf, *head; - char *char_buf; - unsigned char *flag_buf; disc = tty_ldisc_ref(tty); if (disc == NULL) /* !TTY_LDISC */ return; spin_lock_irqsave(&tty->buf.lock, flags); - /* So we know a flush is running */ - set_bit(TTY_FLUSHING, &tty->flags); - head = tty->buf.head; - if (head != NULL) { - tty->buf.head = NULL; - for (;;) { - int count = head->commit - head->read; + + if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) { + struct tty_buffer *head; + while ((head = tty->buf.head) != NULL) { + int count; + char *char_buf; + unsigned char *flag_buf; + + count = head->commit - head->read; if (!count) { if (head->next == NULL) break; - tbuf = head; - head = head->next; - tty_buffer_free(tty, tbuf); + tty->buf.head = head->next; + tty_buffer_free(tty, head); continue; } /* Ldisc or user is trying to flush the buffers @@ -445,9 +443,9 @@ flag_buf, count); spin_lock_irqsave(&tty->buf.lock, flags); } - /* Restore the queue head */ - tty->buf.head = head; + clear_bit(TTY_FLUSHING, &tty->flags); } + /* We may have a deferred request to flush the input buffer, if so pull the chain under the lock and empty the queue */ if (test_bit(TTY_FLUSHPENDING, &tty->flags)) { @@ -455,7 +453,6 @@ clear_bit(TTY_FLUSHPENDING, &tty->flags); wake_up(&tty->read_wait); } - clear_bit(TTY_FLUSHING, &tty->flags); spin_unlock_irqrestore(&tty->buf.lock, flags); tty_ldisc_deref(disc); --- linux-mvl-dove-2.6.31.orig/drivers/char/ds2782.h +++ linux-mvl-dove-2.6.31/drivers/char/ds2782.h @@ -0,0 +1,67 @@ +/* + * + * Marvell Fuel Gauge IC driver + * Maxim DS2782 Fuel Gauge IC + * + * Author: + * Copyright (C) 2008 Marvell Ltd. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef MV_DS2782_DRV +#define MV_DS2782_DRV + +#define DS2782_I2C_ADDR 0x34 + +#define DS2782_STATUS_REG 0x01 +#define DS2782_VOLT_REG 0x0c +#define DS2782_TEMP_REG 0x0a +#define DS2782_CURRENT_REG 0x0e +#define DS2782_ACR_REG 0x10 +#define DS2782_IAVG_REG 0x08 +#define DS2782_AC_REG 0x62 +#define DS2782_AS_REG 0x14 +#define DS2782_RSNSP_REG 0x69 +#define DS2782_VCHG_REG 0x64 +#define DS2782_IMIN_REG 0x65 +#define DS2782_VAE_REG 0x66 +#define DS2782_IAE_REG 0x67 +#define DS2782_FULL40_REG 0x6a +#define DS2782_FULL_REG 0x16 +#define DS2782_AE_REG 0x18 +#define DS2782_SE_REG 0x1a +#define DS2782_RAAC_REG 0x02 +#define DS2782_RSAC_REG 0x04 +#define DS2782_RARC_REG 0x06 +#define DS2782_RSRC_REG 0x07 + +#define DS2782_VOLT_SHIFT_BIT 5 +#define DS2782_TEMP_SHIFT_BIT 5 +#define DS2782_CURRENT_SHIFT_BIT 0 +#define DS2782_ACR_SHIFT_BIT 0 +#define DS2782_IAVG_SHIFT_BIT 0 +#define DS2782_AC_SHIFT_BIT 0 +#define DS2782_AS_SHIFT_BIT 0 +#define DS2782_RSNSP_SHIFT_BIT 0 +#define DS2782_VCHG_SHIFT_BIT 0 +#define DS2782_IMIN_SHIFT_BIT 0 +#define DS2782_VAE_SHIFT_BIT 0 +#define DS2782_IAE_SHIFT_BIT 0 +#define DS2782_FULL40_SHIFT_BIT 0 +#define DS2782_FULL_SHIFT_BIT 0 +#define DS2782_AE_SHIFT_BIT 0 +#define DS2782_SE_SHIFT_BIT 0 +#define DS2782_RAAC_SHIFT_BIT 0 +#define DS2782_RSAC_SHIFT_BIT 0 +#define DS2782_RARC_SHIFT_BIT 0 +#define DS2782_RSRC_SHIFT_BIT 0 + +extern int ds2782_reg_get(int offset, unsigned char *pDataBuf, int datasize); +extern int ds2782_reg_set(int offset, unsigned char data); + +#endif /* MV_DS2782_DRV */ --- linux-mvl-dove-2.6.31.orig/drivers/char/Makefile +++ linux-mvl-dove-2.6.31/drivers/char/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_PRINTER) += lp.o +obj-$(CONFIG_APM_EMU_DS2782) += ds2782.o obj-$(CONFIG_APM_EMULATION) += apm-emulation.o obj-$(CONFIG_DTLK) += dtlk.o --- linux-mvl-dove-2.6.31.orig/drivers/char/tty_port.c +++ linux-mvl-dove-2.6.31/drivers/char/tty_port.c @@ -96,6 +96,14 @@ } EXPORT_SYMBOL(tty_port_tty_set); +static void tty_port_shutdown(struct tty_port *port) +{ + if (port->ops->shutdown && + test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) + port->ops->shutdown(port); + +} + /** * tty_port_hangup - hangup helper * @port: tty port @@ -116,6 +124,7 @@ port->tty = NULL; spin_unlock_irqrestore(&port->lock, flags); wake_up_interruptible(&port->open_wait); + tty_port_shutdown(port); } EXPORT_SYMBOL(tty_port_hangup); @@ -208,8 +217,14 @@ /* if non-blocking mode is set we can pass directly to open unless the port has just hung up or is in another error state */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { + if (tty->flags & (1 << TTY_IO_ERROR)) { + port->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + if (filp->f_flags & O_NONBLOCK) { + /* Indicate we are open */ + if (tty->termios->c_cflag & CBAUD) + tty_port_raise_dtr_rts(port); port->flags |= ASYNC_NORMAL_ACTIVE; return 0; } @@ -296,15 +311,17 @@ if (port->count) { spin_unlock_irqrestore(&port->lock, flags); + if (port->ops->drop) + port->ops->drop(port); return 0; } - port->flags |= ASYNC_CLOSING; + set_bit(ASYNCB_CLOSING, &port->flags); tty->closing = 1; spin_unlock_irqrestore(&port->lock, flags); /* Don't block on a stalled port, just pull the chain */ if (tty->flow_stopped) tty_driver_flush_buffer(tty); - if (port->flags & ASYNC_INITIALIZED && + if (test_bit(ASYNCB_INITIALIZED, &port->flags) && port->closing_wait != ASYNC_CLOSING_WAIT_NONE) tty_wait_until_sent(tty, port->closing_wait); if (port->drain_delay) { @@ -318,6 +335,9 @@ timeout = 2 * HZ; schedule_timeout_interruptible(timeout); } + /* Don't call port->drop for the last reference. Callers will want + to drop the last active reference in ->shutdown() or the tty + shutdown path */ return 1; } EXPORT_SYMBOL(tty_port_close_start); @@ -348,3 +368,14 @@ spin_unlock_irqrestore(&port->lock, flags); } EXPORT_SYMBOL(tty_port_close_end); + +void tty_port_close(struct tty_port *port, struct tty_struct *tty, + struct file *filp) +{ + if (tty_port_close_start(port, tty, filp) == 0) + return; + tty_port_shutdown(port); + tty_port_close_end(port, tty); + tty_port_tty_set(port, NULL); +} +EXPORT_SYMBOL(tty_port_close); --- linux-mvl-dove-2.6.31.orig/drivers/char/tpm/tpm.c +++ linux-mvl-dove-2.6.31/drivers/char/tpm/tpm.c @@ -696,8 +696,7 @@ cmd.header.in = pcrread_header; cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); - BUILD_BUG_ON(cmd.header.in.length > READ_PCR_RESULT_SIZE); - rc = transmit_cmd(chip, &cmd, cmd.header.in.length, + rc = transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE, "attempting to read a pcr value"); if (rc == 0) @@ -742,7 +741,7 @@ * the module usage count. */ #define TPM_ORD_PCR_EXTEND cpu_to_be32(20) -#define EXTEND_PCR_SIZE 34 +#define EXTEND_PCR_RESULT_SIZE 34 static struct tpm_input_header pcrextend_header = { .tag = TPM_TAG_RQU_COMMAND, .length = cpu_to_be32(34), @@ -760,10 +759,9 @@ return -ENODEV; cmd.header.in = pcrextend_header; - BUILD_BUG_ON(be32_to_cpu(cmd.header.in.length) > EXTEND_PCR_SIZE); cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); - rc = transmit_cmd(chip, &cmd, cmd.header.in.length, + rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, "attempting extend a PCR value"); module_put(chip->dev->driver->owner); --- linux-mvl-dove-2.6.31.orig/drivers/char/tpm/tpm_tis.c +++ linux-mvl-dove-2.6.31/drivers/char/tpm/tpm_tis.c @@ -450,6 +450,12 @@ goto out_err; } + /* Default timeouts */ + chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); + chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + if (request_locality(chip, 0) != 0) { rc = -ENODEV; goto out_err; @@ -457,12 +463,6 @@ vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); - /* Default timeouts */ - chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); - chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); - chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); - chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); - dev_info(dev, "1.2 TPM (device-id 0x%X, rev-id %d)\n", vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); --- linux-mvl-dove-2.6.31.orig/drivers/char/agp/intel-agp.c +++ linux-mvl-dove-2.6.31/drivers/char/agp/intel-agp.c @@ -36,6 +36,8 @@ #define PCI_DEVICE_ID_INTEL_Q35_IG 0x29B2 #define PCI_DEVICE_ID_INTEL_Q33_HB 0x29D0 #define PCI_DEVICE_ID_INTEL_Q33_IG 0x29D2 +#define PCI_DEVICE_ID_INTEL_B43_HB 0x2E40 +#define PCI_DEVICE_ID_INTEL_B43_IG 0x2E42 #define PCI_DEVICE_ID_INTEL_GM45_HB 0x2A40 #define PCI_DEVICE_ID_INTEL_GM45_IG 0x2A42 #define PCI_DEVICE_ID_INTEL_IGD_E_HB 0x2E00 @@ -50,6 +52,7 @@ #define PCI_DEVICE_ID_INTEL_IGDNG_D_IG 0x0042 #define PCI_DEVICE_ID_INTEL_IGDNG_M_HB 0x0044 #define PCI_DEVICE_ID_INTEL_IGDNG_MA_HB 0x0062 +#define PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB 0x006a #define PCI_DEVICE_ID_INTEL_IGDNG_M_IG 0x0046 /* cover 915 and 945 variants */ @@ -81,9 +84,11 @@ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_B43_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_D_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_M_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_MA_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_MA_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB) extern int agp_memory_reserved; @@ -679,23 +684,39 @@ if (!intel_private.i8xx_page) return; - /* make page uncached */ - map_page_into_agp(intel_private.i8xx_page); - intel_private.i8xx_flush_page = kmap(intel_private.i8xx_page); if (!intel_private.i8xx_flush_page) intel_i830_fini_flush(); } +static void +do_wbinvd(void *null) +{ + wbinvd(); +} + +/* The chipset_flush interface needs to get data that has already been + * flushed out of the CPU all the way out to main memory, because the GPU + * doesn't snoop those buffers. + * + * The 8xx series doesn't have the same lovely interface for flushing the + * chipset write buffers that the later chips do. According to the 865 + * specs, it's 64 octwords, or 1KB. So, to get those previous things in + * that buffer out, we just fill 1KB and clflush it out, on the assumption + * that it'll push whatever was in there out. It appears to work. + */ static void intel_i830_chipset_flush(struct agp_bridge_data *bridge) { unsigned int *pg = intel_private.i8xx_flush_page; - int i; - for (i = 0; i < 256; i += 2) - *(pg + i) = i; + memset(pg, 0, 1024); - wmb(); + if (cpu_has_clflush) { + clflush_cache_range(pg, 1024); + } else { + if (on_each_cpu(do_wbinvd, NULL, 1) != 0) + printk(KERN_ERR "Timed out waiting for cache flush.\n"); + } } /* The intel i830 automatically initializes the agp aperture during POST. @@ -1216,9 +1237,11 @@ case PCI_DEVICE_ID_INTEL_Q45_HB: case PCI_DEVICE_ID_INTEL_G45_HB: case PCI_DEVICE_ID_INTEL_G41_HB: + case PCI_DEVICE_ID_INTEL_B43_HB: case PCI_DEVICE_ID_INTEL_IGDNG_D_HB: case PCI_DEVICE_ID_INTEL_IGDNG_M_HB: case PCI_DEVICE_ID_INTEL_IGDNG_MA_HB: + case PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB: *gtt_offset = *gtt_size = MB(2); break; default: @@ -2192,6 +2215,8 @@ "Q45/Q43", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_G45_HB, PCI_DEVICE_ID_INTEL_G45_IG, 0, "G45/G43", NULL, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_B43_HB, PCI_DEVICE_ID_INTEL_B43_IG, 0, + "B43", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0, "G41", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_IGDNG_D_HB, PCI_DEVICE_ID_INTEL_IGDNG_D_IG, 0, @@ -2200,6 +2225,8 @@ "IGDNG/M", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_IGDNG_MA_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0, "IGDNG/MA", NULL, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0, + "IGDNG/MC2", NULL, &intel_i965_driver }, { 0, 0, 0, NULL, NULL, NULL } }; @@ -2313,15 +2340,6 @@ struct agp_bridge_data *bridge = pci_get_drvdata(pdev); int ret_val; - pci_restore_state(pdev); - - /* We should restore our graphics device's config space, - * as host bridge (00:00) resumes before graphics device (02:00), - * then our access to its pci space can work right. - */ - if (intel_private.pcidev) - pci_restore_state(intel_private.pcidev); - if (bridge->driver == &intel_generic_driver) intel_configure(); else if (bridge->driver == &intel_850_driver) @@ -2401,9 +2419,11 @@ ID(PCI_DEVICE_ID_INTEL_Q45_HB), ID(PCI_DEVICE_ID_INTEL_G45_HB), ID(PCI_DEVICE_ID_INTEL_G41_HB), + ID(PCI_DEVICE_ID_INTEL_B43_HB), ID(PCI_DEVICE_ID_INTEL_IGDNG_D_HB), ID(PCI_DEVICE_ID_INTEL_IGDNG_M_HB), ID(PCI_DEVICE_ID_INTEL_IGDNG_MA_HB), + ID(PCI_DEVICE_ID_INTEL_IGDNG_MC2_HB), { } }; @@ -2434,5 +2454,6 @@ module_init(agp_intel_init); module_exit(agp_intel_cleanup); +MODULE_EXPORT(intel_agp); MODULE_AUTHOR("Dave Jones "); MODULE_LICENSE("GPL and additional rights"); --- linux-mvl-dove-2.6.31.orig/drivers/bluetooth/dtl1_cs.c +++ linux-mvl-dove-2.6.31/drivers/bluetooth/dtl1_cs.c @@ -299,7 +299,10 @@ int iir, lsr; irqreturn_t r = IRQ_NONE; - BUG_ON(!info->hdev); + if (!info || !info->hdev) { + BT_ERR("Call of irq %d for unknown device", irq); + return IRQ_NONE; + } iobase = info->p_dev->io.BasePort1; --- linux-mvl-dove-2.6.31.orig/drivers/bluetooth/bluecard_cs.c +++ linux-mvl-dove-2.6.31/drivers/bluetooth/bluecard_cs.c @@ -503,7 +503,10 @@ unsigned int iobase; unsigned char reg; - BUG_ON(!info->hdev); + if (!info || !info->hdev) { + BT_ERR("Call of irq %d for unknown device", irq); + return IRQ_NONE; + } if (!test_bit(CARD_READY, &(info->hw_state))) return IRQ_HANDLED; --- linux-mvl-dove-2.6.31.orig/drivers/bluetooth/btuart_cs.c +++ linux-mvl-dove-2.6.31/drivers/bluetooth/btuart_cs.c @@ -295,7 +295,10 @@ int iir, lsr; irqreturn_t r = IRQ_NONE; - BUG_ON(!info->hdev); + if (!info || !info->hdev) { + BT_ERR("Call of irq %d for unknown device", irq); + return IRQ_NONE; + } iobase = info->p_dev->io.BasePort1; --- linux-mvl-dove-2.6.31.orig/drivers/bluetooth/bt3c_cs.c +++ linux-mvl-dove-2.6.31/drivers/bluetooth/bt3c_cs.c @@ -345,7 +345,10 @@ int iir; irqreturn_t r = IRQ_NONE; - BUG_ON(!info->hdev); + if (!info || !info->hdev) { + BT_ERR("Call of irq %d for unknown device", irq); + return IRQ_NONE; + } iobase = info->p_dev->io.BasePort1; --- linux-mvl-dove-2.6.31.orig/drivers/dma/mv_xor.h +++ linux-mvl-dove-2.6.31/drivers/dma/mv_xor.h @@ -22,6 +22,7 @@ #include #include #include +#include #define USE_TIMER #define MV_XOR_SLOT_SIZE 64 @@ -55,6 +56,9 @@ struct mv_xor_shared_private { void __iomem *xor_base; void __iomem *xor_high_base; +#if defined(CONFIG_HAVE_CLK) + struct clk *clk; +#endif }; --- linux-mvl-dove-2.6.31.orig/drivers/dma/at_hdmac.c +++ linux-mvl-dove-2.6.31/drivers/dma/at_hdmac.c @@ -813,7 +813,7 @@ dev_vdbg(chan2dev(chan), "is_tx_complete: %d (d%d, u%d)\n", cookie, done ? *done : 0, used ? *used : 0); - spin_lock_bh(atchan->lock); + spin_lock_bh(&atchan->lock); last_complete = atchan->completed_cookie; last_used = chan->cookie; @@ -828,7 +828,7 @@ ret = dma_async_is_complete(cookie, last_complete, last_used); } - spin_unlock_bh(atchan->lock); + spin_unlock_bh(&atchan->lock); if (done) *done = last_complete; --- linux-mvl-dove-2.6.31.orig/drivers/dma/mv_xor.c +++ linux-mvl-dove-2.6.31/drivers/dma/mv_xor.c @@ -1284,9 +1284,38 @@ writel(win_enable, base + WINDOW_BAR_ENABLE(1)); } +#ifdef CONFIG_PM +static int mv_xor_suspend(struct platform_device *pdev, pm_message_t state) +{ + return 0; +} + +static int mv_xor_resume(struct platform_device *pdev) +{ + struct mv_xor_device *device = platform_get_drvdata(pdev); + struct dma_chan *chan, *_chan; + struct mv_xor_chan *mv_chan; + + list_for_each_entry_safe(chan, _chan, &device->common.channels, + device_node) { + mv_chan = to_mv_xor_chan(chan); + mv_chan_unmask_interrupts(mv_chan); + + mv_set_mode(mv_chan, mv_chan->current_type); + } + return 0; +} + +#else +#define mv_xor_suspend NULL +#define mv_xor_resume NULL +#endif + static struct platform_driver mv_xor_driver = { .probe = mv_xor_probe, .remove = __devexit_p(mv_xor_remove), + .suspend = mv_xor_suspend, + .resume = mv_xor_resume, .driver = { .owner = THIS_MODULE, .name = MV_XOR_NAME, @@ -1325,6 +1354,14 @@ platform_set_drvdata(pdev, msp); +#if defined(CONFIG_HAVE_CLK) + msp->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(msp->clk)) + dev_notice(&pdev->dev, "cannot get clkdev\n"); + else + clk_enable(msp->clk); +#endif + /* * (Re-)program MBUS remapping windows if we are asked to. */ @@ -1336,12 +1373,47 @@ static int mv_xor_shared_remove(struct platform_device *pdev) { +#if defined(CONFIG_HAVE_CLK) + struct mv_xor_shared_private *msp = platform_get_drvdata(pdev); + + if (!IS_ERR(msp->clk)) { + clk_disable(msp->clk); + clk_put(msp->clk); + } +#endif + return 0; +} + +#ifdef CONFIG_PM +static int mv_xor_shared_suspend(struct platform_device *pdev, + pm_message_t state) +{ return 0; } +static int mv_xor_shared_resume(struct platform_device *pdev) +{ + struct mv_xor_platform_shared_data *msd = pdev->dev.platform_data; + struct mv_xor_shared_private *msp = platform_get_drvdata(pdev); + /* + * (Re-)program MBUS remapping windows if we are asked to. + */ + if (msd != NULL && msd->dram != NULL) + mv_xor_conf_mbus_windows(msp, msd->dram); + + return 0; +} + +#else +#define mv_xor_shared_suspend NULL +#define mv_xor_shared_resume NULL +#endif + static struct platform_driver mv_xor_shared_driver = { .probe = mv_xor_shared_probe, .remove = mv_xor_shared_remove, + .suspend = mv_xor_shared_suspend, + .resume = mv_xor_shared_resume, .driver = { .owner = THIS_MODULE, .name = MV_XOR_SHARED_NAME, --- linux-mvl-dove-2.6.31.orig/drivers/watchdog/riowd.c +++ linux-mvl-dove-2.6.31/drivers/watchdog/riowd.c @@ -206,7 +206,7 @@ dev_set_drvdata(&op->dev, p); riowd_device = p; - err = 0; + return 0; out_iounmap: of_iounmap(&op->resource[0], p->regs, 2); --- linux-mvl-dove-2.6.31.orig/drivers/pci/pci.c +++ linux-mvl-dove-2.6.31/drivers/pci/pci.c @@ -2650,6 +2650,11 @@ return 0; } +void __weak pci_fixup_cardbus(struct pci_bus *bus) +{ +} +EXPORT_SYMBOL(pci_fixup_cardbus); + static int __init pci_setup(char *str) { while (str) { --- linux-mvl-dove-2.6.31.orig/drivers/pci/quirks.c +++ linux-mvl-dove-2.6.31/drivers/pci/quirks.c @@ -1201,6 +1201,7 @@ switch(dev->subsystem_device) { case 0x00b8: /* Compaq Evo D510 CMT */ case 0x00b9: /* Compaq Evo D510 SFF */ + case 0x00ba: /* Compaq Evo D510 USDT */ /* Motherboard doesn't have Host bridge * subvendor/subdevice IDs and on-board VGA * controller is disabled if an AGP card is @@ -2382,8 +2383,10 @@ } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk_leaf); +DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk_leaf); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk_all); +DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk_all); static void __devinit quirk_msi_intx_disable_bug(struct pci_dev *dev) { @@ -2492,6 +2495,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e8, quirk_i82576_sriov); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150a, quirk_i82576_sriov); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150d, quirk_i82576_sriov); #endif /* CONFIG_PCI_IOV */ --- linux-mvl-dove-2.6.31.orig/drivers/pci/dmar.c +++ linux-mvl-dove-2.6.31/drivers/pci/dmar.c @@ -632,20 +632,31 @@ iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG); iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); + if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) { + /* Promote an attitude of violence to a BIOS engineer today */ + WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n" + "BIOS vendor: %s; Ver: %s; Product Version: %s\n", + drhd->reg_base_addr, + dmi_get_system_info(DMI_BIOS_VENDOR), + dmi_get_system_info(DMI_BIOS_VERSION), + dmi_get_system_info(DMI_PRODUCT_VERSION)); + goto err_unmap; + } + #ifdef CONFIG_DMAR agaw = iommu_calculate_agaw(iommu); if (agaw < 0) { printk(KERN_ERR "Cannot get a valid agaw for iommu (seq_id = %d)\n", iommu->seq_id); - goto error; + goto err_unmap; } msagaw = iommu_calculate_max_sagaw(iommu); if (msagaw < 0) { printk(KERN_ERR "Cannot get a valid max agaw for iommu (seq_id = %d)\n", iommu->seq_id); - goto error; + goto err_unmap; } #endif iommu->agaw = agaw; @@ -665,7 +676,7 @@ } ver = readl(iommu->reg + DMAR_VER_REG); - pr_debug("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n", + pr_info("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n", (unsigned long long)drhd->reg_base_addr, DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver), (unsigned long long)iommu->cap, @@ -675,7 +686,10 @@ drhd->iommu = iommu; return 0; -error: + + err_unmap: + iounmap(iommu->reg); + error: kfree(iommu); return -1; } --- linux-mvl-dove-2.6.31.orig/drivers/pci/pcie/aer/aerdrv.c +++ linux-mvl-dove-2.6.31/drivers/pci/pcie/aer/aerdrv.c @@ -52,7 +52,7 @@ static struct pcie_port_service_driver aerdriver = { .name = "aer", - .port_type = PCIE_ANY_PORT, + .port_type = PCIE_RC_PORT, .service = PCIE_PORT_SERVICE_AER, .probe = aer_probe, --- linux-mvl-dove-2.6.31.orig/drivers/base/base.h +++ linux-mvl-dove-2.6.31/drivers/base/base.h @@ -104,7 +104,7 @@ extern int cpu_dev_init(void); extern int bus_add_device(struct device *dev); -extern void bus_attach_device(struct device *dev); +extern void bus_probe_device(struct device *dev); extern void bus_remove_device(struct device *dev); extern int bus_add_driver(struct device_driver *drv); --- linux-mvl-dove-2.6.31.orig/drivers/base/core.c +++ linux-mvl-dove-2.6.31/drivers/base/core.c @@ -945,7 +945,7 @@ BUS_NOTIFY_ADD_DEVICE, dev); kobject_uevent(&dev->kobj, KOBJ_ADD); - bus_attach_device(dev); + bus_probe_device(dev); if (parent) klist_add_tail(&dev->p->knode_parent, &parent->p->klist_children); --- linux-mvl-dove-2.6.31.orig/drivers/base/bus.c +++ linux-mvl-dove-2.6.31/drivers/base/bus.c @@ -459,8 +459,9 @@ * bus_add_device - add device to bus * @dev: device being added * + * - Add device's bus attributes. + * - Create links to device's bus. * - Add the device to its bus's list of devices. - * - Create link to device's bus. */ int bus_add_device(struct device *dev) { @@ -483,6 +484,7 @@ error = make_deprecated_bus_links(dev); if (error) goto out_deprecated; + klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices); } return 0; @@ -498,24 +500,19 @@ } /** - * bus_attach_device - add device to bus - * @dev: device tried to attach to a driver + * bus_probe_device - probe drivers for a new device + * @dev: device to probe * - * - Add device to bus's list of devices. - * - Try to attach to driver. + * - Automatically probe for a driver if the bus allows it. */ -void bus_attach_device(struct device *dev) +void bus_probe_device(struct device *dev) { struct bus_type *bus = dev->bus; - int ret = 0; + int ret; - if (bus) { - if (bus->p->drivers_autoprobe) - ret = device_attach(dev); + if (bus && bus->p->drivers_autoprobe) { + ret = device_attach(dev); WARN_ON(ret < 0); - if (ret >= 0) - klist_add_tail(&dev->p->knode_bus, - &bus->p->klist_devices); } } --- linux-mvl-dove-2.6.31.orig/drivers/base/driver.c +++ linux-mvl-dove-2.6.31/drivers/base/driver.c @@ -236,7 +236,7 @@ put_driver(other); printk(KERN_ERR "Error: Driver '%s' is already registered, " "aborting...\n", drv->name); - return -EEXIST; + return -EBUSY; } ret = bus_add_driver(drv); --- linux-mvl-dove-2.6.31.orig/drivers/md/dm-log-userspace-base.c +++ linux-mvl-dove-2.6.31/drivers/md/dm-log-userspace-base.c @@ -156,7 +156,7 @@ } /* The ptr value is sufficient for local unique id */ - lc->luid = (uint64_t)lc; + lc->luid = (unsigned long)lc; lc->ti = ti; @@ -582,7 +582,7 @@ break; case STATUSTYPE_TABLE: sz = 0; - table_args = strstr(lc->usr_argv_str, " "); + table_args = strchr(lc->usr_argv_str, ' '); BUG_ON(!table_args); /* There will always be a ' ' */ table_args++; --- linux-mvl-dove-2.6.31.orig/drivers/md/raid5.c +++ linux-mvl-dove-2.6.31/drivers/md/raid5.c @@ -3790,6 +3790,8 @@ sector_nr = conf->reshape_progress; sector_div(sector_nr, new_data_disks); if (sector_nr) { + mddev->curr_resync_completed = sector_nr; + sysfs_notify(&mddev->kobj, NULL, "sync_completed"); *skipped = 1; return sector_nr; } --- linux-mvl-dove-2.6.31.orig/drivers/md/dm-log-userspace-transfer.c +++ linux-mvl-dove-2.6.31/drivers/md/dm-log-userspace-transfer.c @@ -129,11 +129,13 @@ * This is the connector callback that delivers data * that was sent from userspace. */ -static void cn_ulog_callback(void *data) +static void cn_ulog_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) { - struct cn_msg *msg = (struct cn_msg *)data; struct dm_ulog_request *tfr = (struct dm_ulog_request *)(msg + 1); + if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN)) + return; + spin_lock(&receiving_list_lock); if (msg->len == 0) fill_pkg(msg, NULL); --- linux-mvl-dove-2.6.31.orig/drivers/md/dm-exception-store.h +++ linux-mvl-dove-2.6.31/drivers/md/dm-exception-store.h @@ -101,9 +101,9 @@ struct dm_dev *cow; /* Size of data blocks saved - must be a power of 2 */ - chunk_t chunk_size; - chunk_t chunk_mask; - chunk_t chunk_shift; + unsigned chunk_size; + unsigned chunk_mask; + unsigned chunk_shift; void *context; }; @@ -169,7 +169,7 @@ int dm_exception_store_type_unregister(struct dm_exception_store_type *type); int dm_exception_store_set_chunk_size(struct dm_exception_store *store, - unsigned long chunk_size_ulong, + unsigned chunk_size, char **error); int dm_exception_store_create(struct dm_target *ti, int argc, char **argv, --- linux-mvl-dove-2.6.31.orig/drivers/md/dm-snap.c +++ linux-mvl-dove-2.6.31/drivers/md/dm-snap.c @@ -296,6 +296,7 @@ */ static int register_snapshot(struct dm_snapshot *snap) { + struct dm_snapshot *l; struct origin *o, *new_o; struct block_device *bdev = snap->origin->bdev; @@ -319,7 +320,11 @@ __insert_origin(o); } - list_add_tail(&snap->list, &o->snapshots); + /* Sort the list according to chunk size, largest-first smallest-last */ + list_for_each_entry(l, &o->snapshots, list) + if (l->store->chunk_size < snap->store->chunk_size) + break; + list_add_tail(&snap->list, &l->list); up_write(&_origins_lock); return 0; @@ -668,6 +673,11 @@ bio_list_init(&s->queued_bios); INIT_WORK(&s->queued_bios_work, flush_queued_bios); + if (!s->store->chunk_size) { + ti->error = "Chunk size not set"; + goto bad_load_and_register; + } + /* Add snapshot to the list of snapshots for this origin */ /* Exceptions aren't triggered till snapshot_resume() is called */ if (register_snapshot(s)) { @@ -951,7 +961,7 @@ src.bdev = bdev; src.sector = chunk_to_sector(s->store, pe->e.old_chunk); - src.count = min(s->store->chunk_size, dev_size - src.sector); + src.count = min((sector_t)s->store->chunk_size, dev_size - src.sector); dest.bdev = s->store->cow->bdev; dest.sector = chunk_to_sector(s->store, pe->e.new_chunk); @@ -1142,6 +1152,8 @@ unsigned sz = 0; struct dm_snapshot *snap = ti->private; + down_write(&snap->lock); + switch (type) { case STATUSTYPE_INFO: if (!snap->valid) @@ -1173,6 +1185,8 @@ break; } + up_write(&snap->lock); + return 0; } @@ -1388,7 +1402,7 @@ struct dm_dev *dev = ti->private; struct dm_snapshot *snap; struct origin *o; - chunk_t chunk_size = 0; + unsigned chunk_size = 0; down_read(&_origins_lock); o = __lookup_origin(dev->bdev); @@ -1465,7 +1479,7 @@ r = dm_register_target(&snapshot_target); if (r) { DMERR("snapshot target register failed %d", r); - return r; + goto bad_register_snapshot_target; } r = dm_register_target(&origin_target); @@ -1522,6 +1536,9 @@ dm_unregister_target(&origin_target); bad1: dm_unregister_target(&snapshot_target); + +bad_register_snapshot_target: + dm_exception_store_exit(); return r; } --- linux-mvl-dove-2.6.31.orig/drivers/md/raid1.c +++ linux-mvl-dove-2.6.31/drivers/md/raid1.c @@ -1643,11 +1643,12 @@ r1_bio->sector, r1_bio->sectors); unfreeze_array(conf); - } + } else + md_error(mddev, + conf->mirrors[r1_bio->read_disk].rdev); bio = r1_bio->bios[r1_bio->read_disk]; - if ((disk=read_balance(conf, r1_bio)) == -1 || - disk == r1_bio->read_disk) { + if ((disk=read_balance(conf, r1_bio)) == -1) { printk(KERN_ALERT "raid1: %s: unrecoverable I/O" " read error for block %llu\n", bdevname(bio->bi_bdev,b), @@ -1676,6 +1677,7 @@ generic_make_request(bio); } } + cond_resched(); } if (unplug) unplug_slaves(mddev); --- linux-mvl-dove-2.6.31.orig/drivers/md/bitmap.h +++ linux-mvl-dove-2.6.31/drivers/md/bitmap.h @@ -282,7 +282,7 @@ void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector); void bitmap_unplug(struct bitmap *bitmap); -void bitmap_daemon_work(struct bitmap *bitmap); +void bitmap_daemon_work(mddev_t *mddev); #endif #endif --- linux-mvl-dove-2.6.31.orig/drivers/md/dm.c +++ linux-mvl-dove-2.6.31/drivers/md/dm.c @@ -47,6 +47,7 @@ atomic_t io_count; struct bio *bio; unsigned long start_time; + spinlock_t endio_lock; }; /* @@ -576,8 +577,12 @@ struct mapped_device *md = io->md; /* Push-back supersedes any I/O errors */ - if (error && !(io->error > 0 && __noflush_suspending(md))) - io->error = error; + if (unlikely(error)) { + spin_lock_irqsave(&io->endio_lock, flags); + if (!(io->error > 0 && __noflush_suspending(md))) + io->error = error; + spin_unlock_irqrestore(&io->endio_lock, flags); + } if (atomic_dec_and_test(&io->io_count)) { if (io->error == DM_ENDIO_REQUEUE) { @@ -1224,6 +1229,7 @@ atomic_set(&ci.io->io_count, 1); ci.io->bio = bio; ci.io->md = md; + spin_lock_init(&ci.io->endio_lock); ci.sector = bio->bi_sector; ci.sector_count = bio_sectors(bio); if (unlikely(bio_empty_barrier(bio))) @@ -1819,6 +1825,7 @@ bad_bdev: destroy_workqueue(md->wq); bad_thread: + del_gendisk(md->disk); put_disk(md->disk); bad_disk: blk_cleanup_queue(md->queue); @@ -2562,6 +2569,7 @@ { return md->disk; } +EXPORT_SYMBOL_GPL(dm_disk); struct kobject *dm_kobject(struct mapped_device *md) { --- linux-mvl-dove-2.6.31.orig/drivers/md/dm-exception-store.c +++ linux-mvl-dove-2.6.31/drivers/md/dm-exception-store.c @@ -155,7 +155,8 @@ char *value; chunk_size_ulong = simple_strtoul(chunk_size_arg, &value, 10); - if (*chunk_size_arg == '\0' || *value != '\0') { + if (*chunk_size_arg == '\0' || *value != '\0' || + chunk_size_ulong > UINT_MAX) { *error = "Invalid chunk size"; return -EINVAL; } @@ -171,34 +172,35 @@ */ chunk_size_ulong = round_up(chunk_size_ulong, PAGE_SIZE >> 9); - return dm_exception_store_set_chunk_size(store, chunk_size_ulong, + return dm_exception_store_set_chunk_size(store, + (unsigned) chunk_size_ulong, error); } int dm_exception_store_set_chunk_size(struct dm_exception_store *store, - unsigned long chunk_size_ulong, + unsigned chunk_size, char **error) { /* Check chunk_size is a power of 2 */ - if (!is_power_of_2(chunk_size_ulong)) { + if (!is_power_of_2(chunk_size)) { *error = "Chunk size is not a power of 2"; return -EINVAL; } /* Validate the chunk size against the device block size */ - if (chunk_size_ulong % (bdev_logical_block_size(store->cow->bdev) >> 9)) { + if (chunk_size % (bdev_logical_block_size(store->cow->bdev) >> 9)) { *error = "Chunk size is not a multiple of device blocksize"; return -EINVAL; } - if (chunk_size_ulong > INT_MAX >> SECTOR_SHIFT) { + if (chunk_size > INT_MAX >> SECTOR_SHIFT) { *error = "Chunk size is too high"; return -EINVAL; } - store->chunk_size = chunk_size_ulong; - store->chunk_mask = chunk_size_ulong - 1; - store->chunk_shift = ffs(chunk_size_ulong) - 1; + store->chunk_size = chunk_size; + store->chunk_mask = chunk_size - 1; + store->chunk_shift = ffs(chunk_size) - 1; return 0; } @@ -251,7 +253,7 @@ r = set_chunk_size(tmp_store, argv[2], &ti->error); if (r) - goto bad_cow; + goto bad_ctr; r = type->ctr(tmp_store, 0, NULL); if (r) { --- linux-mvl-dove-2.6.31.orig/drivers/md/raid10.c +++ linux-mvl-dove-2.6.31/drivers/md/raid10.c @@ -1630,6 +1630,7 @@ generic_make_request(bio); } } + cond_resched(); } if (unplug) unplug_slaves(mddev); --- linux-mvl-dove-2.6.31.orig/drivers/md/bitmap.c +++ linux-mvl-dove-2.6.31/drivers/md/bitmap.c @@ -1077,23 +1077,31 @@ * out to disk */ -void bitmap_daemon_work(struct bitmap *bitmap) +void bitmap_daemon_work(mddev_t *mddev) { + struct bitmap *bitmap; unsigned long j; unsigned long flags; struct page *page = NULL, *lastpage = NULL; int blocks; void *paddr; - if (bitmap == NULL) + /* Use a mutex to guard daemon_work against + * bitmap_destroy. + */ + mutex_lock(&mddev->bitmap_mutex); + bitmap = mddev->bitmap; + if (bitmap == NULL) { + mutex_unlock(&mddev->bitmap_mutex); return; + } if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ)) goto done; bitmap->daemon_lastrun = jiffies; if (bitmap->allclean) { bitmap->mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; - return; + goto done; } bitmap->allclean = 1; @@ -1202,6 +1210,7 @@ done: if (bitmap->allclean == 0) bitmap->mddev->thread->timeout = bitmap->daemon_sleep * HZ; + mutex_unlock(&mddev->bitmap_mutex); } static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap, @@ -1538,9 +1547,9 @@ */ sleep = bitmap->daemon_sleep; bitmap->daemon_sleep = 0; - bitmap_daemon_work(bitmap); - bitmap_daemon_work(bitmap); - bitmap_daemon_work(bitmap); + bitmap_daemon_work(mddev); + bitmap_daemon_work(mddev); + bitmap_daemon_work(mddev); bitmap->daemon_sleep = sleep; bitmap_update_sb(bitmap); } @@ -1571,6 +1580,7 @@ kfree(bp); kfree(bitmap); } + void bitmap_destroy(mddev_t *mddev) { struct bitmap *bitmap = mddev->bitmap; @@ -1578,7 +1588,9 @@ if (!bitmap) /* there was no bitmap */ return; + mutex_lock(&mddev->bitmap_mutex); mddev->bitmap = NULL; /* disconnect from the md device */ + mutex_unlock(&mddev->bitmap_mutex); if (mddev->thread) mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; --- linux-mvl-dove-2.6.31.orig/drivers/md/md.c +++ linux-mvl-dove-2.6.31/drivers/md/md.c @@ -276,7 +276,9 @@ if (!atomic_dec_and_lock(&mddev->active, &all_mddevs_lock)) return; if (!mddev->raid_disks && list_empty(&mddev->disks) && - !mddev->hold_active) { + mddev->ctime == 0 && !mddev->hold_active) { + /* Array is not configured at all, and not held active, + * so destroy it */ list_del(&mddev->all_mddevs); if (mddev->gendisk) { /* we did a probe so need to clean up. @@ -361,6 +363,7 @@ mutex_init(&new->open_mutex); mutex_init(&new->reconfig_mutex); + mutex_init(&new->bitmap_mutex); INIT_LIST_HEAD(&new->disks); INIT_LIST_HEAD(&new->all_mddevs); init_timer(&new->safemode_timer); @@ -5039,6 +5042,10 @@ mddev->minor_version = info->minor_version; mddev->patch_version = info->patch_version; mddev->persistent = !info->not_persistent; + /* ensure mddev_put doesn't delete this now that there + * is some minimal configuration. + */ + mddev->ctime = get_seconds(); return 0; } mddev->major_version = MD_MAJOR_VERSION; @@ -6495,8 +6502,9 @@ skip: mddev->curr_resync = 0; mddev->curr_resync_completed = 0; - mddev->resync_min = 0; - mddev->resync_max = MaxSector; + if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) + /* We completed so max setting can be forgotten. */ + mddev->resync_max = MaxSector; sysfs_notify(&mddev->kobj, NULL, "sync_completed"); wake_up(&resync_wait); set_bit(MD_RECOVERY_DONE, &mddev->recovery); @@ -6594,7 +6602,7 @@ if (mddev->bitmap) - bitmap_daemon_work(mddev->bitmap); + bitmap_daemon_work(mddev); if (mddev->ro) return; --- linux-mvl-dove-2.6.31.orig/drivers/md/dm-snap-persistent.c +++ linux-mvl-dove-2.6.31/drivers/md/dm-snap-persistent.c @@ -284,12 +284,13 @@ { int r; struct disk_header *dh; - chunk_t chunk_size; + unsigned chunk_size; int chunk_size_supplied = 1; char *chunk_err; /* - * Use default chunk size (or hardsect_size, if larger) if none supplied + * Use default chunk size (or logical_block_size, if larger) + * if none supplied */ if (!ps->store->chunk_size) { ps->store->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS, @@ -334,10 +335,9 @@ return 0; if (chunk_size_supplied) - DMWARN("chunk size %llu in device metadata overrides " - "table chunk size of %llu.", - (unsigned long long)chunk_size, - (unsigned long long)ps->store->chunk_size); + DMWARN("chunk size %u in device metadata overrides " + "table chunk size of %u.", + chunk_size, ps->store->chunk_size); /* We had a bogus chunk_size. Fix stuff up. */ free_area(ps); @@ -345,8 +345,8 @@ r = dm_exception_store_set_chunk_size(ps->store, chunk_size, &chunk_err); if (r) { - DMERR("invalid on-disk chunk size %llu: %s.", - (unsigned long long)chunk_size, chunk_err); + DMERR("invalid on-disk chunk size %u: %s.", + chunk_size, chunk_err); return r; } --- linux-mvl-dove-2.6.31.orig/drivers/md/md.h +++ linux-mvl-dove-2.6.31/drivers/md/md.h @@ -289,6 +289,7 @@ * hot-adding a bitmap. It should * eventually be settable by sysfs. */ + struct mutex bitmap_mutex; struct list_head all_mddevs; }; --- linux-mvl-dove-2.6.31.orig/drivers/cpuidle/cpuidle.c +++ linux-mvl-dove-2.6.31/drivers/cpuidle/cpuidle.c @@ -75,8 +75,11 @@ #endif /* ask the governor for the next state */ next_state = cpuidle_curr_governor->select(dev); - if (need_resched()) + if (need_resched()) { + local_irq_enable(); return; + } + target_state = &dev->states[next_state]; /* enter the state and update stats */ --- linux-mvl-dove-2.6.31.orig/drivers/virtio/virtio_ring.c +++ linux-mvl-dove-2.6.31/drivers/virtio/virtio_ring.c @@ -281,6 +281,9 @@ return NULL; } + /* Only get used array entries after they have been exposed by host. */ + rmb(); + i = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].id; *len = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].len; --- linux-mvl-dove-2.6.31.orig/drivers/mmc/host/Kconfig +++ linux-mvl-dove-2.6.31/drivers/mmc/host/Kconfig @@ -55,6 +55,17 @@ If unsure, say N. +config MMC_SDHCI_MV + tristate "SDHCI support on Marvell's soc" + depends on MMC_SDHCI + help + This selects the Secure Digital Host Controller Interface in + Marvell's SoC controllers. + + If you have a controller with this interface, say Y or M here. + + If unsure, say N. + config MMC_RICOH_MMC tristate "Ricoh MMC Controller Disabler (EXPERIMENTAL)" depends on MMC_SDHCI_PCI --- linux-mvl-dove-2.6.31.orig/drivers/mmc/host/pxamci.c +++ linux-mvl-dove-2.6.31/drivers/mmc/host/pxamci.c @@ -694,14 +694,14 @@ if (mmc) { struct pxamci_host *host = mmc_priv(mmc); + mmc_remove_host(mmc); + if (host->vcc) regulator_put(host->vcc); if (host->pdata && host->pdata->exit) host->pdata->exit(&pdev->dev, mmc); - mmc_remove_host(mmc); - pxamci_stop_clock(host); writel(TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD| END_CMD_RES|PRG_DONE|DATA_TRAN_DONE, --- linux-mvl-dove-2.6.31.orig/drivers/mmc/host/sdhci.h +++ linux-mvl-dove-2.6.31/drivers/mmc/host/sdhci.h @@ -13,6 +13,7 @@ #include #include #include +#include /* * Controller registers @@ -232,10 +233,16 @@ #define SDHCI_QUIRK_FORCE_1_BIT_DATA (1<<22) /* Controller needs 10ms delay between applying power and clock */ #define SDHCI_QUIRK_DELAY_AFTER_POWER (1<<23) +/* Dove SDHCI has some issues in detecting IRQ */ +#define SDHCI_QUIRK_DISABLE_IRQ (1<<21) +/* Dove SDHCI needs dword access instead word accress */ +#define SDHCI_QUIRK_PIO_USE_WORD_ACCESS (1<<25) +/* Dove SDHCI needs dword access instead word accress */ +#define SDHCI_QUIRK_HIGH_SPEED_WA (1<<26) int irq; /* Device IRQ */ void __iomem * ioaddr; /* Mapped address */ - + struct resource *res; const struct sdhci_ops *ops; /* Low level hw interface */ /* Internal data */ @@ -284,10 +291,12 @@ struct timer_list timer; /* Timer for timeouts */ + int high_speed_wa; /* high speed WA */ + + struct platform_device *plat_dev; unsigned long private[0] ____cacheline_aligned; }; - struct sdhci_ops { #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS u32 (*readl)(struct sdhci_host *host, int reg); @@ -304,6 +313,8 @@ unsigned int (*get_max_clock)(struct sdhci_host *host); unsigned int (*get_min_clock)(struct sdhci_host *host); unsigned int (*get_timeout_clock)(struct sdhci_host *host); + void (*gpio_irq_enable)(struct sdhci_host *host); + void (*gpio_irq_disable)(struct sdhci_host *host); }; #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS --- linux-mvl-dove-2.6.31.orig/drivers/mmc/host/sdhci.c +++ linux-mvl-dove-2.6.31/drivers/mmc/host/sdhci.c @@ -12,12 +12,14 @@ * * - JMicron (hardware and technical support) */ - +//#define DEBUG +//#define VERBOSE #include #include #include #include #include +#include #include @@ -31,7 +33,7 @@ pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x) #if defined(CONFIG_LEDS_CLASS) || (defined(CONFIG_LEDS_CLASS_MODULE) && \ - defined(CONFIG_MMC_SDHCI_MODULE)) + defined(CONFIG_MMC_SDHCI_MODULE)) #define SDHCI_USE_LEDS_CLASS #endif @@ -42,14 +44,18 @@ static void sdhci_send_command(struct sdhci_host *, struct mmc_command *); static void sdhci_finish_command(struct sdhci_host *); - +//static void sdhci_sdio_gpio_irq_dump(struct sdhci_host *host); static void sdhci_dumpregs(struct sdhci_host *host) { printk(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n"); printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n", sdhci_readl(host, SDHCI_DMA_ADDRESS), +#if !defined(CONFIG_ARCH_DOVE) sdhci_readw(host, SDHCI_HOST_VERSION)); +#else + 0/*sdhci_readw(host + SDHCI_HOST_VERSION)*/); +#endif printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n", sdhci_readw(host, SDHCI_BLOCK_SIZE), sdhci_readw(host, SDHCI_BLOCK_COUNT)); @@ -73,7 +79,11 @@ sdhci_readl(host, SDHCI_SIGNAL_ENABLE)); printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n", sdhci_readw(host, SDHCI_ACMD12_ERR), +#if !defined(CONFIG_ARCH_DOVE) sdhci_readw(host, SDHCI_SLOT_INT_STATUS)); +#else + 0/*sdhci_readw(host, SDHCI_SLOT_INT_STATUS)*/); +#endif printk(KERN_DEBUG DRIVER_NAME ": Caps: 0x%08x | Max curr: 0x%08x\n", sdhci_readl(host, SDHCI_CAPABILITIES), sdhci_readl(host, SDHCI_MAX_CURRENT)); @@ -83,6 +93,7 @@ readl(host->ioaddr + SDHCI_ADMA_ERROR), readl(host->ioaddr + SDHCI_ADMA_ADDRESS)); +// sdhci_sdio_gpio_irq_dump(host); printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n"); } @@ -260,10 +271,21 @@ while (len) { if (chunk == 0) { - scratch = sdhci_readl(host, SDHCI_BUFFER); + if (!(host->quirks & SDHCI_QUIRK_PIO_USE_WORD_ACCESS)) + scratch = sdhci_readl(host, SDHCI_BUFFER); + else { + /* + * Marvell soc sdhci needs the cpu to + * read each data register seperatelty + */ + scratch = sdhci_readw(host, SDHCI_BUFFER); + + if (blksize > 2) + scratch |= sdhci_readw(host, + SDHCI_BUFFER + 2) << 16; + } chunk = 4; } - *buf = scratch & 0xFF; buf++; @@ -312,7 +334,17 @@ len--; if ((chunk == 4) || ((len == 0) && (blksize == 0))) { - sdhci_writel(host, scratch, SDHCI_BUFFER); + if (!(host->quirks & SDHCI_QUIRK_PIO_USE_WORD_ACCESS)) + sdhci_writel(host, scratch, SDHCI_BUFFER); + else { + /* + * Marvell soc sdhci needs the cpu to + * write each data register seperatelty + */ + sdhci_writew(host, scratch, SDHCI_BUFFER); + scratch = (0xFFFF0000 & scratch) >> 16; + sdhci_writew(host, scratch, SDHCI_BUFFER + 2); + } chunk = 0; scratch = 0; } @@ -852,7 +884,8 @@ sdhci_reset(host, SDHCI_RESET_CMD); sdhci_reset(host, SDHCI_RESET_DATA); } - + DBG(KERN_ERR "%s: %s data->stop->opcode 0x%x\n", + mmc_hostname(host->mmc), __func__, data->stop->opcode); sdhci_send_command(host, data->stop); } else tasklet_schedule(&host->finish_tasklet); @@ -866,6 +899,17 @@ WARN_ON(host->cmd); + if (host->ops->gpio_irq_disable) + host->ops->gpio_irq_disable(host); + + if (cmd->data && (cmd->data->blksz & 0x3)) { + printk(KERN_ERR "%s: Unsupported block size (%d)!\n", + mmc_hostname(host->mmc), cmd->data->blksz); + cmd->error = -EINVAL; + tasklet_schedule(&host->finish_tasklet); + return; + } + /* Wait max 10 ms */ timeout = 10; @@ -925,6 +969,11 @@ if (cmd->data) flags |= SDHCI_CMD_DATA; +#if defined(CONFIG_ARCH_DOVE) + //maen - ugly workarround for first scan of cards. + if (cmd->opcode == 5) + mdelay(10); +#endif sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); } @@ -1149,7 +1198,8 @@ else ctrl &= ~SDHCI_CTRL_4BITBUS; - if (ios->timing == MMC_TIMING_SD_HS) + if ((ios->timing == MMC_TIMING_SD_HS) && + (!host->quirks & SDHCI_QUIRK_HIGH_SPEED_WA)) ctrl |= SDHCI_CTRL_HISPD; else ctrl &= ~SDHCI_CTRL_HISPD; @@ -1213,7 +1263,7 @@ spin_unlock_irqrestore(&host->lock, flags); } -static const struct mmc_host_ops sdhci_ops = { +static struct mmc_host_ops sdhci_ops = { .request = sdhci_request, .set_ios = sdhci_set_ios, .get_ro = sdhci_get_ro, @@ -1232,7 +1282,6 @@ unsigned long flags; host = (struct sdhci_host*)param; - spin_lock_irqsave(&host->lock, flags); if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) { @@ -1251,7 +1300,6 @@ } spin_unlock_irqrestore(&host->lock, flags); - mmc_detect_change(host->mmc, msecs_to_jiffies(200)); } @@ -1304,6 +1352,10 @@ #endif mmiowb(); + + if (host->ops->gpio_irq_enable) + host->ops->gpio_irq_enable(host); + spin_unlock_irqrestore(&host->lock, flags); mmc_request_done(host->mmc, mrq); @@ -1496,6 +1548,7 @@ u32 intmask; int cardint = 0; + spin_lock(&host->lock); intmask = sdhci_readl(host, SDHCI_INT_STATUS); @@ -1507,7 +1560,9 @@ DBG("*** %s got interrupt: 0x%08x\n", mmc_hostname(host->mmc), intmask); - +#ifdef VERBOSE + sdhci_dumpregs(host); +#endif if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS); @@ -1575,6 +1630,16 @@ \*****************************************************************************/ #ifdef CONFIG_PM +static int sdhci_platform_suspend(struct platform_device *dev, + pm_message_t state) { + /* TODO: Add support for the SDHCI suspend resume */ + return 0; +} + +static int sdhci_platform_resume(struct platform_device *dev) { + /* TODO: Add support for the SDHCI suspend resume */ + return 0; +} int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state) { @@ -1665,8 +1730,11 @@ host->quirks = debug_quirks; sdhci_reset(host, SDHCI_RESET_ALL); - +#if !defined(CONFIG_ARCH_DOVE) host->version = sdhci_readw(host, SDHCI_HOST_VERSION); +#else + host->version = 0;// readw(host->ioaddr + SDHCI_HOST_VERSION); +#endif host->version = (host->version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT; if (host->version > SDHCI_SPEC_200) { @@ -1676,7 +1744,17 @@ } caps = sdhci_readl(host, SDHCI_CAPABILITIES); +#if !defined(CONFIG_ARCH_DOVE) + /* + * fix the clock rate value, should be 0x32 instead of 0x30 + * as the clock is 50MHz + */ + caps &= ~SDHCI_CLOCK_BASE_MASK; + caps |= 0x32 << SDHCI_CLOCK_BASE_SHIFT; + caps &= ~SDHCI_TIMEOUT_CLK_MASK; + caps |= 0x32; +#endif if (host->quirks & SDHCI_QUIRK_FORCE_DMA) host->flags |= SDHCI_USE_DMA; else if (!(caps & SDHCI_CAN_DO_DMA)) @@ -1776,12 +1854,16 @@ mmc->f_min = host->ops->get_min_clock(host); else mmc->f_min = host->max_clk / 256; + mmc->f_max = host->max_clk; mmc->caps = MMC_CAP_SDIO_IRQ; if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) mmc->caps |= MMC_CAP_4_BIT_DATA; + if (host->quirks & SDHCI_QUIRK_DISABLE_IRQ) + mmc->caps &= ~MMC_CAP_SDIO_IRQ; + if (caps & SDHCI_CAN_DO_HISPD) mmc->caps |= MMC_CAP_SD_HIGHSPEED; @@ -1865,6 +1947,9 @@ setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host); + printk(KERN_INFO DRIVER_NAME ": Requesting irq host->irq=%d, host->irqn", + host->irq); + ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, mmc_hostname(mmc), host); if (ret) @@ -1939,6 +2024,7 @@ sdhci_disable_card_detection(host); mmc_remove_host(host->mmc); + DBG("slot 0 at 0x%p, irq %d\n", host->ioaddr, host->irq); #ifdef SDHCI_USE_LEDS_CLASS led_classdev_unregister(&host->led); --- linux-mvl-dove-2.6.31.orig/drivers/mmc/host/Makefile +++ linux-mvl-dove-2.6.31/drivers/mmc/host/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_MMC_MXC) += mxcmmc.o obj-$(CONFIG_MMC_SDHCI) += sdhci.o obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o +obj-$(CONFIG_MMC_SDHCI_MV) += sdhci-mv.o obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o --- linux-mvl-dove-2.6.31.orig/drivers/mmc/host/sdhci-mv.c +++ linux-mvl-dove-2.6.31/drivers/mmc/host/sdhci-mv.c @@ -0,0 +1,313 @@ +/* + * Marvell bindings for Secure Digital Host Controller Interface. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ +//#define DEBUG +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sdhci.h" + +#define DRIVER_NAME "sdhci-mv" + +struct sdhci_mv_host { + /* for dove card interrupt workaround */ + int dove_card_int_wa; + struct sdhci_dove_int_wa dove_int_wa_info; +#if defined(CONFIG_HAVE_CLK) + struct clk *clk; +#endif + +}; +#ifdef CONFIG_PM + +static int sdhci_mv_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct sdhci_host *host = dev_get_drvdata(&pdev->dev); + + return sdhci_suspend_host(host, state); +} + +static int sdhci_mv_resume(struct platform_device *pdev) +{ + struct sdhci_host *host = dev_get_drvdata(&pdev->dev); + + { + u32 ier = sdhci_readl(host, SDHCI_INT_ENABLE); + ier |= SDHCI_INT_CARD_INSERT; + ier |= SDHCI_INT_CARD_REMOVE; + sdhci_writel(host, ier, SDHCI_INT_ENABLE); + } + mmiowb(); + mdelay(400); + return sdhci_resume_host(host); +} + +#else + +#define sdhci_mv_suspend NULL +#define sdhci_mv_resume NULL + +#endif +static void sdhci_sdio_gpio_irq_enable(struct sdhci_host *host); +static void sdhci_sdio_gpio_irq_disable(struct sdhci_host *host); + +static struct sdhci_ops sdhci_mv_ops = { + .gpio_irq_enable = sdhci_sdio_gpio_irq_enable, + .gpio_irq_disable = sdhci_sdio_gpio_irq_disable, +}; + +static irqreturn_t sdhci_dove_gpio_irq(int irq, void *dev_id) +{ + struct sdhci_host* host = dev_id; +#ifdef VERBOSE + DBG("*** %s got gpio interrupt\n", + mmc_hostname(host->mmc)); +#endif + +#ifdef VERBOSE + sdhci_dumpregs(host); +#endif + mmc_signal_sdio_irq(host->mmc); + + return IRQ_HANDLED; +} + + +static void sdhci_enable_sdio_gpio_irq(struct mmc_host *mmc, int enable) +{ + struct sdhci_host *host = mmc_priv(mmc); + struct sdhci_mv_host *mv_host = sdhci_priv(host); + unsigned long flags; + struct sdhci_dove_int_wa *wa_info; + + if (!mv_host->dove_card_int_wa) + return; + + wa_info = &mv_host->dove_int_wa_info; + spin_lock_irqsave(&host->lock, flags); + + if (enable) { + if (wa_info->status == 0) { + enable_irq(wa_info->irq); + wa_info->status = 1; + } + } else { + if (wa_info->status == 1) { + disable_irq_nosync(wa_info->irq); + wa_info->status = 0; + } + } + + mmiowb(); + + spin_unlock_irqrestore(&host->lock, flags); +} + +static void sdhci_sdio_gpio_irq_enable(struct sdhci_host *host) +{ + struct sdhci_mv_host *mv_host = sdhci_priv(host); + u32 mpp_ctrl4; + if (!mv_host->dove_card_int_wa) + return; + + mpp_ctrl4 = readl(DOVE_MPP_CTRL4_VIRT_BASE); + mpp_ctrl4 |= mv_host->dove_int_wa_info.func_select_bit << 1; + writel(mpp_ctrl4, DOVE_MPP_CTRL4_VIRT_BASE); + + mmiowb(); +} + +static void sdhci_sdio_gpio_irq_disable(struct sdhci_host *host) +{ + struct sdhci_mv_host *mv_host = sdhci_priv(host); + u32 mpp_ctrl4; + + if (!mv_host->dove_card_int_wa) + return; + + mpp_ctrl4 = readl(DOVE_MPP_CTRL4_VIRT_BASE); + mpp_ctrl4 &= ~(mv_host->dove_int_wa_info.func_select_bit << 1); + writel(mpp_ctrl4, DOVE_MPP_CTRL4_VIRT_BASE); + + mmiowb(); +} +#ifdef DEBUG +static void sdhci_sdio_gpio_irq_dump(struct sdhci_host *host) +{ + struct sdhci_mv_host *mv_host = sdhci_priv(host); + int gpio; + + if (!mv_host->dove_card_int_wa) + return; + + gpio = mv_host->dove_int_wa_info.gpio; + + printk(" dump gpio irq regs:\n"); + printk(" mpp ctrl 4 [0x%x] 0x%08x\n", DOVE_MPP_CTRL4_VIRT_BASE, + readl(DOVE_MPP_CTRL4_VIRT_BASE)); + printk(" gpio level [0x%x] 0x%08x\n", GPIO_LEVEL_MASK(gpio), + readl(GPIO_LEVEL_MASK(gpio))); + printk(" gpio pol [0x%x] 0x%08x\n", GPIO_IN_POL(gpio), + readl(GPIO_IN_POL(gpio))); + printk(" gpio data in [0x%x] 0x%08x\n", GPIO_DATA_IN(gpio), + readl(GPIO_DATA_IN(gpio))); +} +#endif +static int __devinit sdhci_mv_probe(struct platform_device *pdev) +{ + struct sdhci_host *host; + struct sdhci_mv_host *mv_host; + struct resource *r; + struct sdhci_dove_int_wa *data = (struct sdhci_dove_int_wa *) + pdev->dev.platform_data; + int ret = 0; + + host = sdhci_alloc_host(&pdev->dev, sizeof(*mv_host)); + if (IS_ERR(host)) { + dev_err(&pdev->dev, "failed to alloc sdhci host\n"); + return -ENOMEM; + } + mv_host = sdhci_priv(host); + dev_set_drvdata(&pdev->dev, host); + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + goto err_get_resource; + ret = -ENXIO; + } + + host->irq = platform_get_irq(pdev, 0); + if (host->irq < 0) { + goto err_get_resource; + ret = -ENXIO; + } + r = devm_request_mem_region(&pdev->dev, r->start, SZ_4K, DRIVER_NAME); + if (!r) { + dev_err(&pdev->dev, "cannot request region\n"); + ret = -EINVAL; + goto err_request_region; + } + + dev_dbg(&pdev->dev, "r->start=0x%x\n", r->start); + + host->ioaddr = devm_ioremap(&pdev->dev, r->start, SZ_4K); + + dev_dbg(&pdev->dev, "slot 0 at 0x%p, irq %d\n", host->ioaddr, host->irq); + + if (!host->ioaddr) { + ret = -EINVAL; + goto err_ioremap; + } + + host->hw_name = dev_name(&pdev->dev); + host->ops = &sdhci_mv_ops; + host->quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | + SDHCI_QUIRK_NO_BUSY_IRQ | + SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | + SDHCI_QUIRK_PIO_USE_WORD_ACCESS | + SDHCI_QUIRK_HIGH_SPEED_WA; + + if (data) { + dev_dbg(&pdev->dev, " request wa irq\n"); + mv_host->dove_card_int_wa = 1; + mv_host->dove_int_wa_info.irq = data->irq; + mv_host->dove_int_wa_info.gpio = data->gpio; + mv_host->dove_int_wa_info.func_select_bit = data->func_select_bit; + mv_host->dove_int_wa_info.status = 0; //disabled + ret = devm_request_irq(&pdev->dev, mv_host->dove_int_wa_info.irq, + sdhci_dove_gpio_irq, IRQF_DISABLED, + mmc_hostname(host->mmc), host); + if(ret) { + dev_err(&pdev->dev, "cannot request wa irq\n"); + goto err_request_irq; + } + + /* to balance disable/enable_irq */ + disable_irq_nosync(mv_host->dove_int_wa_info.irq); + + } else { + dev_dbg(&pdev->dev, " no request wa irq\n"); + mv_host->dove_card_int_wa = 0; + } + +#if defined(CONFIG_HAVE_CLK) + mv_host->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(mv_host->clk)) + dev_notice(&pdev->dev, "cannot get clkdev\n"); + else + clk_enable(mv_host->clk); +#endif + + ret = sdhci_add_host(host); + if (ret) + goto err_add_host; + if (mv_host->dove_card_int_wa) + host->mmc->ops->enable_sdio_irq = sdhci_enable_sdio_gpio_irq; + return 0; + +err_add_host: +err_request_irq: +err_ioremap: +err_request_region: +err_get_resource: + sdhci_free_host(host); + return ret; +} + +static int __devexit sdhci_mv_remove(struct platform_device *pdev) +{ + struct sdhci_host *host = dev_get_drvdata(&pdev->dev); +#if defined(CONFIG_HAVE_CLK) + struct sdhci_mv_host *mv_host = sdhci_priv(host); +#endif + + sdhci_remove_host(host, 0); + sdhci_free_host(host); +#if defined(CONFIG_HAVE_CLK) + if (!IS_ERR(mv_host->clk)) { + clk_disable(mv_host->clk); + clk_put(mv_host->clk); + } +#endif + + return 0; +} + +static struct platform_driver sdhci_mv_driver = { + .probe = sdhci_mv_probe, + .remove = __devexit_p(sdhci_mv_remove), + .suspend = sdhci_mv_suspend, + .resume = sdhci_mv_resume, + .driver = { + .name = "sdhci-mv", + .owner = THIS_MODULE, + }, +}; + +static int __init sdhci_mv_init(void) +{ + return platform_driver_register(&sdhci_mv_driver); +} +module_init(sdhci_mv_init); + +static void __exit sdhci_mv_exit(void) +{ + platform_driver_unregister(&sdhci_mv_driver); +} +module_exit(sdhci_mv_exit); + +MODULE_DESCRIPTION("Secure Digital Host Controller Interface MV driver"); +MODULE_AUTHOR("Saeed Bishara "); +MODULE_LICENSE("GPL"); --- linux-mvl-dove-2.6.31.orig/drivers/mmc/card/block.c +++ linux-mvl-dove-2.6.31/drivers/mmc/card/block.c @@ -88,6 +88,12 @@ int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT; __clear_bit(devidx, dev_use); + /* + * We are about to drop the last reference to the disk object. + * Nothing else should now be looking at the queue pointer, so + * now it won't hurt if we release it. + */ + blk_cleanup_queue(md->disk->queue); put_disk(md->disk); kfree(md); } --- linux-mvl-dove-2.6.31.orig/drivers/mmc/card/queue.c +++ linux-mvl-dove-2.6.31/drivers/mmc/card/queue.c @@ -245,7 +245,12 @@ kfree(mq->bounce_buf); mq->bounce_buf = NULL; - blk_cleanup_queue(mq->queue); + /* + * Calling blk_cleanup_queue() would be too soon here. As long as + * the gendisk has a reference to it and is not released we should + * keep the queue. It has been shutdown and will not accept any new + * requests, so that should be safe. + */ mq->card = NULL; } --- linux-mvl-dove-2.6.31.orig/drivers/mmc/core/mmc_ops.c +++ linux-mvl-dove-2.6.31/drivers/mmc/core/mmc_ops.c @@ -19,6 +19,39 @@ #include "core.h" #include "mmc_ops.h" +int mmc_force_reset (struct mmc_host *host) + +{ + struct mmc_command cmd; + int err = 0; + + BUG_ON(!host); + +#ifndef SD_IO_RW_DIRECT +#define SD_IO_RW_DIRECT 52 +#endif + +#ifndef SDIO_CCCR_ABORT +#define SDIO_CCCR_ABORT 0x06 +#endif + +#ifndef PMR_WRITE +#define PMR_WRITE 1 +#endif + + memset(&cmd, 0, sizeof(struct mmc_command)); + cmd.opcode = SD_IO_RW_DIRECT; + cmd.arg = PMR_WRITE ? 0x80000000 : 0x00000000; + cmd.arg |= 0<<28; + cmd.arg |= 0x00000000; + cmd.arg |= SDIO_CCCR_ABORT << 9; + cmd.arg |= (1<<3) ; + cmd.flags = MMC_RSP_NONE; + err = mmc_wait_for_cmd(host, &cmd, 0); + return err; +} + + static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card) { int err; @@ -111,6 +144,11 @@ for (i = 100; i; i--) { err = mmc_wait_for_cmd(host, &cmd, 0); + if (err == -ETIMEDOUT) { + mmc_delay(10); + continue; + } + if (err) break; --- linux-mvl-dove-2.6.31.orig/drivers/mmc/core/mmc_ops.h +++ linux-mvl-dove-2.6.31/drivers/mmc/core/mmc_ops.h @@ -12,6 +12,7 @@ #ifndef _MMC_MMC_OPS_H #define _MMC_MMC_OPS_H +int mmc_force_reset (struct mmc_host *host); int mmc_select_card(struct mmc_card *card); int mmc_deselect_cards(struct mmc_host *host); int mmc_go_idle(struct mmc_host *host); --- linux-mvl-dove-2.6.31.orig/drivers/mmc/core/core.c +++ linux-mvl-dove-2.6.31/drivers/mmc/core/core.c @@ -890,6 +890,10 @@ mmc_claim_host(host); mmc_power_up(host); +#if 0 + /* reset sdio hardware */ /* Maen */ + mmc_force_reset(host); +#endif mmc_go_idle(host); mmc_send_if_cond(host, host->ocr_avail); @@ -917,7 +921,11 @@ /* * ...and finally MMC. */ +#ifdef CONFIG_ARCH_DOVE + err = mmc_send_op_cond(host, 0x40000, &ocr); +#else err = mmc_send_op_cond(host, 0, &ocr); +#endif if (!err) { if (mmc_attach_mmc(host, ocr)) mmc_power_off(host); --- linux-mvl-dove-2.6.31.orig/drivers/mmc/core/mmc.c +++ linux-mvl-dove-2.6.31/drivers/mmc/core/mmc.c @@ -121,7 +121,7 @@ * v1.2 has extra information in bits 15, 11 and 10. */ csd_struct = UNSTUFF_BITS(resp, 126, 2); - if (csd_struct != 1 && csd_struct != 2) { + if (csd_struct != 1 && csd_struct != 2 && csd_struct != 3) { printk(KERN_ERR "%s: unrecognised CSD structure version %d\n", mmc_hostname(card->host), csd_struct); return -EINVAL; @@ -180,11 +180,11 @@ err = mmc_send_ext_csd(card, ext_csd); if (err) { - /* - * We all hosts that cannot perform the command - * to fail more gracefully - */ - if (err != -EINVAL) + /* If the host or the card can't do the switch, + * fail more gracefully. */ + if ((err != -EINVAL) + && (err != -ENOSYS) + && (err != -EFAULT)) goto out; /* --- linux-mvl-dove-2.6.31.orig/drivers/mmc/core/sd.c +++ linux-mvl-dove-2.6.31/drivers/mmc/core/sd.c @@ -210,11 +210,11 @@ err = mmc_sd_switch(card, 0, 0, 1, status); if (err) { - /* - * We all hosts that cannot perform the command - * to fail more gracefully - */ - if (err != -EINVAL) + /* If the host or the card can't do the switch, + * fail more gracefully. */ + if ((err != -EINVAL) + && (err != -ENOSYS) + && (err != -EFAULT)) goto out; printk(KERN_WARNING "%s: problem reading switch " --- linux-mvl-dove-2.6.31.orig/drivers/video/vesafb.c +++ linux-mvl-dove-2.6.31/drivers/video/vesafb.c @@ -28,6 +28,12 @@ #define dac_reg (0x3c8) #define dac_val (0x3c9) +struct vesafb_info +{ + u32 pseudo_palette[256]; + int mtrr_hdl; +}; + /* --------------------------------------------------------------------- */ static struct fb_var_screeninfo vesafb_defined __initdata = { @@ -47,16 +53,37 @@ .accel = FB_ACCEL_NONE, }; +#ifndef MODULE static int inverse __read_mostly; +#endif static int mtrr __read_mostly; /* disable mtrr */ static int vram_remap __initdata; /* Set amount of memory to be used */ static int vram_total __initdata; /* Set total amount of memory */ static int pmi_setpal __read_mostly = 1; /* pmi for palette changes ??? */ +static int redraw __read_mostly; static int ypan __read_mostly; /* 0..nothing, 1..ypan, 2..ywrap */ +static int ywrap __read_mostly; static void (*pmi_start)(void) __read_mostly; static void (*pmi_pal) (void) __read_mostly; static int depth __read_mostly; static int vga_compat __read_mostly; + +module_param(redraw, bool, 0); +module_param(ypan, bool, 0); +module_param(ywrap, bool, 0); +module_param_named(vgapal, pmi_setpal, invbool, 0); +MODULE_PARM_DESC(vgapal, "Use VGA for setting palette (default)"); +module_param_named(pmipal, pmi_setpal, bool, 0); +MODULE_PARM_DESC(pmipal, "Use PMI for setting palette"); +module_param(mtrr, bool, 0); +MODULE_PARM_DESC(mtrr, "Enable MTRR support (default)"); +module_param_named(nomtrr, mtrr, invbool, 0); +MODULE_PARM_DESC(nomtrr, "Disable MTRR support"); +module_param(vram_remap, int, 0); +MODULE_PARM_DESC(vram_remap, "Set total amount of memory to be used"); +module_param(vram_total, int, 0); +MODULE_PARM_DESC(vram_total, "Total amount of memory"); + /* --------------------------------------------------------------------- */ static int vesafb_pan_display(struct fb_var_screeninfo *var, @@ -192,6 +219,7 @@ .fb_imageblit = cfb_imageblit, }; +#ifndef MODULE static int __init vesafb_setup(char *options) { char *this_opt; @@ -225,6 +253,7 @@ } return 0; } +#endif static int __init vesafb_probe(struct platform_device *dev) { @@ -476,8 +505,28 @@ return err; } +static int __exit vesafb_remove(struct platform_device *device) +{ + struct fb_info *info = dev_get_drvdata(&device->dev); + + unregister_framebuffer(info); +#ifdef CONFIG_MTRR + { + struct vesafb_info *vfb_info = (struct vesafb_info *) info->par; + if (vfb_info->mtrr_hdl >= 0) + mtrr_del(vfb_info->mtrr_hdl, 0, 0); + } +#endif + iounmap(info->screen_base); + framebuffer_release(info); + release_mem_region(vesafb_fix.smem_start, vesafb_fix.smem_len); + + return 0; +} + static struct platform_driver vesafb_driver = { .probe = vesafb_probe, + .remove = vesafb_remove, .driver = { .name = "vesafb", }, @@ -488,11 +537,18 @@ static int __init vesafb_init(void) { int ret; +#ifndef MODULE char *option = NULL; /* ignore error return of fb_get_options */ fb_get_options("vesafb", &option); vesafb_setup(option); +#else + if (redraw) + ypan = 0; + if (ywrap) + ypan = 2; +#endif ret = platform_driver_register(&vesafb_driver); if (!ret) { @@ -511,6 +567,14 @@ return ret; } + +static void __exit vesafb_exit(void) +{ + platform_device_unregister(vesafb_device); + platform_driver_unregister(&vesafb_driver); +} + module_init(vesafb_init); +module_exit(vesafb_exit); MODULE_LICENSE("GPL"); --- linux-mvl-dove-2.6.31.orig/drivers/video/fb_ddc.c +++ linux-mvl-dove-2.6.31/drivers/video/fb_ddc.c @@ -40,9 +40,28 @@ "block.\n"); return NULL; } - - if (i2c_transfer(adapter, msgs, 2) == 2) + if (adapter->algo->master_xfer) { + if (i2c_transfer(adapter, msgs, 2) == 2) + return buf; + } else { + int i; + dev_info(&adapter->dev, "use SMBUS adapter for reading EDID\n"); + if (0 != i2c_smbus_xfer(adapter, msgs[0].addr, msgs[0].flags, + I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE_DATA, buf)) { + printk("%s: failed for address 0\n", __func__); + return NULL; + } + for (i=0; i < EDID_LENGTH; i++) { + if (0 != i2c_smbus_xfer(adapter, msgs[1].addr, 0, + I2C_SMBUS_READ, i, I2C_SMBUS_BYTE_DATA, + buf + i)) { + printk("%s: failed for address %d\n", __func__, i); + return NULL; + } + + } return buf; + } dev_warn(&adapter->dev, "unable to read EDID block.\n"); kfree(buf); @@ -55,6 +74,15 @@ unsigned char *edid = NULL; int i, j; + if (!algo_data) { + /* No direct control on I2C bus */ + for (i = 0; i < 3; i++) { + edid = fb_do_probe_ddc_edid(adapter); + if (edid) + break; + } + return edid; + } algo_data->setscl(algo_data->data, 1); for (i = 0; i < 3; i++) { --- linux-mvl-dove-2.6.31.orig/drivers/video/Kconfig +++ linux-mvl-dove-2.6.31/drivers/video/Kconfig @@ -19,6 +19,23 @@ This framework adds support for low-level control of the video output switch. + +config DOVE_GPU + bool "Enable DOVE GPU support" + depends on ARCH_DOVE + default y + help + This framework adds support for dove gpu. + +config DOVE_GPU_MEM_SIZE + int "DOVE GPU memory size (MB)" + depends on DOVE_GPU + default 128 + help + Set the memory size to be reserved for GPU usage. The value should be + between 64 and 128. + + menuconfig FB tristate "Support for frame buffer devices" ---help--- @@ -686,8 +703,8 @@ If unsure, say N. config FB_VESA - bool "VESA VGA graphics support" - depends on (FB = y) && X86 + tristate "VESA VGA graphics support" + depends on FB && X86 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -2148,6 +2165,7 @@ and could also have been called by other names when coupled with a bridge adapter. +source "drivers/video/marvell/Kconfig" source "drivers/video/omap/Kconfig" source "drivers/video/backlight/Kconfig" --- linux-mvl-dove-2.6.31.orig/drivers/video/uvesafb.c +++ linux-mvl-dove-2.6.31/drivers/video/uvesafb.c @@ -67,12 +67,14 @@ * find the kernel part of the task struct, copy the registers and * the buffer contents and then complete the task. */ -static void uvesafb_cn_callback(void *data) +static void uvesafb_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) { - struct cn_msg *msg = data; struct uvesafb_task *utask; struct uvesafb_ktask *task; + if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN)) + return; + if (msg->seq >= UVESAFB_TASKS_MAX) return; --- linux-mvl-dove-2.6.31.orig/drivers/video/s3c-fb.c +++ linux-mvl-dove-2.6.31/drivers/video/s3c-fb.c @@ -1036,7 +1036,7 @@ static struct platform_driver s3c_fb_driver = { .probe = s3c_fb_probe, - .remove = s3c_fb_remove, + .remove = __devexit_p(s3c_fb_remove), .suspend = s3c_fb_suspend, .resume = s3c_fb_resume, .driver = { --- linux-mvl-dove-2.6.31.orig/drivers/video/fbmon.c +++ linux-mvl-dove-2.6.31/drivers/video/fbmon.c @@ -40,8 +40,8 @@ * EDID parser */ -#undef DEBUG /* define this for verbose EDID parsing output */ - +//#undef DEBUG /* define this for verbose EDID parsing output */ +#define DEBUG #ifdef DEBUG #define DPRINTK(fmt, args...) printk(fmt,## args) #else --- linux-mvl-dove-2.6.31.orig/drivers/video/Makefile +++ linux-mvl-dove-2.6.31/drivers/video/Makefile @@ -28,6 +28,8 @@ obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o # Hardware specific drivers go first +obj-$(CONFIG_FB_DOVE) += marvell/ + obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o obj-$(CONFIG_FB_ARC) += arcfb.o obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o --- linux-mvl-dove-2.6.31.orig/drivers/video/fbmem.c +++ linux-mvl-dove-2.6.31/drivers/video/fbmem.c @@ -1351,7 +1351,11 @@ vma->vm_pgoff = off >> PAGE_SHIFT; /* This is an IO map - tell maydump to skip this VMA */ vma->vm_flags |= VM_IO | VM_RESERVED; - fb_pgprotect(file, vma, off); + /* io control needs non-cacheable attribute. */ + if (start == info->fix.mmio_start) + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + else + fb_pgprotect(file, vma, off); if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; --- linux-mvl-dove-2.6.31.orig/drivers/video/marvell/dovefb_gpio.c +++ linux-mvl-dove-2.6.31/drivers/video/marvell/dovefb_gpio.c @@ -0,0 +1,201 @@ +#include +#include +#include +#include