rk3066 add phone pad modem support

This commit is contained in:
蓝斌元
2013-03-06 18:13:33 +08:00
parent cc29a5947e
commit 2fd93fbff1
55 changed files with 10067 additions and 2209 deletions

View File

@@ -0,0 +1,437 @@
CONFIG_EXPERIMENTAL=y
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_KERNEL_LZO=y
CONFIG_LOG_BUF_SHIFT=19
CONFIG_CGROUPS=y
CONFIG_CGROUP_DEBUG=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_RESOURCE_COUNTERS=y
CONFIG_CGROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_PANIC_TIMEOUT=1
# CONFIG_SYSCTL_SYSCALL is not set
# CONFIG_ELF_CORE is not set
CONFIG_ASHMEM=y
# CONFIG_AIO is not set
CONFIG_EMBEDDED=y
# CONFIG_SLUB_DEBUG is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_ARCH_RK30=y
CONFIG_CLK_SWITCH_TO_32K=y
CONFIG_MACH_RK30_Z600T=y
CONFIG_FIQ_DEBUGGER=y
CONFIG_FIQ_DEBUGGER_NO_SLEEP=y
CONFIG_FIQ_DEBUGGER_CONSOLE=y
CONFIG_FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
# CONFIG_SMP_ON_UP is not set
CONFIG_NR_CPUS=2
CONFIG_PREEMPT=y
CONFIG_AEABI=y
# CONFIG_OABI_COMPAT is not set
CONFIG_HIGHMEM=y
CONFIG_COMPACTION=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_CMDLINE="console=ttyFIQ0 androidboot.console=ttyFIQ0 init=/init"
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_CPU_FREQ_GOV_HOTPLUG=y
CONFIG_CPU_IDLE=y
CONFIG_VFP=y
CONFIG_NEON=y
CONFIG_WAKELOCK=y
CONFIG_PM_RUNTIME=y
CONFIG_PM_DEBUG=y
CONFIG_SUSPEND_TIME=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
CONFIG_NET_KEY=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_INET_ESP=y
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
CONFIG_IPV6=y
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
CONFIG_INET6_AH=y
CONFIG_INET6_ESP=y
CONFIG_INET6_IPCOMP=y
CONFIG_IPV6_MIP6=y
CONFIG_IPV6_TUNNEL=y
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_NETFILTER=y
# CONFIG_BRIDGE_NETFILTER is not set
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
CONFIG_NF_CT_PROTO_SCTP=y
CONFIG_NF_CT_PROTO_UDPLITE=y
CONFIG_NF_CONNTRACK_AMANDA=y
CONFIG_NF_CONNTRACK_FTP=y
CONFIG_NF_CONNTRACK_H323=y
CONFIG_NF_CONNTRACK_IRC=y
CONFIG_NF_CONNTRACK_NETBIOS_NS=y
CONFIG_NF_CONNTRACK_PPTP=y
CONFIG_NF_CONNTRACK_SANE=y
CONFIG_NF_CONNTRACK_SIP=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
CONFIG_NETFILTER_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFLOG=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
CONFIG_NETFILTER_XT_TARGET_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_TRACE=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
CONFIG_NETFILTER_XT_MATCH_HELPER=y
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
CONFIG_NETFILTER_XT_MATCH_LENGTH=y
CONFIG_NETFILTER_XT_MATCH_LIMIT=y
CONFIG_NETFILTER_XT_MATCH_MAC=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
CONFIG_NETFILTER_XT_MATCH_STRING=y
CONFIG_NETFILTER_XT_MATCH_TIME=y
CONFIG_NETFILTER_XT_MATCH_U32=y
CONFIG_NF_CONNTRACK_IPV4=y
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_MATCH_AH=y
CONFIG_IP_NF_MATCH_ECN=y
CONFIG_IP_NF_MATCH_TTL=y
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_TARGET_REJECT=y
CONFIG_IP_NF_TARGET_REJECT_SKERR=y
CONFIG_IP_NF_TARGET_LOG=y
CONFIG_NF_NAT=y
CONFIG_IP_NF_TARGET_MASQUERADE=y
CONFIG_IP_NF_TARGET_NETMAP=y
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
CONFIG_NF_CONNTRACK_IPV6=y
CONFIG_IP6_NF_IPTABLES=y
CONFIG_IP6_NF_TARGET_LOG=y
CONFIG_IP6_NF_FILTER=y
CONFIG_IP6_NF_TARGET_REJECT=y
CONFIG_IP6_NF_TARGET_REJECT_SKERR=y
CONFIG_IP6_NF_MANGLE=y
CONFIG_IP6_NF_RAW=y
CONFIG_BRIDGE=y
# CONFIG_BRIDGE_IGMP_SNOOPING is not set
CONFIG_PHONET=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS_U32=y
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_U32=y
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=y
CONFIG_NET_ACT_GACT=y
CONFIG_NET_ACT_MIRRED=y
CONFIG_BT=y
CONFIG_BT_L2CAP=y
CONFIG_BT_SCO=y
CONFIG_BT_RFCOMM=y
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_BNEP=y
CONFIG_BT_HIDP=y
CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_LL=y
CONFIG_BT_HCIBCM4325=y
CONFIG_BT_AUTOSLEEP=y
CONFIG_RFKILL=y
CONFIG_RFKILL_RK=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_FIRMWARE_IN_KERNEL is not set
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_NAND_IDS=y
CONFIG_MTD_RKNAND=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_MISC_DEVICES=y
CONFIG_UID_STAT=y
CONFIG_APANIC=y
CONFIG_BP_AUTO=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_MULTI_LUN=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
CONFIG_DM_UEVENT=y
CONFIG_NETDEVICES=y
CONFIG_PHYLIB=y
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
CONFIG_WLAN_80211=y
CONFIG_RKWIFI=y
CONFIG_RKWIFI_26M=y
CONFIG_USB_USBNET=y
CONFIG_PPP=y
CONFIG_PPP_MULTILINK=y
CONFIG_PPP_FILTER=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_MPPE=y
CONFIG_PPPOLAC=y
CONFIG_PPPOPNS=y
# CONFIG_INPUT_MOUSEDEV is not set
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
# CONFIG_KEYBOARD_ATKBD is not set
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_JOYSTICK=y
CONFIG_JOYSTICK_XPAD=y
CONFIG_JOYSTICK_XPAD_FF=y
CONFIG_JOYSTICK_XPAD_LEDS=y
CONFIG_INPUT_TABLET=y
CONFIG_TABLET_USB_ACECAD=y
CONFIG_TABLET_USB_AIPTEK=y
CONFIG_TABLET_USB_GTCO=y
CONFIG_TABLET_USB_HANWANG=y
CONFIG_TABLET_USB_KBTAB=y
CONFIG_TABLET_USB_WACOM=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_CT36X=y
CONFIG_TOUCHSCREEN_CT36X_PLATFORM_ROCKCHIP=y
CONFIG_TOUCHSCREEN_CT36X_CHIP_CT365=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_KEYCHORD=y
CONFIG_INPUT_UINPUT=y
CONFIG_GS_MMA8452=y
CONFIG_SENSOR_DEVICE=y
CONFIG_GSENSOR_DEVICE=y
# CONFIG_SERIO is not set
# CONFIG_CONSOLE_TRANSLATIONS is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_RK29=y
CONFIG_UART0_RK29=y
CONFIG_UART0_CTS_RTS_RK29=y
CONFIG_UART3_RK29=y
CONFIG_UART3_CTS_RTS_RK29=y
# CONFIG_HW_RANDOM is not set
CONFIG_I2C=y
# CONFIG_I2C_COMPAT is not set
CONFIG_I2C0_CONTROLLER_RK30=y
CONFIG_I2C1_CONTROLLER_RK30=y
CONFIG_I2C2_CONTROLLER_RK30=y
CONFIG_I2C3_CONTROLLER_RK30=y
CONFIG_I2C4_CONTROLLER_RK30=y
CONFIG_RK_HEADSET_IRQ_HOOK_ADC_DET=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_WM831X=y
CONFIG_EXPANDED_GPIO_NUM=0
CONFIG_EXPANDED_GPIO_IRQ_NUM=0
CONFIG_SPI_FPGA_GPIO_NUM=0
CONFIG_SPI_FPGA_GPIO_IRQ_NUM=0
CONFIG_POWER_SUPPLY=y
CONFIG_WM831X_BACKUP=y
CONFIG_BATTERY_RK30_ADC_FAC=y
CONFIG_BATTERY_RK30_AC_CHARGE=y
CONFIG_BATTERY_RK30_USB_CHARGE=y
CONFIG_BATTERY_RK30_VOL3V8=y
CONFIG_POWER_ON_CHARGER_DISPLAY=y
CONFIG_WM8326_VBAT_LOW_DETECTION=y
CONFIG_CHARGER_SMB347=y
# CONFIG_HWMON is not set
CONFIG_MFD_TPS65910=y
CONFIG_MFD_WM831X_I2C=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_TPS65910=y
CONFIG_REGULATOR_WM831X=y
CONFIG_RK30_PWM_REGULATOR=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_VIDEO_DEV=y
CONFIG_SOC_CAMERA=y
CONFIG_SOC_CAMERA_OV2659=y
CONFIG_SOC_CAMERA_OV5640=y
CONFIG_VIDEO_RK29=y
CONFIG_VIDEO_RK29_CAMMEM_ION=y
CONFIG_ION=y
CONFIG_ION_ROCKCHIP=y
CONFIG_FB=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
# CONFIG_LCD_CLASS_DEVICE is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=y
# CONFIG_BACKLIGHT_GENERIC is not set
CONFIG_DISPLAY_SUPPORT=y
CONFIG_LCD_HJ101NA=y
CONFIG_FB_ROCKCHIP=y
CONFIG_DUAL_LCDC_DUAL_DISP_IN_KERNEL=y
CONFIG_LCDC_RK30=y
CONFIG_RK_HDMI=y
CONFIG_HDMI_RK30=y
CONFIG_HDMI_SOURCE_LCDC1=y
CONFIG_RGA_RK30=y
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
CONFIG_SOUND=y
CONFIG_SND=y
# CONFIG_SND_SUPPORT_OLD_API is not set
# CONFIG_SND_VERBOSE_PROCFS is not set
# CONFIG_SND_DRIVERS is not set
# CONFIG_SND_ARM is not set
CONFIG_SND_SOC=y
CONFIG_SND_RK29_SOC=y
CONFIG_SND_RK_SOC_I2S2_2CH=y
CONFIG_SND_I2S_DMA_EVENT_STATIC=y
CONFIG_SND_RK29_SOC_RT3224=y
CONFIG_SND_RK29_CODEC_SOC_SLAVE=y
CONFIG_HID_A4TECH=y
CONFIG_HID_ACRUX=y
CONFIG_HID_ACRUX_FF=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
CONFIG_HID_DRAGONRISE=y
CONFIG_DRAGONRISE_FF=y
CONFIG_HID_EMS_FF=y
CONFIG_HID_ELECOM=y
CONFIG_HID_EZKEY=y
CONFIG_HID_KEYTOUCH=y
CONFIG_HID_KYE=y
CONFIG_HID_UCLOGIC=y
CONFIG_HID_WALTOP=y
CONFIG_HID_GYRATION=y
CONFIG_HID_TWINHAN=y
CONFIG_HID_KENSINGTON=y
CONFIG_HID_LCPOWER=y
CONFIG_HID_LOGITECH=y
CONFIG_LOGITECH_FF=y
CONFIG_LOGIRUMBLEPAD2_FF=y
CONFIG_LOGIG940_FF=y
CONFIG_LOGIWII_FF=y
CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
CONFIG_HID_MULTITOUCH=y
CONFIG_HID_NTRIG=y
CONFIG_HID_ORTEK=y
CONFIG_HID_PANTHERLORD=y
CONFIG_PANTHERLORD_FF=y
CONFIG_HID_PETALYNX=y
CONFIG_HID_PICOLCD=y
CONFIG_HID_QUANTA=y
CONFIG_HID_ROCCAT_ARVO=y
CONFIG_HID_ROCCAT_KONE=y
CONFIG_HID_ROCCAT_KONEPLUS=y
CONFIG_HID_ROCCAT_KOVAPLUS=y
CONFIG_HID_ROCCAT_PYRA=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_HID_GREENASIA=y
CONFIG_GREENASIA_FF=y
CONFIG_HID_SMARTJOYPLUS=y
CONFIG_SMARTJOYPLUS_FF=y
CONFIG_HID_TOPSEED=y
CONFIG_HID_THRUSTMASTER=y
CONFIG_THRUSTMASTER_FF=y
CONFIG_HID_WACOM=y
CONFIG_HID_ZEROPLUS=y
CONFIG_ZEROPLUS_FF=y
CONFIG_HID_ZYDACRON=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_DEVICEFS=y
CONFIG_USB_OTG_BLACKLIST_HUB=y
CONFIG_USB_STORAGE=y
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_GENERIC=y
CONFIG_USB_SERIAL_OPTION=y
CONFIG_USB_GADGET=y
CONFIG_USB20_HOST=y
CONFIG_USB20_OTG=y
CONFIG_DWC_OTG_BOTH_HOST_SLAVE=y
CONFIG_MMC=y
CONFIG_MMC_UNSAFE_RESUME=y
CONFIG_MMC_EMBEDDED_SDIO=y
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_SDMMC_RK29=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_SWITCH=y
CONFIG_SWITCH_GPIO=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_WM831X=y
CONFIG_TPS65910_RTC=y
CONFIG_STAGING=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ANDROID_LOGGER=y
CONFIG_ANDROID_TIMED_GPIO=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
# CONFIG_CMMB is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
CONFIG_EXT4_FS=y
# CONFIG_EXT4_FS_XATTR is not set
# CONFIG_DNOTIFY is not set
CONFIG_FUSE_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
# CONFIG_MISC_FILESYSTEMS is not set
# CONFIG_NETWORK_FILESYSTEMS is not set
CONFIG_PARTITION_ADVANCED=y
CONFIG_EFI_PARTITION=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_KERNEL=y
CONFIG_SCHEDSTATS=y
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_EVENT_POWER_TRACING_DEPRECATED is not set
CONFIG_ENABLE_DEFAULT_TRACERS=y
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_TWOFISH=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set

View File

@@ -73,7 +73,10 @@ config MACH_RK30_PHONE_A22
config MACH_RK30_PHONE_PAD
bool "RK30 phone pad board"
config MACH_RK30_Z600T
bool "RK30 Z600T smart phone pad board"
endchoice
choice

View File

@@ -26,10 +26,12 @@ obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_DVFS) += dvfs.o
obj-$(CONFIG_RK30_I2C_INSRAM) += i2c_sram.o
obj-y += board.o
obj-$(CONFIG_MACH_RK3066_SDK) += board-rk30-sdk.o
obj-$(CONFIG_MACH_RK30_SDK) += board-rk30-sdk.o
obj-$(CONFIG_MACH_RK30_DS975) += board-rk30-ds975.o
board-$(CONFIG_MACH_RK3066_SDK) += board-rk30-sdk.o
board-$(CONFIG_MACH_RK30_SDK) += board-rk30-sdk.o
board-$(CONFIG_MACH_RK30_DS975) += board-rk30-ds975.o
board-$(CONFIG_MACH_RK30_Z600T) += board-rk30-phonepad-z600t.o
obj-$(CONFIG_MACH_RK30_PHONE) += board-rk30-phone.o board-rk30-phone-key.o
obj-$(CONFIG_MACH_RK30_PHONE_PAD) += board-rk30-phonepad.o board-rk30-phonepad-key.o
obj-$(CONFIG_MACH_RK30_PHONE_LOQUAT) += board-rk30-phone-loquat.o board-rk30-phone-loquat-key.o

File diff suppressed because it is too large Load Diff

View File

@@ -45,6 +45,7 @@
#include <linux/sensor-dev.h>
#include <linux/regulator/rk29-pwm-regulator.h>
#include "../../../drivers/headset_observe/rk_headset.h"
#if defined(CONFIG_MFD_RK610)
#include <linux/mfd/rk610_core.h>
#endif
@@ -56,22 +57,24 @@
#if defined(CONFIG_SPIM_RK29)
#include "../../../drivers/spi/rk29_spim.h"
#endif
#if defined(CONFIG_MU509)
#include <linux/mu509.h>
#endif
#if defined(CONFIG_MW100)
#include <linux/mw100.h>
#endif
#if defined(CONFIG_MT6229)
#include <linux/mt6229.h>
#endif
#if defined(CONFIG_SEW868)
#include <linux/sew868.h>
#if defined (CONFIG_BP_AUTO)
#include <linux/bp-auto.h>
#endif
#if defined(CONFIG_ANDROID_TIMED_GPIO)
#include "../../../drivers/staging/android/timed_gpio.h"
#endif
/* Android Parameter */
static int ap_mdm = 0;
module_param(ap_mdm, int, 0644);
static int ap_has_alsa = 0;
module_param(ap_has_alsa, int, 0644);
static int ap_data_only = 2;
module_param(ap_data_only, int, 0644);
static int ap_has_earphone = 0;
module_param(ap_has_earphone, int, 0644);
#if defined(CONFIG_MT6620)
#include <linux/gps.h>
#endif
@@ -172,6 +175,39 @@ struct rk29_keys_platform_data rk29_keys_pdata = {
.chn = 1, //chn: 0-7, if do not use ADC,set 'chn' -1
};
#if defined (CONFIG_RK_HEADSET_DET) || defined (CONFIG_RK_HEADSET_IRQ_HOOK_ADC_DET)
static int rk_headset_io_init(int gpio, char *iomux_name, int iomux_mode)
{
int ret;
ret = gpio_request(gpio, NULL);
if(ret)
return ret;
rk30_mux_api_set(iomux_name, iomux_mode);
gpio_pull_updown(gpio, PullDisable);
gpio_direction_input(gpio);
mdelay(50);
return 0;
};
struct rk_headset_pdata rk_headset_info = {
.Headset_gpio = RK30_PIN0_PC7,
.headset_in_type = HEADSET_IN_LOW,
.Hook_adc_chn = 2,
.hook_key_code = KEY_MEDIA,
.headset_gpio_info = {GPIO0C7_TRACECTL_SMCADDR3_NAME, GPIO0C_GPIO0C7},
.headset_io_init = rk_headset_io_init,
};
struct platform_device rk_device_headset = {
.name = "rk_headsetdet",
.id = 0,
.dev = {
.platform_data = &rk_headset_info,
}
};
#endif
#if defined(CONFIG_TOUCHSCREEN_GT8XX)
#define TOUCH_RESET_PIN RK30_PIN4_PD0
#define TOUCH_PWR_PIN INVALID_GPIO
@@ -318,6 +354,94 @@ static struct platform_device rk29_device_backlight = {
#endif
#if defined (CONFIG_SND_SOC_RT3224) || defined (CONFIG_SND_SOC_RT3261)
#define DIFFERENTIAL 1
#define SINGLE_END 0
#define TWO_SPK 2
#define ONE_SPK 1
enum {
SPK_AMPLIFY_ZERO_POINT_FIVE_WATT=1,
SPK_AMPLIFY_ZERO_POINT_SIX_WATT,
SPK_AMPLIFY_ZERO_POINT_EIGHT_WATT,
SPK_AMPLIFY_ONE_WATT,
};
enum {
LR_NORMAL,
LR_SWAP,
LEFT_COPY_TO_RIGHT,
RIGHT_COPY_LEFT,
};
static int rt3261_io_init(int gpio, char *iomux_name, int iomux_mode)
{
gpio_request(gpio,NULL);
rk30_mux_api_set(iomux_name, iomux_mode);
gpio_direction_output(gpio,1);
};
static struct rt3261_platform_data rt3261_info = {
.codec_en_gpio = RK30_PIN4_PD7,
.codec_en_gpio_info = {GPIO4D7_SMCDATA15_TRACEDATA15_NAME,GPIO4D_GPIO4D7},
.io_init = rt3261_io_init,
.spk_num = TWO_SPK,
.modem_input_mode = DIFFERENTIAL,
.lout_to_modem_mode = DIFFERENTIAL,
.spk_amplify = SPK_AMPLIFY_ZERO_POINT_SIX_WATT,
.playback_if1_data_control = LR_NORMAL,
.playback_if2_data_control = LR_NORMAL,
};
#endif
#if defined(CONFIG_BP_AUTO)
static int bp_io_init(void)
{
rk30_mux_api_set(GPIO2B6_LCDC1DATA14_SMCADDR18_TSSYNC_NAME, GPIO2B_GPIO2B6);
rk30_mux_api_set(GPIO4D2_SMCDATA10_TRACEDATA10_NAME, GPIO4D_GPIO4D2);
rk30_mux_api_set(GPIO4C6_SMCDATA6_TRACEDATA6_NAME, GPIO4C_GPIO4C6);
rk30_mux_api_set(GPIO4C4_SMCDATA4_TRACEDATA4_NAME, GPIO4C_GPIO4C4);
//rk30_mux_api_set(GPIO2B7_LCDC1DATA15_SMCADDR19_HSADCDATA7_NAME, GPIO2B_GPIO2B7);
//rk30_mux_api_set(GPIO2C0_LCDCDATA16_GPSCLK_HSADCCLKOUT_NAME, GPIO2C_GPIO2C0);
return 0;
}
static int bp_io_deinit(void)
{
return 0;
}
static int bp_id_get(void)
{
return ap_mdm; //internally 3G modem ID, defined in include\linux\Bp-auto.h
}
struct bp_platform_data bp_auto_info = {
.init_platform_hw = bp_io_init,
.exit_platform_hw = bp_io_deinit,
.get_bp_id = bp_id_get,
.bp_power = RK30_PIN6_PB2, // 3g_power
.bp_en = RK30_PIN2_PB6, // 3g_en
.bp_reset = RK30_PIN4_PD2,
.bp_usb_en = BP_UNKNOW_DATA, //W_disable
.bp_uart_en = BP_UNKNOW_DATA, //EINT9
.bp_wakeup_ap = RK30_PIN4_PC6, //
.ap_wakeup_bp = RK30_PIN4_PC4,
.ap_ready = BP_UNKNOW_DATA, //
.bp_ready = BP_UNKNOW_DATA,
.gpio_valid = 1, //if 1:gpio is define in bp_auto_info,if 0:is not use gpio in bp_auto_info
};
struct platform_device device_bp_auto = {
.name = "bp-auto",
.id = -1,
.dev = {
.platform_data = &bp_auto_info,
}
};
#endif
#ifdef CONFIG_RK29_SUPPORT_MODEM
#define RK30_MODEM_POWER RK30_PIN4_PD1
@@ -346,144 +470,7 @@ static struct platform_device rk30_device_modem = {
}
};
#endif
#if defined(CONFIG_MU509)
static int mu509_io_init(void)
{
rk30_mux_api_set(GPIO2B6_LCDC1DATA14_SMCADDR18_TSSYNC_NAME, GPIO2B_GPIO2B6);
rk30_mux_api_set(GPIO4D2_SMCDATA10_TRACEDATA10_NAME, GPIO4D_GPIO4D2);
rk30_mux_api_set(GPIO2B7_LCDC1DATA15_SMCADDR19_HSADCDATA7_NAME, GPIO2B_GPIO2B7);
rk30_mux_api_set(GPIO2C0_LCDCDATA16_GPSCLK_HSADCCLKOUT_NAME, GPIO2C_GPIO2C0);
return 0;
}
static int mu509_io_deinit(void)
{
return 0;
}
struct rk29_mu509_data rk29_mu509_info = {
.io_init = mu509_io_init,
.io_deinit = mu509_io_deinit,
.modem_power_en = RK30_PIN6_PB2,//RK30_PIN4_PD1,
.bp_power = RK30_PIN2_PB6,//RK30_PIN4_PD1,
.bp_reset = RK30_PIN4_PD2,
.ap_wakeup_bp = RK30_PIN2_PB7,
.bp_wakeup_ap = RK30_PIN6_PA0,
};
struct platform_device rk29_device_mu509 = {
.name = "mu509",
.id = -1,
.dev = {
.platform_data = &rk29_mu509_info,
}
};
#endif
#if defined(CONFIG_MW100)
static int mw100_io_init(void)
{
rk30_mux_api_set(GPIO2B6_LCDC1DATA14_SMCADDR18_TSSYNC_NAME, GPIO2B_GPIO2B6);
rk30_mux_api_set(GPIO4D2_SMCDATA10_TRACEDATA10_NAME, GPIO4D_GPIO4D2);
rk30_mux_api_set(GPIO2B7_LCDC1DATA15_SMCADDR19_HSADCDATA7_NAME, GPIO2B_GPIO2B7);
rk30_mux_api_set(GPIO2C0_LCDCDATA16_GPSCLK_HSADCCLKOUT_NAME, GPIO2C_GPIO2C0);
return 0;
}
static int mw100_io_deinit(void)
{
return 0;
}
struct rk29_mw100_data rk29_mw100_info = {
.io_init = mw100_io_init,
.io_deinit = mw100_io_deinit,
.modem_power_en = RK30_PIN6_PB2,
.bp_power = RK30_PIN2_PB6,
.bp_reset = RK30_PIN4_PD2,
.ap_wakeup_bp = RK30_PIN2_PB7,
.bp_wakeup_ap = RK30_PIN6_PA0,
};
struct platform_device rk29_device_mw100 = {
.name = "mw100",
.id = -1,
.dev = {
.platform_data = &rk29_mw100_info,
}
};
#endif
#if defined(CONFIG_MT6229)
static int mt6229_io_init(void)
{
rk30_mux_api_set(GPIO2B6_LCDC1DATA14_SMCADDR18_TSSYNC_NAME, GPIO2B_GPIO2B6);
rk30_mux_api_set(GPIO4D2_SMCDATA10_TRACEDATA10_NAME, GPIO4D_GPIO4D2);
rk30_mux_api_set(GPIO2B7_LCDC1DATA15_SMCADDR19_HSADCDATA7_NAME, GPIO2B_GPIO2B7);
rk30_mux_api_set(GPIO2C0_LCDCDATA16_GPSCLK_HSADCCLKOUT_NAME, GPIO2C_GPIO2C0);
rk30_mux_api_set(GPIO2C1_LCDC1DATA17_SMCBLSN0_HSADCDATA6_NAME, GPIO2C_GPIO2C1);
rk30_mux_api_set(GPIO2C1_LCDC1DATA17_SMCBLSN0_HSADCDATA6_NAME, GPIO2C_GPIO2C1);
return 0;
return 0;
}
static int mt6229_io_deinit(void)
{
return 0;
}
struct rk29_mt6229_data rk29_mt6229_info = {
.io_init = mt6229_io_init,
.io_deinit = mt6229_io_deinit,
.modem_power_en = RK30_PIN6_PB2,
.bp_power = RK30_PIN2_PB6,
.modem_usb_en = RK30_PIN2_PC0,
.modem_uart_en = RK30_PIN2_PC1,
.bp_wakeup_ap = RK30_PIN6_PA1,
.ap_ready = RK30_PIN2_PB7,
};
struct platform_device rk29_device_mt6229 = {
.name = "mt6229",
.id = -1,
.dev = {
.platform_data = &rk29_mt6229_info,
}
};
#endif
#if defined(CONFIG_SEW868)
static int sew868_io_init(void)
{
rk30_mux_api_set(GPIO2B6_LCDC1DATA14_SMCADDR18_TSSYNC_NAME, GPIO2B_GPIO2B6);
rk30_mux_api_set(GPIO4D2_SMCDATA10_TRACEDATA10_NAME, GPIO4D_GPIO4D2);
rk30_mux_api_set(GPIO4D4_SMCDATA12_TRACEDATA12_NAME, GPIO4D_GPIO4D4);
return 0;
}
static int sew868_io_deinit(void)
{
return 0;
}
struct rk30_sew868_data rk30_sew868_info = {
.io_init = sew868_io_init,
.io_deinit = sew868_io_deinit,
.bp_power = RK30_PIN6_PB2,
.bp_power_active_low = 1,
.bp_sys = RK30_PIN2_PB6,
.bp_reset = RK30_PIN4_PD2,
.bp_reset_active_low = 1,
.bp_wakeup_ap = RK30_PIN4_PD4,
.ap_wakeup_bp = NULL,
};
struct platform_device rk30_device_sew868 = {
.name = "sew868",
.id = -1,
.dev = {
.platform_data = &rk30_sew868_info,
}
};
#endif
/*MMA8452 gsensor*/
#if defined (CONFIG_GS_MMA8452)
@@ -1453,18 +1440,10 @@ static struct platform_device *devices[] __initdata = {
#ifdef CONFIG_RK29_SUPPORT_MODEM
&rk30_device_modem,
#endif
#if defined(CONFIG_MU509)
&rk29_device_mu509,
#endif
#if defined(CONFIG_MW100)
&rk29_device_mw100,
#endif
#if defined(CONFIG_MT6229)
&rk29_device_mt6229,
#endif
#if defined(CONFIG_SEW868)
&rk30_device_sew868,
#if defined (CONFIG_RK_HEADSET_DET) || defined (CONFIG_RK_HEADSET_IRQ_HOOK_ADC_DET)
&rk_device_headset,
#endif
#if defined(CONFIG_BATTERY_RK30_ADC)||defined(CONFIG_BATTERY_RK30_ADC_FAC)
&rk30_device_adc_battery,
#endif
@@ -1474,6 +1453,9 @@ static struct platform_device *devices[] __initdata = {
#ifdef CONFIG_MT5931_MT6622
&device_mt6622,
#endif
#if defined(CONFIG_BP_AUTO)
&device_bp_auto,
#endif
};
@@ -1609,6 +1591,14 @@ static struct i2c_board_info __initdata i2c0_info[] = {
.flags = 0,
},
#endif
#if defined (CONFIG_SND_SOC_RT3224) || defined (CONFIG_SND_SOC_RT3261)
{
.type = "rt3261",
.addr = 0x1c,
.flags = 0,
.platform_data = &rt3261_info,
},
#endif
#ifdef CONFIG_MFD_RK610
{
@@ -1832,6 +1822,12 @@ static void __init machine_rk30_board_init(void)
#if defined(CONFIG_MT6620)
clk_set_rate(clk_get_sys("rk_serial.0", "uart"), 48*1000000);
#endif
#if defined (CONFIG_SND_SOC_RT3224) || defined (CONFIG_SND_SOC_RT3261)
//add for codec_en
gpio_request(RK30_PIN4_PD7, "codec_en");
rk30_mux_api_set(GPIO4D7_SMCDATA15_TRACEDATA15_NAME, GPIO4D_GPIO4D7);
gpio_direction_output(RK30_PIN4_PD7, GPIO_HIGH);
#endif
}
static void __init rk30_reserve(void)

View File

@@ -217,6 +217,13 @@ struct board_id_platform_data {
int (*init_parameter)(int id);
};
struct ft5506_platform_data {
int (*get_pendown_state)(void);
int (*init_platform_hw)(void);
int (*platform_sleep)(void);
int (*platform_wakeup)(void);
void (*exit_platform_hw)(void);
};
struct cm3217_platform_data {
int irq_pin;
int power_pin;

View File

@@ -144,6 +144,7 @@ config TOUCHSCREEN_GT8XX
goodix touch max y resolution
config TOUCHSCREEN_CT36X
default n
tristate "CT36X based touchscreens"
config RK28_I2C_TS_NTP070
@@ -1063,6 +1064,17 @@ config TOUCHSCREEN_FT5406
config TOUCHSCREEN_FT5X0X
tristate "ft5x0x touchscreen panel support "
depends on I2C2_RK29 || I2C2_RK30
config TOUCHSCREEN_FT5506
tristate "FT5506 based touchscreens: FT5506 Interface"
depends on I2C2_RK29 || I2C2_RK30
help
say Y here if you have a touchscreen interface using the FT5506
controller,and your board-specific initialization code includes that
in its table of I2C devices.
If unsure, say N(but it's safe to say "Y").
# VTL TouchScreen Driver Config
source "drivers/input/touchscreen/ct36x_ts/Kconfig"
config ATMEL_MXT1386
tristate "ATMEL_MXT1386 touchscreen panel support"

View File

@@ -85,6 +85,7 @@ obj-$(CONFIG_TOUCHSCREEN_ILI2102_IIC) += ili2102_ts.o
obj-$(CONFIG_D70_L3188A) += goodix_touch.o
obj-$(CONFIG_TOUCHSCREEN_GT8XX) += rk29_i2c_goodix.o
obj-$(CONFIG_TOUCHSCREEN_FT5406) += ft5406_ts.o
obj-$(CONFIG_TOUCHSCREEN_FT5506) += ft5506_wgj.o
obj-$(CONFIG_TOUCHSCREEN_FT5306) += ft5306_ts.o
obj-$(CONFIG_TOUCHSCREEN_SITRONIX_A720) += sitronix_ts_a720.o
obj-$(CONFIG_TOUCHSCREEN_FT5306_WPX2) += ft5306_ts_wpx2.o
@@ -99,4 +100,6 @@ obj-$(CONFIG_TOUCHSCREEN_I30) += i30_ts.o
obj-$(CONFIG_TOUCHSCREEN_BYD693X) += byd693x_ts.o
obj-$(CONFIG_TOUCHSCREEN_FT5X0X) += ft5x0x.o
obj-$(CONFIG_TOUCHSCREEN_GSLX680) += rockchip_gslX680.o
# Make VTL TouchScreen Driver
obj-$(CONFIG_TOUCHSCREEN_CT36X) += ct36x_ts/

View File

@@ -0,0 +1,63 @@
#
# Touchscreen driver configuration
#
config TOUCHSCREEN_CT36X
tristate "VTL ct36x based touchscreens"
default y
if TOUCHSCREEN_CT36X
#config TOUCHSCREEN_CT36X_I2C
# tristate "VTL ct36x based touchscreens"
# depends on I2C
choice
prompt "Device driver platform support"
default TOUCHSCREEN_CT36X_PLATFORM_GENERIC
config TOUCHSCREEN_CT36X_PLATFORM_GENERIC
bool "Generic"
config TOUCHSCREEN_CT36X_PLATFORM_ROCKCHIP
bool "RockChip"
config TOUCHSCREEN_CT36X_PLATFORM_ALLWINNER
bool "AllWinner"
endchoice
choice
prompt "Device driver chip support"
default TOUCHSCREEN_CT36X_CHIP_CT360
config TOUCHSCREEN_CT36X_CHIP_CT360
bool "ct360"
config TOUCHSCREEN_CT36X_CHIP_CT365
bool "ct363/ct365"
endchoice
config TOUCHSCREEN_CT36X_MISC
bool "Device driver misc support"
default y
config TOUCHSCREEN_CT36X_MISC_X_REVERSE
bool "reverse X axis"
default n
depends on TOUCHSCREEN_CT36X_MISC
config TOUCHSCREEN_CT36X_MISC_Y_REVERSE
bool "reverse Y axis"
default n
depends on TOUCHSCREEN_CT36X_MISC
config TOUCHSCREEN_CT36X_MISC_XY_SWAP
bool "swap X, Y"
default n
depends on TOUCHSCREEN_CT36X_MISC
config TOUCHSCREEN_CT36X_MISC_NEW_TPS
bool "uses new touch point structure"
default y
depends on TOUCHSCREEN_CT36X_MISC
endif

View File

@@ -0,0 +1,26 @@
#
# Makefile for the touchscreen drivers.
#
# Each configuration option enables a list of files.
# Core
ct36x_ts-y := tscore.o
obj-$(CONFIG_TOUCHSCREEN_CT36X) += ct36x_ts.o
# platform
# Generic
ct36x_ts-$(CONFIG_TOUCHSCREEN_CT36X_PLATFORM_GENERIC) += generic.o
# RockChip
ct36x_ts-$(CONFIG_TOUCHSCREEN_CT36X_PLATFORM_ROCKCHIP) += rockchip.o
# AllWinner
ct36x_ts-$(CONFIG_TOUCHSCREEN_CT36X_PLATFORM_ALLWINNER) += allwinner.o
# Chip
# ct360
ct36x_ts-$(CONFIG_TOUCHSCREEN_CT36X_CHIP_CT360) += ct360.o
# ct362/ct363/365
ct36x_ts-$(CONFIG_TOUCHSCREEN_CT36X_CHIP_CT365) += ct365.o
# Misc

View File

@@ -0,0 +1,99 @@
#include <linux/i2c.h>
#include "tscore.h"
//#include "generic.h"
static struct i2c_device_id ct36x_ts_id[] = {
{ DRIVER_NAME, 0 },
{ }
};
static struct i2c_board_info i2c_board_info[] = {
{
I2C_BOARD_INFO(DRIVER_NAME, 0x01),
.platform_data = NULL,
},
};
struct i2c_driver ct36x_ts_driver = {
.driver = {
.owner = THIS_MODULE,
.name = DRIVER_NAME
},
.id_table = ct36x_ts_id,
.probe = ct36x_ts_probe,
.suspend = ct36x_ts_suspend,
.resume = ct36x_ts_resume,
.remove = __devexit_p(ct36x_ts_remove),
};
void ct36x_platform_get_cfg(struct ct36x_ts_info *ct36x_ts)
{
/* I2C config */
ct36x_ts->i2c_bus = CT36X_TS_I2C_BUS;
ct36x_ts->i2c_address = CT36X_TS_I2C_ADDRESS;
/* GPIO config */
ct36x_ts->rst = CT36X_TS_RST_PIN;
ct36x_ts->ss = CT36X_TS_IRQ_PIN;
/* IRQ config*/
ct36x_ts->irq = gpio_to_irq(ct36x_ts->ss);
ct36x_ts->ready = 0;
}
int ct36x_platform_set_dev(struct ct36x_ts_info *ct36x_ts)
{
struct i2c_adapter *adapter;
struct i2c_client *client;
adapter = i2c_get_adapter(ct36x_ts->i2c_bus);
if ( !adapter ) {
printk("Unable to get i2c adapter on bus %d.\n", ct36x_ts->i2c_bus);
return -ENODEV;
}
client = i2c_new_device(adapter, i2c_board_info);
i2c_put_adapter(adapter);
if (!client) {
printk("Unable to create i2c device on bus %d.\n", ct36x_ts->i2c_bus);
return -ENODEV;
}
ct36x_ts->client = client;
i2c_set_clientdata(client, ct36x_ts);
return 0;
}
int ct36x_platform_get_resource(struct ct36x_ts_info *ct36x_ts)
{
int err = -1;
// Init Reset pin
err = gpio_request(ct36x_ts->rst, "ct36x_ts_rst");
if ( err ) {
return -EIO;
}
gpio_direction_output(ct36x_ts->rst, 1);
gpio_set_value(ct36x_ts->rst, 1);
// Init Int pin
err = gpio_request(ct36x_ts->ss, "ct36x_ts_int");
if ( err ) {
return -EIO;
}
gpio_direction_input(ct36x_ts->ss);
return 0;
}
void ct36x_platform_put_resource(struct ct36x_ts_info *ct36x_ts)
{
gpio_free(ct36x_ts->rst);
gpio_free(ct36x_ts->ss);
}

View File

@@ -0,0 +1,13 @@
#ifndef CHIP_H
#define CHIP_H
#if defined(CONFIG_TOUCHSCREEN_CT36X_CHIP_CT360)
#include "ct360.h"
#elif defined(CONFIG_TOUCHSCREEN_CT36X_CHIP_CT365)
#include "ct365.h"
#else
#error XXXXXXXXXXXXXXXXXXXXXXXX
#endif
#endif

View File

@@ -0,0 +1,363 @@
#include <linux/i2c.h>
#include <linux/delay.h>
#include "tscore.h"
#include "platform.h"
#include "ct360.h"
#define CT36X_CHIP_FLASH_SECTOR_NUM 8
#define CT36X_CHIP_FLASH_SECTOR_SIZE 2048
#define CT36X_CHIP_FLASH_SOURCE_SIZE 8
static unsigned char binary_data[] = {
//#include "CT365Five3020D_V42120523A.dat"
#include "CT365_THSD_40X28_V05_120827_I2C0X01.dat"
};
/******************************************************************************
* Private functions
*/
static void ct36x_chip_set_idle(struct i2c_client *client, unsigned char *buf)
{
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
buf[0] = 0x00;
buf[1] = 0xA5;
ct36x_ts_reg_write(client, 0x7F, buf, 2);
mdelay(10);
}
static void ct36x_chip_rst_offset(struct i2c_client *client, unsigned char *buf)
{
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
buf[0] = 0x00;
ct36x_ts_reg_write(client, 0x7F, buf, 1);
mdelay(10);
}
static int ct36x_chip_get_busstatus(struct i2c_client *client, unsigned char *buf)
{
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
ct36x_ts_reg_read(client, 0x7F, buf, 1);
mdelay(10);
return buf[0];
}
static int ct36x_chip_erase_flash(struct i2c_client *client, unsigned char *buf)
{
int ret = -1;
int sec;
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
// Erase 16k flash
for ( sec = 0; sec < CT36X_CHIP_FLASH_SECTOR_NUM; sec++ ) {
buf[0] = 0x00;
buf[1] = 0x33;
buf[2] = sec*8;
ct36x_ts_reg_write(client, 0x7F, buf, 3);
mdelay(100);
// Reset I2C offset address
ct36x_chip_rst_offset(client, buf);
// Read I2C bus status
ret = ct36x_chip_get_busstatus(client, buf);
if ( ret != 0xAA ) {
return -1;
}
}
return 0;
}
/*
** Prepare code segment
*/
static int ct36x_chip_set_code(unsigned int flash_addr, unsigned char *buf)
{
unsigned char cod_chksum;
//if ( CT36X_TS_CHIP_DEBUG )
//printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
// Flash address
// data length
buf[2] = (char)(flash_addr >> 8);
buf[3] = (char)(flash_addr & 0xFF);
buf[4] = 0x08;
// Fill firmware source data
//if ( (sec == 1 && cod == 4) || (sec == 1 && cod == 5) ) {
//if ( flash_addr == (CT36X_CHIP_FLASH_SECTOR_SIZE + 32) ||
//flash_addr == (CT36X_CHIP_FLASH_SECTOR_SIZE + 40) ) {
if ( flash_addr == (160) || flash_addr == (168) ) {
buf[6] = ~binary_data[flash_addr + 0];
buf[7] = ~binary_data[flash_addr + 1];
buf[8] = ~binary_data[flash_addr + 2];
buf[9] = ~binary_data[flash_addr + 3];
buf[10] = ~binary_data[flash_addr + 4];
buf[11] = ~binary_data[flash_addr + 5];
buf[12] = ~binary_data[flash_addr + 6];
buf[13] = ~binary_data[flash_addr + 7];
} else {
buf[6] = binary_data[flash_addr + 0];
buf[7] = binary_data[flash_addr + 1];
buf[8] = binary_data[flash_addr + 2];
buf[9] = binary_data[flash_addr + 3];
buf[10] = binary_data[flash_addr + 4];
buf[11] = binary_data[flash_addr + 5];
buf[12] = binary_data[flash_addr + 6];
buf[13] = binary_data[flash_addr + 7];
}
/* Calculate a checksum by Host controller.
** Checksum = ~(FLASH_ADRH+FLASH_ADRL+LENGTH+
** Binary_Data1+Binary_Data2+Binary_Data3+Binary_Data4+
** Binary_Data5+Binary_Data6+Binary_Data7+Binary_Data8) + 1
*/
cod_chksum = ~(buf[2]+buf[3]+buf[4]+
buf[6]+buf[7]+buf[8]+buf[9]+
buf[10]+buf[11]+buf[12]+buf[13]) + 1;
buf[5] = cod_chksum;
return cod_chksum;
}
static int ct36x_chip_write_firmware(struct i2c_client *client, unsigned char *buf)
{
int ret = -1;
int sec, cod;
unsigned char cod_chksum;
unsigned int fin_chksum;
unsigned int flash_addr;
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
// Code checksum, final checksum
cod_chksum = 0x00; fin_chksum = 0x00;
// Flash write command
buf[0] = 0x00;
buf[1] = 0x55;
// 8 sectors, 2048 bytes per sectors
for ( sec = 0; sec < CT36X_CHIP_FLASH_SECTOR_NUM; sec++ ) {
flash_addr = sec * CT36X_CHIP_FLASH_SECTOR_SIZE;
// 256 segments, 8 bytes per segment
for ( cod = 0; cod < (CT36X_CHIP_FLASH_SECTOR_SIZE/CT36X_CHIP_FLASH_SOURCE_SIZE); cod++ ) {
// Fill binary data
cod_chksum = ct36x_chip_set_code(flash_addr, buf);
fin_chksum += cod_chksum;
// Write firmware source data
ct36x_ts_reg_write(client, 0x7F, buf, 14);
//
mdelay(1);
// Increase flash address 8bytes for each write command
flash_addr += CT36X_CHIP_FLASH_SOURCE_SIZE;
}
//
mdelay(20);
}
return 0;
}
/*
** public functions
*/
int ct36x_chip_get_binchksum(unsigned char *buf)
{
int ret = -1;
int sec, cod;
unsigned char cod_chksum;
unsigned int fin_chksum = 0;
unsigned int flash_addr;
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
// 8 sectors, 2048 bytes per sectors
for ( sec = 0; sec < CT36X_CHIP_FLASH_SECTOR_NUM; sec++ ) {
flash_addr = sec * CT36X_CHIP_FLASH_SECTOR_SIZE;
// 256 segments, 8 bytes per segment
for ( cod = 0; cod < (CT36X_CHIP_FLASH_SECTOR_SIZE/CT36X_CHIP_FLASH_SOURCE_SIZE); cod++ ) {
// Fill binary data
cod_chksum = ct36x_chip_set_code(flash_addr, buf);
fin_chksum += cod_chksum;
// Increase flash address 8bytes for each write command
flash_addr += CT36X_CHIP_FLASH_SOURCE_SIZE;
}
}
return (unsigned short)fin_chksum;
}
int ct36x_chip_get_fwchksum(struct i2c_client *client, unsigned char *buf)
{
int fwchksum = 0x00;
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
buf[0] = 0xFF;
buf[1] = 0x0F;
buf[2] = 0xFF;
ct36x_ts_reg_write(client, client->addr, buf, 3);
mdelay(20);
buf[0] = 0x00;
buf[1] = 0xE1;
ct36x_ts_reg_write(client, client->addr, buf, 2);
mdelay(500);
buf[0] = 0xFF;
buf[1] = 0x0A;
buf[2] = 0x0D;
ct36x_ts_reg_write(client, client->addr, buf, 3);
mdelay(20);
ct36x_chip_rst_offset(client, buf);
ct36x_ts_reg_read(client, client->addr, buf, 3);
mdelay(20);
fwchksum = ((buf[0]<<8) | buf[1]);
return fwchksum;
}
int ct36x_chip_get_ver(struct i2c_client *client, unsigned char *buf)
{
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
// Read version command
buf[0] = 0xFF;
buf[1] = 0x3F;
buf[2] = 0xFF;
ct36x_ts_reg_write(client, client->addr, buf, 3);
mdelay(10);
buf[0] = 0x00;
ct36x_ts_reg_write(client, client->addr, buf, 1);
mdelay(10);
// do read version
ct36x_ts_reg_read(client, client->addr, buf, 1);
mdelay(10);
return buf[0];
}
int ct36x_chip_get_vendor(struct i2c_client *client, unsigned char *buf)
{
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
return 0;
}
void ct36x_chip_go_sleep(struct i2c_client *client, unsigned char *buf)
{
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
buf[0] = 0xFF;
buf[1] = 0x0F;
buf[2] = 0x2B;
ct36x_ts_reg_write(client, client->addr, buf, 3);
mdelay(3);
buf[0] = 0x00;
buf[1] = 0x00;
ct36x_ts_reg_write(client, client->addr, buf, 2);
mdelay(3);
//mdelay(50);
}
int ct36x_chip_go_bootloader(struct i2c_client *client, unsigned char *buf)
{
int ret = -1;
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
// Init bootloader
ct36x_chip_set_idle(client, buf);
// Reset I2C offset address
ct36x_chip_rst_offset(client, buf);
// Get I2C bus status
ret = ct36x_chip_get_busstatus(client, buf);
if ( ret != 0xAA ) {
printk("I2C bus status: 0x%x.\n", ret);
return -1;
}
// Erase flash
ret = ct36x_chip_erase_flash(client, buf);
if ( ret ) {
printk("Erase flash failed.\n");
return -1;
}
// Write source data
ct36x_chip_write_firmware(client, buf);
return 0;
}
void ct36x_chip_set_adapter_on(struct i2c_client *client, unsigned char *buf)
{
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
buf[0] = 0xFF;
buf[1] = 0x0F;
buf[2] = 0xFF;
ct36x_ts_reg_write(client, client->addr, buf, 3);
mdelay(3);
buf[0] = 0x00;
buf[1] = 0xE3;
ct36x_ts_reg_write(client, client->addr, buf, 2);
mdelay(3);
}
void ct36x_chip_set_adapter_off(struct i2c_client *client, unsigned char *buf)
{
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
buf[0] = 0xFF;
buf[1] = 0x0F;
buf[2] = 0xFF;
ct36x_ts_reg_write(client, client->addr, buf, 3);
mdelay(3);
buf[0] = 0x00;
buf[1] = 0xE2;
ct36x_ts_reg_write(client, client->addr, buf, 2);
mdelay(3);
}

View File

@@ -0,0 +1,77 @@
#ifndef CT360_H
#define CT360_H
#define CT36X_TS_CHIP_DEBUG 1
/* max touch points supported */
#define CT36X_TS_POINT_NUM 5
#define CT36X_TS_ABS_X_MAX 1024
#define CT36X_TS_ABS_Y_MAX 768
/* data structure of point event */
/* Old Touch Points Protocol
---------+-+-+-+-+-+-+-+-+
Byte0|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|Finger ID|Statu|
---------+-+-+-+-+-+-+-+-+
Byte1|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|X High |
---------+-+-+-+-+-+-+-+-+
Byte2|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|Y High |
---------+-+-+-+-+-+-+-+-+
Byte3|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|X Low |X High |
---------+-+-+-+-+-+-+-+-+
*/
/* New Touch Points Protocol
---------+-+-+-+-+-+-+-+-+
Byte0|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|X High |
---------+-+-+-+-+-+-+-+-+
Byte1|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|Y High |
---------+-+-+-+-+-+-+-+-+
Byte2|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|X Low |X High |
---------+-+-+-+-+-+-+-+-+
Byte3|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|Finger ID|Statu|
---------+-+-+-+-+-+-+-+-+
*/
struct ct36x_finger_info {
#ifndef CONFIG_TOUCHSCREEN_CT36X_MISC_NEW_TPS
unsigned char status : 4; // Action information, 1: Down; 2: Move; 3: Up
unsigned char id : 4; // ID information, from 1 to CFG_MAX_POINT_NUM
#endif
unsigned char xhi; // X coordinate Hi
unsigned char yhi; // Y coordinate Hi
unsigned char ylo : 4; // Y coordinate Lo
unsigned char xlo : 4; // X coordinate Lo
#ifdef CONFIG_TOUCHSCREEN_CT36X_MISC_NEW_TPS
unsigned char status : 4; // Action information, 1: Down; 2: Move; 3: Up
unsigned char id : 4; // ID information, from 1 to CFG_MAX_POINT_NUM
#endif
};
int ct36x_chip_get_binchksum(unsigned char *buf);
int ct36x_chip_get_fwchksum(struct i2c_client *client, unsigned char *buf);
int ct36x_chip_get_ver(struct i2c_client *client, unsigned char *buf);
int ct36x_chip_get_vendor(struct i2c_client *client, unsigned char *buf);
void ct36x_chip_go_sleep(struct i2c_client *client, unsigned char *buf);
int ct36x_chip_go_bootloader(struct i2c_client *client, unsigned char *buf);
void ct36x_chip_set_adapter_on(struct i2c_client *client, unsigned char *buf);
void ct36x_chip_set_adapter_off(struct i2c_client *client, unsigned char *buf);
#endif

View File

@@ -0,0 +1,439 @@
#include <linux/i2c.h>
#include <linux/delay.h>
#include "tscore.h"
#include "platform.h"
#include "ct365.h"
/*
* Private functions
*/
#define CT36X_CHIP_FLASH_SECTOR_NUM 256
#define CT36X_CHIP_FLASH_SECTOR_SIZE 128
#define CT36X_CHIP_FLASH_SOURCE_SIZE 8
static unsigned char binary_data[] = {
//#include "CT365Five3020D_V42120523A.dat"
//#include "CT365_THSD_40X28_V05_120827_I2C0X01.dat"
};
static void ct36x_chip_set_idle(struct i2c_client *client, unsigned char *buf)
{
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
buf[0] = 0x00;
buf[1] = 0xA5;
ct36x_ts_reg_write(client, 0x7F, buf, 2);
mdelay(10);
}
static void ct36x_chip_rst_offset(struct i2c_client *client, unsigned char *buf)
{
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
buf[0] = 0x00;
ct36x_ts_reg_write(client, 0x7F, buf, 1);
mdelay(10);
}
static int ct36x_chip_get_busstatus(struct i2c_client *client, unsigned char *buf)
{
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
ct36x_ts_reg_read(client, 0x7F, buf, 1);
mdelay(10);
return buf[0];
}
static int ct36x_chip_erase_flash(struct i2c_client *client, unsigned char *buf)
{
int ret = -1;
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
// Erase 32k flash
buf[0] = 0x00;
buf[1] = 0x33;
buf[2] = 0x00;
ct36x_ts_reg_write(client, 0x7F, buf, 3);
mdelay(10);
// Reset I2C offset address
ct36x_chip_rst_offset(client, buf);
// Read I2C bus status
ret = ct36x_chip_get_busstatus(client, buf);
if ( ret != 0xAA ) {
return -1;
}
return 0;
}
/*
** Prepare code segment
*/
static int ct36x_chip_set_code(unsigned int flash_addr, unsigned char *buf)
{
unsigned char cod_chksum;
//if ( CT36X_TS_CHIP_DEBUG )
//printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
// Flash address
// data length
buf[2] = (char)(flash_addr >> 8);
buf[3] = (char)(flash_addr & 0xFF);
buf[4] = 0x08;
// Fill firmware source data
//if ( (sec == 1 && cod == 4) || (sec == 1 && cod == 5) ) {
//if ( flash_addr == (CT36X_CHIP_FLASH_SECTOR_SIZE + 32) ||
//flash_addr == (CT36X_CHIP_FLASH_SECTOR_SIZE + 40) ) {
if ( flash_addr == (160) || flash_addr == (168) ) {
buf[6] = ~binary_data[flash_addr + 0];
buf[7] = ~binary_data[flash_addr + 1];
buf[8] = ~binary_data[flash_addr + 2];
buf[9] = ~binary_data[flash_addr + 3];
buf[10] = ~binary_data[flash_addr + 4];
buf[11] = ~binary_data[flash_addr + 5];
buf[12] = ~binary_data[flash_addr + 6];
buf[13] = ~binary_data[flash_addr + 7];
} else {
buf[6] = binary_data[flash_addr + 0];
buf[7] = binary_data[flash_addr + 1];
buf[8] = binary_data[flash_addr + 2];
buf[9] = binary_data[flash_addr + 3];
buf[10] = binary_data[flash_addr + 4];
buf[11] = binary_data[flash_addr + 5];
buf[12] = binary_data[flash_addr + 6];
buf[13] = binary_data[flash_addr + 7];
}
/* Calculate a checksum by Host controller.
** Checksum = ~(FLASH_ADRH+FLASH_ADRL+LENGTH+
** Binary_Data1+Binary_Data2+Binary_Data3+Binary_Data4+
** Binary_Data5+Binary_Data6+Binary_Data7+Binary_Data8) + 1
*/
cod_chksum = ~(buf[2]+buf[3]+buf[4]+
buf[6]+buf[7]+buf[8]+buf[9]+
buf[10]+buf[11]+buf[12]+buf[13]) + 1;
buf[5] = cod_chksum;
return cod_chksum;
}
static int ct36x_chip_write_firmware(struct i2c_client *client, unsigned char *buf)
{
int ret = -1;
int sec, cod;
unsigned char cod_chksum;
unsigned int fin_chksum;
unsigned int flash_addr;
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
// Code checksum, final checksum
cod_chksum = 0x00; fin_chksum = 0x00;
// Flash write command
buf[0] = 0x00;
buf[1] = 0x55;
// 256 sectors, 128 bytes per sectors
for ( sec = 0; sec < CT36X_CHIP_FLASH_SECTOR_NUM; sec++ ) {
flash_addr = sec * CT36X_CHIP_FLASH_SECTOR_SIZE;
// 16 segments, 8 bytes per segment
for ( cod = 0; cod < (CT36X_CHIP_FLASH_SECTOR_SIZE/CT36X_CHIP_FLASH_SOURCE_SIZE); cod++ ) {
// Fill binary data
cod_chksum = ct36x_chip_set_code(flash_addr, buf);
fin_chksum += cod_chksum;
// Write firmware source data
ct36x_ts_reg_write(client, 0x7F, buf, 14);
//
mdelay(1);
// Increase flash address 8bytes for each write command
flash_addr += CT36X_CHIP_FLASH_SOURCE_SIZE;
}
//
mdelay(20);
}
return 0;
}
static int ct36x_chip_read_infoblk(struct i2c_client *client, unsigned char *buf)
{
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
return 0;
}
static int ct36x_chip_erase_infoblk(struct i2c_client *client, unsigned char *buf)
{
int ret = -1;
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
// info block erase command
buf[0] = 0x00;
buf[1] = 0x60;
buf[2] = 0x00;
ct36x_ts_reg_write(client, 0x7F, buf, 3);
mdelay(10);
// Reset I2C offset address
ct36x_chip_rst_offset(client, buf);
// Read I2C bus status
ret = ct36x_chip_get_busstatus(client, buf);
if ( ret != 0xAA ) {
printk("trim data erase error!!! \n");
return -1;
}
return 0;
}
static int ct36x_chip_write_infoblk(struct i2c_client *client, unsigned char *buf)
{
//int ret = -1;
int sec, cod;
unsigned int flash_addr;
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
flash_addr = 0x00;
// write info block 0
buf[0] = 0x00;
buf[1] = 0x61;
for ( cod = 0; cod < 16; cod++ ) {
// Flash address
// data length
buf[2] = (char)(flash_addr >> 8);
buf[3] = (char)(flash_addr & 0xFF);
buf[4] = 0x08;
if ( flash_addr == 0x0000 )
buf[6] = 0x17;
else
buf[6] = 0x00;
buf[7] = 0x00;
buf[8] = 0x00;
buf[9] = 0x00;
buf[10] = 0x00;
buf[11] = 0x00;
buf[12] = 0x00;
buf[13] = 0x00;
buf[5] = (~(buf[2]+buf[3]+buf[4]+buf[6]+buf[7]+buf[8]+buf[9]+buf[10]+buf[11]+buf[12]+buf[13]))+1;
ct36x_ts_reg_write(client, 0x7F, buf, 14);
mdelay(10);
flash_addr += 8;
}
return 0;
}
int ct36x_chip_get_binchksum(unsigned char *buf)
{
int sec, cod;
unsigned char cod_chksum;
unsigned int fin_chksum = 0;
unsigned int flash_addr;
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
// 256 sectors, 128 bytes per sectors
for ( sec = 0; sec < CT36X_CHIP_FLASH_SECTOR_NUM; sec++ ) {
flash_addr = sec * CT36X_CHIP_FLASH_SECTOR_SIZE;
// 16 segments, 8 bytes per segment
for ( cod = 0; cod < (CT36X_CHIP_FLASH_SECTOR_SIZE/CT36X_CHIP_FLASH_SOURCE_SIZE); cod++ ) {
// Fill binary data
cod_chksum = ct36x_chip_set_code(flash_addr, buf);
fin_chksum += cod_chksum;
// Increase flash address 8bytes for each write command
flash_addr += CT36X_CHIP_FLASH_SOURCE_SIZE;
}
}
return (unsigned short)fin_chksum;
}
int ct36x_chip_get_fwchksum(struct i2c_client *client, unsigned char *buf)
{
int fwchksum = 0x00;
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
buf[0] = 0xFF;
buf[1] = 0x8F;
buf[2] = 0xFF;
ct36x_ts_reg_write(client, client->addr, buf, 3);
mdelay(20);
buf[0] = 0x00;
buf[1] = 0xE1;
ct36x_ts_reg_write(client, client->addr, buf, 2);
mdelay(500);
buf[0] = 0xFF;
buf[1] = 0x8E;
buf[2] = 0x0E;
ct36x_ts_reg_write(client, client->addr, buf, 3);
mdelay(20);
ct36x_chip_rst_offset(client, buf);
ct36x_ts_reg_read(client, client->addr, buf, 3);
mdelay(20);
fwchksum = ((buf[0]<<8) | buf[1]);
return fwchksum;
}
int ct36x_chip_get_ver(struct i2c_client *client, unsigned char *buf)
{
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
// Read version command
buf[0] = 0xFF;
buf[1] = 0x3F;
buf[2] = 0xFF;
ct36x_ts_reg_write(client, client->addr, buf, 3);
mdelay(10);
buf[0] = 0x00;
ct36x_ts_reg_write(client, client->addr, buf, 1);
mdelay(10);
// do read version
ct36x_ts_reg_read(client, client->addr, buf, 1);
mdelay(10);
return buf[0];
}
int ct36x_chip_get_vendor(struct i2c_client *client, unsigned char *buf)
{
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
return 0;
}
void ct36x_chip_go_sleep(struct i2c_client *client, unsigned char *buf)
{
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
buf[0] = 0xFF;
buf[1] = 0x8F;
buf[2] = 0xFF;
ct36x_ts_reg_write(client, client->addr, buf, 3);
mdelay(3);
buf[0] = 0x00;
buf[1] = 0xAF;
ct36x_ts_reg_write(client, client->addr, buf, 2);
mdelay(3);
//mdelay(50);
}
int ct36x_chip_go_bootloader(struct i2c_client *client, unsigned char *buf)
{
int ret = -1;
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
// Init bootloader
ct36x_chip_set_idle(client, buf);
// Reset I2C offset address
ct36x_chip_rst_offset(client, buf);
// Get I2C bus status
ret = ct36x_chip_get_busstatus(client, buf);
if ( ret != 0xAA ) {
printk("I2C bus status: 0x%x.\n", ret);
return -1;
}
// trim adc
ct36x_chip_read_infoblk(client, buf);
ct36x_chip_erase_infoblk(client, buf);
ct36x_chip_write_infoblk(client, buf);
// Erase flash
//ret = ct36x_chip_erase_flash(client, buf);
//if ( ret ) {
// printk("Erase flash failed.\n");
// return -1;
//}
// Write source data
//ct36x_chip_write_firmware(client, buf);
return 0;
}
void ct36x_chip_set_adapter_on(struct i2c_client *client, unsigned char *buf)
{
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
buf[0] = 0xFF;
buf[1] = 0x0F;
buf[2] = 0xFF;
ct36x_ts_reg_write(client, client->addr, buf, 3);
mdelay(3);
buf[0] = 0x00;
buf[1] = 0xE3;
ct36x_ts_reg_write(client, client->addr, buf, 2);
mdelay(3);
}
void ct36x_chip_set_adapter_off(struct i2c_client *client, unsigned char *buf)
{
if ( CT36X_TS_CHIP_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
buf[0] = 0xFF;
buf[1] = 0x0F;
buf[2] = 0xFF;
ct36x_ts_reg_write(client, client->addr, buf, 3);
mdelay(3);
buf[0] = 0x00;
buf[1] = 0xE2;
ct36x_ts_reg_write(client, client->addr, buf, 2);
mdelay(3);
}

View File

@@ -0,0 +1,96 @@
#ifndef CT365_H
#define CT365_H
#define CT36X_TS_CHIP_DEBUG 0
/* max touch points supported */
#define CT36X_TS_POINT_NUM 10
#define CT36X_TS_ABS_X_MAX 1280
#define CT36X_TS_ABS_Y_MAX 800
/* data structure of point event */
/* Old Touch Points Protocol
---------+-+-+-+-+-+-+-+-+
Byte0|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|Finger ID|Statu|
---------+-+-+-+-+-+-+-+-+
Byte1|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|X High |
---------+-+-+-+-+-+-+-+-+
Byte2|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|Y High |
---------+-+-+-+-+-+-+-+-+
Byte3|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|X Low |X High |
---------+-+-+-+-+-+-+-+-+
Byte4|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|Area |
---------+-+-+-+-+-+-+-+-+
Byte5|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|Pressure |
---------+-+-+-+-+-+-+-+-+
*/
/* New Touch Points Protocol
---------+-+-+-+-+-+-+-+-+
Byte0|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|X High |
---------+-+-+-+-+-+-+-+-+
Byte1|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|Y High |
---------+-+-+-+-+-+-+-+-+
Byte2|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|X Low |X High |
---------+-+-+-+-+-+-+-+-+
Byte3|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|Finger ID|Statu|
---------+-+-+-+-+-+-+-+-+
Byte4|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|Area |
---------+-+-+-+-+-+-+-+-+
Byte5|Bit|7|6|5|4|3|2|1|0|
---------+-+-+-+-+-+-+-+-+
|Pressure |
---------+-+-+-+-+-+-+-+-+
*/
struct ct36x_finger_info {
#ifndef CONFIG_TOUCHSCREEN_CT36X_MISC_NEW_TPS
unsigned char status : 3; // Action information, 1: Down; 2: Move; 3: Up
unsigned char id : 5; // ID information, from 1 to CFG_MAX_POINT_NUM
#endif
unsigned char xhi; // X coordinate Hi
unsigned char yhi; // Y coordinate Hi
unsigned char ylo : 4; // Y coordinate Lo
unsigned char xlo : 4; // X coordinate Lo
#ifdef CONFIG_TOUCHSCREEN_CT36X_MISC_NEW_TPS
unsigned char status : 3; // Action information, 1: Down; 2: Move; 3: Up
unsigned char id : 5; // ID information, from 1 to CFG_MAX_POINT_NUM
#endif
unsigned char area; // Touch area
unsigned char pressure; // Touch Pressure
};
int ct36x_chip_get_binchksum(unsigned char *buf);
int ct36x_chip_get_fwchksum(struct i2c_client *client, unsigned char *buf);
int ct36x_chip_get_ver(struct i2c_client *client, unsigned char *buf);
int ct36x_chip_get_vendor(struct i2c_client *client, unsigned char *buf);
void ct36x_chip_go_sleep(struct i2c_client *client, unsigned char *buf);
int ct36x_chip_go_bootloader(struct i2c_client *client, unsigned char *buf);
void ct36x_chip_set_adapter_on(struct i2c_client *client, unsigned char *buf);
void ct36x_chip_set_adapter_off(struct i2c_client *client, unsigned char *buf);
#endif

View File

@@ -0,0 +1,109 @@
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include "tscore.h"
#include "generic.h"
static struct i2c_device_id ct36x_ts_id[] = {
{ DRIVER_NAME, 0 },
{ }
};
struct i2c_driver ct36x_ts_driver = {
.driver = {
.owner = THIS_MODULE,
.name = DRIVER_NAME
},
.id_table = ct36x_ts_id,
.probe = ct36x_ts_probe,
.suspend = ct36x_ts_suspend,
.resume = ct36x_ts_resume,
.remove = __devexit_p(ct36x_ts_remove),
};
void ct36x_ts_reg_read(struct i2c_client *client, unsigned short addr, char *buf, int len)
{
struct i2c_msg msgs;
msgs.addr = addr;
msgs.flags = 0x01; // 0x00: write 0x01:read
msgs.len = len;
msgs.buf = buf;
msgs.scl_rate = CT36X_TS_I2C_SPEED;
i2c_transfer(client->adapter, &msgs, 1);
}
void ct36x_ts_reg_write(struct i2c_client *client, unsigned short addr, char *buf, int len)
{
struct i2c_msg msgs;
msgs.addr = addr;
msgs.flags = 0x00; // 0x00: write 0x01:read
msgs.len = len;
msgs.buf = buf;
msgs.scl_rate = CT36X_TS_I2C_SPEED;
i2c_transfer(client->adapter, &msgs, 1);
}
void ct36x_platform_get_cfg(struct ct36x_ts_info *ct36x_ts)
{
/* I2C config */
//ct36x_ts->i2c_bus = CT36X_TS_I2C_BUS;
//ct36x_ts->i2c_address = CT36X_TS_I2C_ADDRESS;
/* GPIO config */
//ct36x_ts->rst = ct36x_ts->pdata->rst;
//ct36x_ts->ss = ct36x_ts->pdata->ss;
/* IRQ config*/
ct36x_ts->irq = gpio_to_irq(ct36x_ts->ss);
ct36x_ts->ready = 0;
}
int ct36x_platform_set_dev(struct ct36x_ts_info *ct36x_ts)
{
return 0;
}
int ct36x_platform_get_resource(struct ct36x_ts_info *ct36x_ts)
{
int err = -1;
// Init Reset pin
err = gpio_request(ct36x_ts->rst, "ct36x_ts_rst");
if ( err ) {
return -EIO;
}
gpio_direction_output(ct36x_ts->rst, 1);
gpio_set_value(ct36x_ts->rst, 1);
// Init Int pin
err = gpio_request(ct36x_ts->ss, "ct36x_ts_int");
if ( err ) {
return -EIO;
}
gpio_direction_input(ct36x_ts->ss);
return 0;
}
void ct36x_platform_put_resource(struct ct36x_ts_info *ct36x_ts)
{
gpio_free(ct36x_ts->rst);
gpio_free(ct36x_ts->ss);
}
void ct36x_platform_hw_reset(struct ct36x_ts_info *ct36x_ts)
{
mdelay(500);
gpio_set_value(ct36x_ts->rst, 0);
mdelay(50);
gpio_set_value(ct36x_ts->rst, 1);
mdelay(500);
}

View File

@@ -0,0 +1,8 @@
#ifndef GENERIC_H
#define GENERIC_H
#define CT36X_TS_I2C_SPEED 400000
#endif

View File

@@ -0,0 +1,22 @@
#ifndef PLATFORM_H
#define PLATFORM_H
// Platform data
struct ct36x_platform_data {
int rst;
int ss;
};
extern struct i2c_driver ct36x_ts_driver;
void ct36x_ts_reg_read(struct i2c_client *client, unsigned short addr, char *buf, int len);
void ct36x_ts_reg_write(struct i2c_client *client, unsigned short addr, char *buf, int len);
void ct36x_platform_get_cfg(struct ct36x_ts_info *ct36x_ts);
int ct36x_platform_set_dev(struct ct36x_ts_info *ct36x_ts);
int ct36x_platform_get_resource(struct ct36x_ts_info *ct36x_ts);
void ct36x_platform_put_resource(struct ct36x_ts_info *ct36x_ts);
void ct36x_platform_hw_reset(struct ct36x_ts_info *ct36x_ts);
#endif

View File

@@ -0,0 +1,136 @@
#include <linux/i2c.h>
#include <linux/delay.h>
#include "tscore.h"
#include "rockchip.h"
static struct i2c_device_id ct36x_ts_id[] = {
{ DRIVER_NAME, 0 },
{ }
};
static struct i2c_board_info i2c_board_info[] = {
{
I2C_BOARD_INFO(DRIVER_NAME, 0x01),
.platform_data = NULL,
},
};
struct i2c_driver ct36x_ts_driver = {
.driver = {
.owner = THIS_MODULE,
.name = DRIVER_NAME
},
.id_table = ct36x_ts_id,
.probe = ct36x_ts_probe,
.shutdown = ct36x_ts_shutdown,
.suspend = ct36x_ts_suspend,
.resume = ct36x_ts_resume,
.remove = __devexit_p(ct36x_ts_remove),
};
void ct36x_ts_reg_read(struct i2c_client *client, unsigned short addr, char *buf, int len)
{
struct i2c_msg msgs;
msgs.addr = addr;
msgs.flags = 0x01; // 0x00: write 0x01:read
msgs.len = len;
msgs.buf = buf;
msgs.scl_rate = CT36X_TS_I2C_SPEED;
i2c_transfer(client->adapter, &msgs, 1);
}
void ct36x_ts_reg_write(struct i2c_client *client, unsigned short addr, char *buf, int len)
{
struct i2c_msg msgs;
msgs.addr = addr;
msgs.flags = 0x00; // 0x00: write 0x01:read
msgs.len = len;
msgs.buf = buf;
msgs.scl_rate = CT36X_TS_I2C_SPEED;
i2c_transfer(client->adapter, &msgs, 1);
}
void ct36x_platform_get_cfg(struct ct36x_ts_info *ct36x_ts)
{
/* I2C config */
ct36x_ts->i2c_bus = CT36X_TS_I2C_BUS;
ct36x_ts->i2c_address = CT36X_TS_I2C_ADDRESS;
/* GPIO config */
ct36x_ts->rst = CT36X_TS_RST_PIN;
ct36x_ts->ss = CT36X_TS_IRQ_PIN;
/* IRQ config*/
ct36x_ts->irq = gpio_to_irq(ct36x_ts->ss);
ct36x_ts->ready = 0;
}
int ct36x_platform_set_dev(struct ct36x_ts_info *ct36x_ts)
{
struct i2c_adapter *adapter;
struct i2c_client *client;
adapter = i2c_get_adapter(ct36x_ts->i2c_bus);
if ( !adapter ) {
printk("Unable to get i2c adapter on bus %d.\n", ct36x_ts->i2c_bus);
return -ENODEV;
}
client = i2c_new_device(adapter, i2c_board_info);
i2c_put_adapter(adapter);
if (!client) {
printk("Unable to create i2c device on bus %d.\n", ct36x_ts->i2c_bus);
return -ENODEV;
}
ct36x_ts->client = client;
i2c_set_clientdata(client, ct36x_ts);
return 0;
}
int ct36x_platform_get_resource(struct ct36x_ts_info *ct36x_ts)
{
int err = -1;
// Init Reset pin
err = gpio_request(ct36x_ts->rst, "ct36x_ts_rst");
if ( err ) {
return -EIO;
}
gpio_direction_output(ct36x_ts->rst, 1);
gpio_set_value(ct36x_ts->rst, 1);
// Init Int pin
err = gpio_request(ct36x_ts->ss, "ct36x_ts_int");
if ( err ) {
return -EIO;
}
gpio_direction_input(ct36x_ts->ss);
return 0;
}
void ct36x_platform_put_resource(struct ct36x_ts_info *ct36x_ts)
{
gpio_free(ct36x_ts->rst);
gpio_free(ct36x_ts->ss);
}
void ct36x_platform_hw_reset(struct ct36x_ts_info *ct36x_ts)
{
mdelay(500);
gpio_set_value(ct36x_ts->rst, 0);
mdelay(50);
gpio_set_value(ct36x_ts->rst, 1);
mdelay(500);
}

View File

@@ -0,0 +1,15 @@
#ifndef ROCKCHIP_H
#define ROCKCHIP_H
#include <mach/gpio.h>
#define CT36X_TS_I2C_BUS 2 // I2C Bus
#define CT36X_TS_I2C_ADDRESS 0x01
#define CT36X_TS_I2C_SPEED 400000
#define CT36X_TS_IRQ_PIN RK30_PIN4_PC2
#define CT36X_TS_RST_PIN RK30_PIN4_PD0
#endif

View File

@@ -0,0 +1,572 @@
/*
* drivers/input/touchscreen/ct36x_ts.c
*
* VTL ct36x TouchScreen driver.
*
* Copyright (c) 2010 VTL tech Ltd.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* George Chen, 2012-06-15
*/
// ****************************************************************************
// Includes
// ****************************************************************************
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/proc_fs.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/gpio.h>
#include "tscore.h"
#include "platform.h"
enum enum_ct36x_ts_cmds {
CT36X_TS_CHIP_ID,
CT36X_TS_CHIP_RESET,
CT36X_TS_FW_VER,
CT36X_TS_FW_CHKSUM,
CT36X_TS_FW_UPDATE,
CT36X_TS_BIN_VER,
CT36X_TS_BIN_CHKSUM,
};
// ****************************************************************************
// Globel or static variables
// ****************************************************************************
static struct ct36x_ts_info ct36x_ts;
// ****************************************************************************
// Function declaration
// ****************************************************************************
int ct36x_cmd_list_ind[] = {
CT36X_TS_CHIP_ID,
CT36X_TS_CHIP_RESET,
CT36X_TS_FW_VER,
CT36X_TS_FW_CHKSUM,
CT36X_TS_FW_UPDATE,
CT36X_TS_BIN_VER,
CT36X_TS_BIN_CHKSUM,
};
char ct36x_cmd_list_cmd[] = { 'i','r','v','c','u','b','k',0, };
static int ct36x_ts_cmd(char *cmdlist, const char cmd)
{
int i = 0;
// search cmd
while ( cmdlist[i] ) {
if ( cmd == cmdlist[i] )
return ct36x_cmd_list_ind[i];
i++;
}
return -1;
}
static int ct36x_ts_open(struct inode *inode, struct file *file)
{
if ( CT36X_TS_CORE_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
return 0;
}
static int ct36x_ts_close(struct inode *inode, struct file *file)
{
if ( CT36X_TS_CORE_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
return 0;
}
static ssize_t ct36x_ts_write(struct file *file, const char __user *buffer, size_t count, loff_t *offset)
{
int cmd = 0;
int rslt = 0;
if ( CT36X_TS_CORE_DEBUG ) {
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
printk("%s(): count=0x%x \n", __FUNCTION__, count);
}
// search cmd
cmd = ct36x_ts_cmd(ct36x_cmd_list_cmd, buffer[0]);
switch ( cmd ) {
case CT36X_TS_CHIP_ID:
break;
case CT36X_TS_CHIP_RESET:
printk("%s(): CT36X_TS_CHIP_RESET\n", __FUNCTION__);
ct36x_platform_hw_reset(&ct36x_ts);
break;
case CT36X_TS_FW_VER:
break;
case CT36X_TS_FW_CHKSUM:
printk("%s(): CT36X_TS_FW_CHKSUM\n", __FUNCTION__);
rslt = ct36x_chip_get_fwchksum(ct36x_ts.client, ct36x_ts.data.buf);
printk("%s(): Fw checksum: 0x%x\n", __FUNCTION__, rslt);
break;
case CT36X_TS_FW_UPDATE:
printk("%s(): CT36X_TS_FW_UPDATE\n", __FUNCTION__);
ct36x_chip_go_bootloader(ct36x_ts.client, ct36x_ts.data.buf);
break;
case CT36X_TS_BIN_VER:
break;
case CT36X_TS_BIN_CHKSUM:
printk("%s(): CT36X_TS_BIN_CHKSUM\n", __FUNCTION__);
rslt = ct36x_chip_get_binchksum(ct36x_ts.data.buf);
printk("%s(): bin checksum: 0x%x\n", __FUNCTION__, rslt);
break;
default:
printk("%s(): No such command (0x%x). \n", __FUNCTION__, buffer[0]);
break;
}
return count;
}
static ssize_t ct36x_ts_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
int err = -1;
if ( CT36X_TS_CORE_DEBUG ) {
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
printk("%s(): count=0x%x \n", __FUNCTION__, count);
}
if ( !ct36x_ts.ready )
return 0;
//ct36x_ts_reg_read(ct36x_ts->client, buf[0], buf+1, buf[]);
return count;
}
static struct file_operations ct36x_ts_fops = {
.owner = THIS_MODULE,
.open = ct36x_ts_open,
.release = ct36x_ts_close,
.write = ct36x_ts_write,
.read = ct36x_ts_read,
};
static irqreturn_t ct36x_ts_irq(int irq, void *dev)
{
struct ct36x_ts_info *ts;
if ( CT36X_TS_CORE_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
ts = (struct ct36x_ts_info *)dev;
// touch device is ready??
if ( ts->ready ) {
// Disable ts interrupt
disable_irq_nosync(ts->irq);
queue_work(ts->workqueue, &ts->event_work);
}
return IRQ_HANDLED;
}
static void ct36x_ts_workfunc(struct work_struct *work)
{
int iter;
int sync;
int x, y;
struct ct36x_ts_info *ts;
if ( CT36X_TS_CORE_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
ts = container_of(work, struct ct36x_ts_info, event_work);
/* read touch points */
ct36x_ts_reg_read(ts->client, ts->i2c_address, (char *) ts->data.pts, sizeof(struct ct36x_finger_info) * CT36X_TS_POINT_NUM);
/* report points */
sync = 0; ts->press = 0;
for ( iter = 0; iter < CT36X_TS_POINT_NUM; iter++ ) {
if ( ts->data.pts[iter].xhi != 0xFF && ts->data.pts[iter].yhi != 0xFF &&
(ts->data.pts[iter].status == 1 || ts->data.pts[iter].status == 2) ) {
#ifdef CONFIG_TOUCHSCREEN_CT36X_MISC_XY_SWAP
x = (ts->data.pts[iter].yhi<<4)|(ts->data.pts[iter].ylo&0xF);
y = (ts->data.pts[iter].xhi<<4)|(ts->data.pts[iter].xlo&0xF);
#else
x = (ts->data.pts[iter].xhi<<4)|(ts->data.pts[iter].xlo&0xF);
y = (ts->data.pts[iter].yhi<<4)|(ts->data.pts[iter].ylo&0xF);
#endif
#ifdef CONFIG_TOUCHSCREEN_CT36X_MISC_X_REVERSE
x = CT36X_TS_ABS_X_MAX - x;
#endif
#ifdef CONFIG_TOUCHSCREEN_CT36X_MISC_Y_REVERSE
y = CT36X_TS_ABS_Y_MAX - y;
#endif
if ( CT36X_TS_EVENT_DEBUG ) {
printk("ID: %d\n", ts->data.pts[iter].id);
printk("status: %d\n", ts->data.pts[iter].status);
printk("X Lo: %d\n", ts->data.pts[iter].xlo);
printk("Y Lo: %d\n", ts->data.pts[iter].ylo);
printk("X Hi: %d\n", ts->data.pts[iter].xhi);
printk("Y Hi: %d\n", ts->data.pts[iter].yhi);
printk("X: %d\n", x);
printk("Y: %d\n", y);
}
input_report_abs(ts->input, ABS_MT_POSITION_X, x);
input_report_abs(ts->input, ABS_MT_POSITION_Y, y);
input_mt_sync(ts->input);
sync = 1;
ts->press |= 0x01 << (ts->data.pts[iter].id - 1);
}
}
ts->release &= ts->release ^ ts->press;
for ( iter = 0; iter < CT36X_TS_POINT_NUM; iter++ ) {
if ( ts->release & (0x01<<iter) ) {
input_mt_sync(ts->input);
sync = 1;
}
}
ts->release = ts->press;
if ( sync ) input_sync(ts->input);
// Enable ts interrupt
enable_irq(ts->irq);
}
static void ct36x_ts_adapter(int state)
{
if ( CT36X_TS_CORE_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
if ( !ct36x_ts.ready ) return;
}
#ifdef CONFIG_HAS_EARLYSUSPEND
static void ct36x_early_suspend(struct early_suspend *handler)
{
struct ct36x_ts_info *ts;
if (CT36X_TS_CORE_DEBUG)
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
ts = container_of(handler, struct ct36x_ts_info, early_suspend);
ct36x_ts_suspend(ts->client, PMSG_SUSPEND);
}
static void ct36x_early_resume(struct early_suspend *handler)
{
struct ct36x_ts_info *ts;
if (CT36X_TS_CORE_DEBUG)
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
ts = container_of(handler, struct ct36x_ts_info, early_suspend);
ct36x_ts_resume(ts->client);
}
#endif
int ct36x_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int err = -1;
int binchksum, fwchksum;
int updcnt;
struct ct36x_ts_info *ts;
struct ct36x_platform_data *pdata;
struct device *dev;
if ( CT36X_TS_CORE_DEBUG )
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
dev = &client->dev;
pdata = dev->platform_data;
if ( pdata ) {
ct36x_ts.i2c_address = client->addr;
ct36x_ts.rst = pdata->rst;
ct36x_ts.ss = pdata->ss;
ct36x_platform_get_cfg(&ct36x_ts);
ct36x_ts.client = client;
i2c_set_clientdata(client, &ct36x_ts);
} else {
printk("No platform data for device %s.\n", DRIVER_NAME);
}
ts = (struct ct36x_ts_info *)i2c_get_clientdata(client);
/* Create Proc Entry File */
ts->proc_entry = create_proc_entry(DRIVER_NAME, 0666/*S_IFREG | S_IRUGO | S_IWUSR*/, NULL);
if ( ts->proc_entry == NULL ) {
dev_err(dev, "Failed creating proc dir entry file.\n");
} else {
ts->proc_entry->proc_fops = &ct36x_ts_fops;
}
/* register early suspend */
#ifdef CONFIG_HAS_EARLYSUSPEND
ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
ts->early_suspend.suspend = ct36x_early_suspend;
ts->early_suspend.resume = ct36x_early_resume;
register_early_suspend(&ts->early_suspend);
#endif
/* Check I2C Functionality */
err = i2c_check_functionality(client->adapter, I2C_FUNC_I2C);
if ( !err ) {
dev_err(dev, "Check I2C Functionality Failed.\n");
goto ERR_I2C_CHK;
}
/* Request platform resources (gpio/interrupt pins) */
err = ct36x_platform_get_resource(ts);
if ( err ) {
dev_err(dev, "Unable to request platform resource for device %s.\n", DRIVER_NAME);
goto ERR_PLAT_RSC;
}
/* Hardware reset */
ct36x_platform_hw_reset(ts);
// Get binary Checksum
binchksum = ct36x_chip_get_binchksum(ts->data.buf);
if ( CT36X_TS_CORE_DEBUG )
printk("Bin checksum: 0x%x\n", binchksum);
// Get firmware Checksum
fwchksum = ct36x_chip_get_fwchksum(client, ts->data.buf);
if ( CT36X_TS_CORE_DEBUG )
printk("Fw checksum: 0x%x\n", fwchksum);
updcnt = 5;
while ( binchksum != fwchksum && updcnt--) {
/* Update Firmware */
ct36x_chip_go_bootloader(client, ts->data.buf);
/* Hardware reset */
ct36x_platform_hw_reset(ts);
// Get firmware Checksum
fwchksum = ct36x_chip_get_fwchksum(client, ts->data.buf);
if ( CT36X_TS_CORE_DEBUG )
printk("Fw checksum: 0x%x\n", fwchksum);
}
printk("Fw update %s. 0x%x, 0x%x\n", binchksum != fwchksum ? "Failed" : "Success", binchksum, fwchksum);
/* Hardware reset */
ct36x_platform_hw_reset(ts);
/* allocate input device */
ts->input = input_allocate_device();
if ( !ts->input ) {
dev_err(dev, "Unable to allocate input device for device %s.\n", DRIVER_NAME);
err = -ENOMEM;
goto ERR_INPUT_ALLOC;
}
/* config input device */
__set_bit(EV_SYN, ts->input->evbit);
__set_bit(EV_KEY, ts->input->evbit);
__set_bit(EV_ABS, ts->input->evbit);
__set_bit(INPUT_PROP_DIRECT, ts->input->propbit);
input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, CT36X_TS_ABS_X_MAX, 0, 0);
input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, CT36X_TS_ABS_Y_MAX, 0, 0);
ts->input->name = DRIVER_NAME;
ts->input->id.bustype = BUS_I2C;
/* register input device */
err = input_register_device(ts->input);
if ( err ) {
dev_err(dev, "Unable to register input device for device %s.\n", DRIVER_NAME);
goto ERR_INPUT_REGIS;
}
/* Create work queue */
INIT_WORK(&ts->event_work, ct36x_ts_workfunc);
ts->workqueue = create_singlethread_workqueue(dev_name(&client->dev));
/* Init irq */
err = request_irq(ts->irq, ct36x_ts_irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, DRIVER_NAME, ts);
if ( err ) {
dev_err(dev, "Unable to request irq for device %s.\n", DRIVER_NAME);
goto ERR_IRQ_REQ;
}
/* Set device is ready */
ts->ready = 1;
ts->state = CT36X_STATE_NORMAL;
/* power denoisy*/
//ct36x_chip_set_adapter_on(client, ts->data.buf);
//ct36x_chip_set_adapter_off(client, ts->data.buf);
ct36x_ts_adapter(0);
return 0;
ERR_IRQ_REQ:
destroy_workqueue(ts->workqueue);
ERR_INPUT_REGIS:
input_free_device(ts->input);
ERR_INPUT_ALLOC:
ERR_PLAT_RSC:
ct36x_platform_put_resource(ts);
ERR_I2C_CHK:
#ifdef CONFIG_HAS_EARLYSUSPEND
unregister_early_suspend(&ts->early_suspend);
#endif
remove_proc_entry(DRIVER_NAME, NULL);
return err;
}
void ct36x_ts_shutdown(struct i2c_client *client)
{
struct ct36x_ts_info *ts;
if (CT36X_TS_CORE_DEBUG)
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
ts = (struct ct36x_ts_info *)i2c_get_clientdata(client);
ct36x_chip_go_sleep(client, ts->data.buf);
}
int ct36x_ts_suspend(struct i2c_client *client, pm_message_t mesg)
{
struct ct36x_ts_info *ts;
if (CT36X_TS_CORE_DEBUG)
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
ts = (struct ct36x_ts_info *)i2c_get_clientdata(client);
if ( ts->state == CT36X_STATE_SLEEP ) return 0;
disable_irq(ts->irq);
cancel_work_sync(&ts->event_work);
ct36x_chip_go_sleep(client, ts->data.buf);
ts->state = CT36X_STATE_SLEEP;
return 0;
}
int ct36x_ts_resume(struct i2c_client *client)
{
struct ct36x_ts_info *ts;
if (CT36X_TS_CORE_DEBUG)
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
ts = (struct ct36x_ts_info *)i2c_get_clientdata(client);
if ( ts->state == CT36X_STATE_NORMAL ) return 0;
/* Hardware reset */
ct36x_platform_hw_reset(ts);
enable_irq(ts->irq);
ts->state = CT36X_STATE_NORMAL;
return 0;
}
int __devexit ct36x_ts_remove(struct i2c_client *client)
{
struct ct36x_ts_info *ts;
if (CT36X_TS_CORE_DEBUG)
printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
ts = (struct ct36x_ts_info *)i2c_get_clientdata(client);
/* Driver clean up */
disable_irq(ts->irq);
cancel_work_sync(&ts->event_work);
destroy_workqueue(ts->workqueue);
input_free_device(ts->input);
free_irq(ts->irq, ts);
ct36x_platform_put_resource(ts);
i2c_unregister_device(client);
#ifdef CONFIG_HAS_EARLYSUSPEND
unregister_early_suspend(&ts->early_suspend);
#endif
remove_proc_entry(DRIVER_NAME, NULL);
return 0;
}
int __init ct36x_ts_init(void)
{
int err = -1;
printk("VTL ct36x TouchScreen driver, <george.chen@vtl.com.cn>.\n");
ct36x_platform_get_cfg(&ct36x_ts);
err = ct36x_platform_set_dev(&ct36x_ts);
if ( err ) goto ERR_INIT;
err = i2c_add_driver(&ct36x_ts_driver);
if ( err ) goto ERR_INIT;
return 0;
ERR_INIT:
return err;
}
void __exit ct36x_ts_exit(void)
{
i2c_del_driver(&ct36x_ts_driver);
}
module_init(ct36x_ts_init);
module_exit(ct36x_ts_exit);
MODULE_AUTHOR("<george.chen@vtl.com>");
MODULE_DESCRIPTION("VTL ct36x TouchScreen driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,80 @@
#ifndef TSCORE_H
#define TSCORE_H
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
#include "chip.h"
// ****************************************************************************
// Defines
// ****************************************************************************
#define CT36X_TS_CORE_DEBUG 0
#define CT36X_TS_EVENT_DEBUG 0
#define DRIVER_NAME "ct36x_ts"
enum enum_ct36x_state {
CT36X_STATE_INIT,
CT36X_STATE_NORMAL,
CT36X_STATE_SLEEP,
CT36X_STATE_UPDATE,
};
union ct36x_i2c_data {
struct ct36x_finger_info pts[CT36X_TS_POINT_NUM];
unsigned char buf[CT36X_TS_POINT_NUM * sizeof(struct ct36x_finger_info)];
};
struct ct36x_ts_info {
/* Chip ID */
int chip_id;
// Communication settings
int i2c_bus;
unsigned short i2c_address;
struct i2c_client *client;
// Devices
struct input_dev *input;
int irq;
int rst;
int ss;
int ready;
int state;
// Early suspend
#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend early_suspend;
#endif
// Proc Control
struct proc_dir_entry *proc_entry;
// Work thread settings
struct work_struct event_work;
struct workqueue_struct *workqueue;
// touch event data
union ct36x_i2c_data data;
int press;
int release;
};
//////////////////////////////////////////////
int ct36x_ts_probe(struct i2c_client *client, const struct i2c_device_id *id);
void ct36x_ts_shutdown(struct i2c_client *client);
int ct36x_ts_suspend(struct i2c_client *client, pm_message_t mesg);
int ct36x_ts_resume(struct i2c_client *client);
int __devexit ct36x_ts_remove(struct i2c_client *client);
int __init ct36x_ts_init(void);
void __exit ct36x_ts_exit(void);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,120 @@
#ifndef __LINUX_FT5X0X_TS_H__
#define __LINUX_FT5X0X_TS_H__
//#define CONFIG_SUPPORT_FTS_CTP_UPG
#define CONFIG_FTS_CUSTOME_ENV
#define FT5X0X_I2C_SPEED 200*1000
#define CFG_DBG_DUMMY_INFO_SUPPORT 1 //output touch point information
#define CFG_DBG_FUCTION_INFO_SUPPORT 0 //output fouction name
#define CFG_DBG_INPUT_EVENT 1 //debug input event
#define CFG_MAX_POINT_NUM 10 //max touch points supported
#define CFG_NUMOFKEYS 0x00//0x4 //number of touch keys
#ifdef CONFIG_FTS_CUSTOME_ENV
//<2F><><EFBFBD><EFBFBD>ָ<EFBFBD>ӱ߽绮<DFBD><E7BBAE>ʱ,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>߽<EFBFBD><DFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define SCREEN_BOUNDARY_ADJUST_VALUE 10
#define SCREEN_MAX_X 1280
#define SCREEN_MAX_Y 800//600
#else
#define SCREEN_MAX_X 1024
#define SCREEN_MAX_Y 768
#endif
#define PRESS_MAX 255
#define KEY_PRESS 0x1
#define KEY_RELEASE 0x0
#define FT5X0X_NAME "laibao_touch"//"ft5x0x_ts"
#define FTS_NULL 0x0
#define FTS_TRUE 0x1
#define FTS_FALSE 0x0
#define I2C_CTPM_ADDRESS 0x70
typedef unsigned char FTS_BYTE;
typedef unsigned short FTS_WORD;
typedef unsigned int FTS_DWRD;
typedef unsigned char FTS_BOOL;
typedef struct _REPORT_FINGER_INFO_T
{
short ui2_id; /* ID information, from 0 to CFG_MAX_POINT_NUM - 1*/
short u2_pressure; /* ***pressure information, valid from 0 -63 **********/
short i2_x; /*********** X coordinate, 0 - 2047 ****************/
short i2_y; /* **********Y coordinate, 0 - 2047 ****************/
} REPORT_FINGER_INFO_T;
typedef enum
{
ERR_OK,
ERR_MODE,
ERR_READID,
ERR_ERASE,
ERR_STATUS,
ERR_ECC,
ERR_DL_ERASE_FAIL,
ERR_DL_PROGRAM_FAIL,
ERR_DL_VERIFY_FAIL
}E_UPGRADE_ERR_TYPE;
struct FTS_TS_EVENT_T {
short x1;
short y1;
short x2;
short y2;
short x3;
short y3;
short x4;
short y4;
short x5;
short y5;
short pressure1;
short pressure2;
short pressure3;
short pressure4;
short pressure5;
u8 touch_point;
};
enum ft5x0x_ts_regs {
FT5X0X_REG_THRES = 0x80, /* Thresshold, the threshold be low, the sensitivy will be high */
FT5X0X_REG_REPORT_RATE = 0x88, /* **************report rate, in unit of 10Hz **************/
FT5X0X_REG_PMODE = 0xA5, /* Power Consume Mode 0 -- active, 1 -- monitor, 3 -- sleep */
FT5X0X_REG_FIRMID = 0xA6, /* ***************firmware version **********************/
FT5X0X_REG_NOISE_MODE = 0xb2 /* to enable or disable power noise, 1 -- enable, 0 -- disable */
};
#define PMODE_ACTIVE 0x00
#define PMODE_MONITOR 0x01
#define PMODE_STANDBY 0x02
#define PMODE_HIBERNATE 0x03
#ifndef ABS_MT_TOUCH_MAJOR
#define ABS_MT_TOUCH_MAJOR 0x30 /* touching ellipse */
#define ABS_MT_TOUCH_MINOR 0x31 /* (omit if circular) */
#define ABS_MT_WIDTH_MAJOR 0x32 /* approaching ellipse */
#define ABS_MT_WIDTH_MINOR 0x33 /* (omit if circular) */
#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */
#define ABS_MT_BLOB_ID 0x38 /* Group set of pkts as blob */
#endif
#endif

View File

@@ -1,31 +0,0 @@
#
# 3G device configuration
#
menuconfig 3G_MODULE
tristate "3G module for phonepad"
---help---
Say Y here if you have a support modem
choice
depends on 3G_MODULE
prompt "Select 3G Module"
config MU509
bool "MU509"
config MT6229
bool "MT6229"
config MW100
bool "MW100"
config SEW868
bool "SEW868"
config MI700
bool "MI700"
config SC6610
bool "SC6610"
endchoice

View File

@@ -1,6 +0,0 @@
obj-$(CONFIG_MU509) += mu509.o
obj-$(CONFIG_MW100) += mw100.o
obj-$(CONFIG_MT6229) += mt6229.o
obj-$(CONFIG_SEW868) += sew868.o
obj-$(CONFIG_MI700) += mi700.o
obj-$(CONFIG_SC6610) += sc6610.o

View File

@@ -1,352 +0,0 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/circ_buf.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <mach/iomux.h>
#include <mach/gpio.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/wakelock.h>
#include <linux/workqueue.h>
#include <linux/mi700.h>
#include <mach/iomux.h>
#include<linux/ioctl.h>
#include <linux/slab.h>
MODULE_LICENSE("GPL");
#define DEBUG
#ifdef DEBUG
#define MODEMDBG(x...) printk(x)
#else
#define MODEMDBG(fmt,argss...)
#endif
#define MW100IO 0XA1
#define MW_IOCTL_RESET _IO(MW100IO,0X01)
#define SLEEP 1
#define READY 0
#define MI700_RESET 0x01
static struct wake_lock modem_wakelock;
#define IRQ_BB_WAKEUP_AP_TRIGGER IRQF_TRIGGER_RISING
struct rk29_mi700_data *gpdata = NULL;
static int bp_wakeup_ap_irq = 0;
struct class *modem_class = NULL;
static int do_wakeup_irq = 1;
static int modem_status;
static int online = 0;
static void ap_wakeup_bp(struct platform_device *pdev, int wake)
{
struct rk29_mi700_data *pdata = pdev->dev.platform_data;
MODEMDBG("ap_wakeup_bp\n");
gpio_set_value(pdata->ap_wakeup_bp, wake);
}
extern void rk28_send_wakeup_key(void);
static void do_wakeup(struct work_struct *work)
{
MODEMDBG("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);
//rk28_send_wakeup_key();
}
static DECLARE_DELAYED_WORK(wakeup_work, do_wakeup);
static irqreturn_t detect_irq_handler(int irq, void *dev_id)
{
if(do_wakeup_irq)
{
do_wakeup_irq = 0;
printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);
wake_lock_timeout(&modem_wakelock, 10 * HZ);
schedule_delayed_work(&wakeup_work, HZ / 10);
} else
printk("%s: already wakeup\n", __FUNCTION__);
return IRQ_HANDLED;
}
int modem_poweron_off(int on_off)
{
struct rk29_mi700_data *pdata = gpdata;
mutex_lock(&pdata->bp_mutex);
if(on_off)
{
MODEMDBG("------------modem_poweron\n");
gpio_set_value(pdata->bp_reset, GPIO_LOW);
msleep(100);
gpio_set_value(pdata->bp_reset, GPIO_HIGH);
gpio_set_value(pdata->bp_power, GPIO_HIGH);
msleep(1000);
gpio_set_value(pdata->bp_power, GPIO_LOW);
msleep(700);
gpio_set_value(pdata->bp_power, GPIO_HIGH);
}
else
{
MODEMDBG("------------modem_poweroff\n");
gpio_set_value(pdata->bp_power, GPIO_LOW);
gpio_set_value(pdata->bp_power, GPIO_HIGH);
msleep(2500);
gpio_set_value(pdata->bp_power, GPIO_LOW);
}
mutex_unlock(&pdata->bp_mutex);
return 0;
}
static int mi700_open(struct inode *inode, struct file *file)
{
//MODEMDBG("-------------%s\n",__FUNCTION__);
struct rk29_mi700_data *pdata = gpdata;
// struct platform_data *pdev = container_of(pdata, struct device, platform_data);
device_init_wakeup(pdata->dev, 1);
return 0;
}
static int mi700_release(struct inode *inode, struct file *file)
{
MODEMDBG("%s::%d--bruins--\n",__func__,__LINE__);
//modem_poweron_off(0);
return 0;
}
static long mi700_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct rk29_mi700_data *pdata = gpdata;
switch(cmd)
{
case MI700_RESET:
gpio_set_value(pdata->bp_reset, GPIO_LOW);
msleep(100);
gpio_set_value(pdata->bp_reset, GPIO_HIGH);
msleep(100);
gpio_set_value(pdata->bp_power, GPIO_HIGH);
msleep(1000);
gpio_set_value(pdata->bp_power, GPIO_LOW);
msleep(700);
gpio_set_value(pdata->bp_power, GPIO_HIGH);
break;
default:
break;
}
return 0;
}
static struct file_operations mi700_fops = {
.owner = THIS_MODULE,
.open = mi700_open,
.release = mi700_release,
.unlocked_ioctl = mi700_ioctl
};
static struct miscdevice mi700_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "mi700",
.fops = &mi700_fops
};
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
static ssize_t modem_status_read(struct class *cls, struct class_attribute *attr, char *_buf)
#else
static ssize_t modem_status_read(struct class *cls, char *_buf)
#endif
{
return sprintf(_buf, "%d\n", modem_status);
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
static ssize_t modem_status_write(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count)
#else
static ssize_t modem_status_write(struct class *cls, const char *_buf, size_t _count)
#endif
{
int new_state = simple_strtoul(_buf, NULL, 16);
if(new_state == modem_status)
return _count;
if (new_state == 1){
printk("%s, c(%d), open modem \n", __FUNCTION__, new_state);
modem_poweron_off(1);
}else if(new_state == 0){
printk("%s, c(%d), close modem \n", __FUNCTION__, new_state);
modem_poweron_off(0);
}else{
printk("%s, invalid parameter \n", __FUNCTION__);
}
modem_status = new_state;
return _count;
}
static CLASS_ATTR(modem_status, 0777, modem_status_read, modem_status_write);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
static ssize_t online_read(struct class *cls, struct class_attribute *attr, char *_buf)
#else
static ssize_t online_read(struct class *cls, char *_buf)
#endif
{
return sprintf(_buf, "%d\n", online);
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
static ssize_t online_write(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count)
#else
static ssize_t online_write(struct class *cls, const char *_buf, size_t _count)
#endif
{
int new_value = simple_strtoul(_buf, NULL, 16);
if(new_value == online) return _count;
online = new_value;
return _count;
}
static CLASS_ATTR(online, 0777, online_read, online_write);
static int mi700_probe(struct platform_device *pdev)
{
struct rk29_mi700_data *pdata = gpdata = pdev->dev.platform_data;
struct modem_dev *mi700_data = NULL;
int result, irq = 0;
MODEMDBG("-------------%s\n",__FUNCTION__);
pdata->dev = &pdev->dev;
if(pdata->io_init)
pdata->io_init();
mi700_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
if(mi700_data == NULL)
{
printk("failed to request mi700_data\n");
goto err2;
}
platform_set_drvdata(pdev, mi700_data);
#if 0
result = gpio_request(pdata->ap_wakeup_bp, "mi700");
if (result) {
printk("failed to request AP_BP_WAKEUP gpio\n");
goto err1;
}
#endif
irq = gpio_to_irq(pdata->bp_wakeup_ap);
enable_irq_wake(irq);
if(irq < 0)
{
gpio_free(pdata->bp_wakeup_ap);
printk("failed to request bp_wakeup_ap\n");
}
result = gpio_request(pdata->bp_wakeup_ap, "bp_wakeup_ap");
if (result < 0) {
printk("%s: gpio_request(%d) failed\n", __func__, pdata->bp_wakeup_ap);
}
wake_lock_init(&modem_wakelock, WAKE_LOCK_SUSPEND, "bp_wakeup_ap");
gpio_direction_input(pdata->bp_wakeup_ap);
gpio_pull_updown(pdata->bp_wakeup_ap, 1);
result = request_irq(irq, detect_irq_handler, IRQ_BB_WAKEUP_AP_TRIGGER, "bp_wakeup_ap", NULL);
if (result < 0) {
printk("%s: request_irq(%d) failed\n", __func__, irq);
gpio_free(pdata->bp_wakeup_ap);
goto err0;
}
enable_irq_wake(gpio_to_irq(pdata->bp_wakeup_ap));
mutex_init(&pdata->bp_mutex);
modem_poweron_off(1);
modem_status = 1;
result = misc_register(&mi700_misc);
if(result)
{
printk("misc_register err\n");
}
return result;
err0:
cancel_work_sync(&mi700_data->work);
gpio_free(pdata->bp_wakeup_ap);
err1:
//gpio_free(pdata->ap_wakeup_bp);
err2:
kfree(mi700_data);
return 0;
}
int mi700_suspend(struct platform_device *pdev)
{
struct rk29_mi700_data *pdata = pdev->dev.platform_data;
do_wakeup_irq = 1;
MODEMDBG("%s::%d--\n",__func__,__LINE__);
//gpio_set_value(pdata->ap_wakeup_bp, GPIO_LOW);
return 0;
}
int mi700_resume(struct platform_device *pdev)
{
MODEMDBG("-------------%s\n",__FUNCTION__);
//ap_wakeup_bp(pdev, 0);
//rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_UART0_RTS_N);
return 0;
}
void mi700_shutdown(struct platform_device *pdev, pm_message_t state)
{
struct rk29_mi700_data *pdata = pdev->dev.platform_data;
struct modem_dev *mi700_data = platform_get_drvdata(pdev);
MODEMDBG("-------------%s\n",__FUNCTION__);
modem_poweron_off(0);
if(pdata->io_deinit)
pdata->io_deinit();
cancel_work_sync(&mi700_data->work);
//gpio_free(pdata->bp_power);
//gpio_free(pdata->bp_reset);
//gpio_free(pdata->ap_wakeup_bp);
gpio_free(pdata->bp_wakeup_ap);
kfree(mi700_data);
}
static struct platform_driver mi700_driver = {
.probe = mi700_probe,
.shutdown = mi700_shutdown,
.suspend = mi700_suspend,
.resume = mi700_resume,
.driver = {
.name = "MW100",
.owner = THIS_MODULE,
},
};
static int __init mi700_init(void)
{
MODEMDBG("-------------%s\n",__FUNCTION__);
int ret ;
modem_class = class_create(THIS_MODULE, "rk291x_modem");
ret = class_create_file(modem_class, &class_attr_modem_status);
ret = class_create_file(modem_class, &class_attr_online);
if (ret)
{
printk("Fail to class rk291x_modem.\n");
}
return platform_driver_register(&mi700_driver);
}
static void __exit mi700_exit(void)
{
MODEMDBG("%s::%d--bruins--\n",__func__,__LINE__);
platform_driver_unregister(&mi700_driver);
class_remove_file(modem_class, &class_attr_modem_status);
class_remove_file(modem_class, &class_attr_online);
}
module_init(mi700_init);
module_exit(mi700_exit);

View File

@@ -1,358 +0,0 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/circ_buf.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <mach/iomux.h>
#include <mach/gpio.h>
#include <asm/gpio.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/wakelock.h>
#include <linux/workqueue.h>
#include <linux/mt6229.h>
#include <linux/slab.h>
#include <linux/earlysuspend.h>
MODULE_LICENSE("GPL");
#define DEBUG
#ifdef DEBUG
#define MODEMDBG(x...) printk(x)
#else
#define MODEMDBG(fmt,argss...)
#endif
#define SLEEP 1
#define READY 0
static struct wake_lock modem_wakelock;
//#define IRQ_BB_WAKEUP_AP_TRIGGER IRQF_TRIGGER_FALLING
#define IRQ_BB_WAKEUP_AP_TRIGGER IRQF_TRIGGER_RISING
#define MT6229_RESET 0x01
struct rk29_mt6229_data *gpdata = NULL;
struct class *modem_class = NULL;
static int do_wakeup_irq = 0;
static int modem_status;
static void ap_wakeup_bp(struct platform_device *pdev, int wake)
{
struct rk29_mt6229_data *pdata = pdev->dev.platform_data;
gpio_set_value(pdata->modem_usb_en,wake);
if(wake == 1)
wake = 0;
else
wake = 1;
gpio_set_value(pdata->modem_uart_en,wake);
}
extern void rk28_send_wakeup_key(void);
static void do_wakeup(struct work_struct *work)
{
gpio_set_value(gpdata->ap_ready,GPIO_HIGH);
gpio_set_value(gpdata->modem_usb_en,GPIO_HIGH);
}
static DECLARE_DELAYED_WORK(wakeup_work, do_wakeup);
static irqreturn_t detect_irq_handler(int irq, void *dev_id)
{
if(do_wakeup_irq)
{
do_wakeup_irq = 0;
wake_lock_timeout(&modem_wakelock, 10 * HZ);
//schedule_delayed_work(&wakeup_work, 2*HZ);
}
return IRQ_HANDLED;
}
int modem_poweron_off(int on_off)
{
struct rk29_mt6229_data *pdata = gpdata;
if(on_off)
{
gpio_set_value(pdata->bp_power, GPIO_LOW);
gpio_set_value(pdata->modem_usb_en, GPIO_HIGH);
gpio_set_value(pdata->modem_uart_en, GPIO_LOW);
gpio_set_value(pdata->ap_ready, GPIO_HIGH);
}
else
{
gpio_set_value(pdata->bp_power, GPIO_HIGH);
gpio_set_value(pdata->modem_usb_en, GPIO_LOW);
gpio_set_value(pdata->modem_uart_en, GPIO_HIGH);
gpio_set_value(pdata->ap_ready, GPIO_LOW);
}
return 0;
}
static int mt6229_open(struct inode *inode, struct file *file)
{
struct rk29_mt6229_data *pdata = gpdata;
device_init_wakeup(pdata->dev, 1);
return 0;
}
static ssize_t mt6229_write(struct file *file, const char __user *buf,size_t len, loff_t *off)
{
static char cmd[2];
int ret = 0;
if (len > 2)
{
return -EINVAL;
}
ret = copy_from_user(&cmd, buf, len);
if (ret != 0) {
return -EFAULT;
}
printk(" received cmd = %c\n",cmd[0]);
if (cmd[0] == '0')
{
gpio_set_value(gpdata->ap_ready, GPIO_LOW);
}
if (cmd[0] == '1')
{
gpio_set_value(gpdata->ap_ready, GPIO_HIGH);
}
if (cmd[0] == '2')
{
gpio_set_value(gpdata->modem_uart_en, GPIO_LOW);
}
if (cmd[0] == '3')
{
gpio_set_value(gpdata->modem_uart_en, GPIO_HIGH);
}
if (cmd[0] == '4')
{
gpio_set_value(gpdata->modem_usb_en, GPIO_HIGH);
}if (cmd[0] == '5')
{
gpio_set_value(gpdata->modem_usb_en, GPIO_LOW);
}
return len;
}
static int mt6229_release(struct inode *inode, struct file *file)
{
return 0;
}
static long mt6229_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct rk29_mt6229_data *pdata = gpdata;
switch(cmd)
{
case MT6229_RESET:
gpio_set_value(pdata->bp_power, GPIO_HIGH);
msleep(10);
gpio_set_value(pdata->bp_power, GPIO_LOW);
break;
default:
break;
}
return 0;
}
static struct file_operations mt6229_fops = {
.owner = THIS_MODULE,
.open = mt6229_open,
.write = mt6229_write,
.release = mt6229_release,
.unlocked_ioctl = mt6229_ioctl
};
static struct miscdevice mt6229_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = MODEM_NAME,
.fops = &mt6229_fops
};
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
static ssize_t modem_status_read(struct class *cls, struct class_attribute *attr, char *_buf)
#else
static ssize_t modem_status_read(struct class *cls, char *_buf)
#endif
{
return sprintf(_buf, "%d\n", modem_status);
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
static ssize_t modem_status_write(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count)
#else
static ssize_t modem_status_write(struct class *cls, const char *_buf, size_t _count)
#endif
{
int new_state = simple_strtoul(_buf, NULL, 16);
if(new_state == modem_status) return _count;
if (new_state == 1){
printk("%s, c(%d), modem resume \n", __FUNCTION__, new_state);
gpio_set_value(gpdata->modem_usb_en, GPIO_HIGH);
gpio_set_value(gpdata->modem_uart_en,GPIO_LOW);
}else if(new_state == 0){
printk("%s, c(%d), modem suspend \n", __FUNCTION__, new_state);
gpio_set_value(gpdata->modem_usb_en, GPIO_LOW);
gpio_set_value(gpdata->modem_uart_en,GPIO_HIGH);
}else{
printk("%s, invalid parameter \n", __FUNCTION__);
}
modem_status = new_state;
return _count;
}
static CLASS_ATTR(modem_status, 0777, modem_status_read, modem_status_write);
static int mt6229_probe(struct platform_device *pdev)
{
struct rk29_mt6229_data *pdata = gpdata = pdev->dev.platform_data;
struct modem_dev *mt6229_data = NULL;
int result, irq = 0;
pdata->dev = &pdev->dev;
if(pdata->io_init)
pdata->io_init();
mt6229_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
if(mt6229_data == NULL)
{
printk("failed to request mt6229_data\n");
goto err0;
}
platform_set_drvdata(pdev, mt6229_data);
result = gpio_request(pdata->modem_power_en,"modem_power_en");
if(result){
printk("failed to request modem_power_en gpio\n");
goto err1;
}
gpio_set_value(pdata->modem_power_en, GPIO_HIGH);
msleep(1000);
result = gpio_request(pdata->bp_power,"modem_power");
if(result){
printk("failed to request modem_power gpio\n");
goto err2;
}
result = gpio_request(pdata->modem_usb_en, "modem_usb_en");
if (result) {
printk("failed to request modem_usb_en gpio\n");
goto err3;
}
result = gpio_request(pdata->modem_uart_en,"modem_uart_en");
if(result){
printk("failed to request modem_uart_en gpio\n");
goto err4;
}
result = gpio_request(pdata->bp_wakeup_ap, "bp_wakeup_ap");
if (result) {
printk("failed to request bp_wakeup_ap gpio\n");
goto err5;
}
gpio_direction_input(pdata->bp_wakeup_ap);
irq = gpio_to_irq(pdata->bp_wakeup_ap);
if(irq < 0)
{
gpio_free(pdata->bp_wakeup_ap);
printk("failed to request bp_wakeup_ap\n");
}
result = request_irq(irq, detect_irq_handler, IRQ_BB_WAKEUP_AP_TRIGGER, "bp_wakeup_ap", NULL);
if (result < 0) {
printk("%s: request_irq(%d) failed\n", __func__, irq);
gpio_free(pdata->bp_wakeup_ap);
goto err5;
}
enable_irq_wake(irq);
wake_lock_init(&modem_wakelock, WAKE_LOCK_SUSPEND, "bp_wakeup_ap");
result = gpio_request(pdata->ap_ready, "ap_ready");
if (result < 0) {
printk("failed to request ap_ready gpio\n");
goto err6;
}
modem_poweron_off(1);
modem_status = 1;
result = misc_register(&mt6229_misc);
if(result)
{
printk("misc_register err\n");
}
return result;
err0:
kfree(mt6229_data);
err1:
gpio_free(pdata->modem_power_en);
err2:
gpio_free(pdata->bp_power);
err3:
gpio_free(pdata->modem_usb_en);
err4:
gpio_free(pdata->modem_uart_en);
err5:
gpio_free(pdata->bp_wakeup_ap);
err6:
gpio_free(pdata->ap_ready);
return 0;
}
int mt6229_suspend(struct platform_device *pdev, pm_message_t state)
{
do_wakeup_irq = 1;
ap_wakeup_bp(pdev, 0);
gpio_set_value(gpdata->ap_ready,0);
return 0;
}
int mt6229_resume(struct platform_device *pdev)
{
gpio_set_value(gpdata->modem_uart_en,GPIO_LOW);
schedule_delayed_work(&wakeup_work, 2*HZ);
return 0;
}
void mt6229_shutdown(struct platform_device *pdev)
{
struct rk29_mt6229_data *pdata = pdev->dev.platform_data;
struct modem_dev *mt6229_data = platform_get_drvdata(pdev);
modem_poweron_off(0);
if(pdata->io_deinit)
pdata->io_deinit();
cancel_work_sync(&mt6229_data->work);
gpio_free(pdata->modem_power_en);
gpio_free(pdata->bp_power);
gpio_free(pdata->modem_usb_en);
gpio_free(pdata->modem_uart_en);
gpio_free(pdata->bp_wakeup_ap);
kfree(mt6229_data);
}
static struct platform_driver mt6229_driver = {
.probe = mt6229_probe,
.shutdown = mt6229_shutdown,
.suspend = mt6229_suspend,
.resume = mt6229_resume,
.driver = {
.name = "mt6229",
.owner = THIS_MODULE,
},
};
static int __init mt6229_init(void)
{
int ret ;
modem_class = class_create(THIS_MODULE, "rk291x_modem");
ret = class_create_file(modem_class, &class_attr_modem_status);
if (ret)
{
printk("Fail to class rk291x_modem.\n");
}
return platform_driver_register(&mt6229_driver);
}
static void __exit mt6229_exit(void)
{
platform_driver_unregister(&mt6229_driver);
class_remove_file(modem_class, &class_attr_modem_status);
}
module_init(mt6229_init);
module_exit(mt6229_exit);

View File

@@ -1,339 +0,0 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/circ_buf.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <mach/iomux.h>
#include <mach/gpio.h>
#include <asm/gpio.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/wakelock.h>
#include <linux/workqueue.h>
#include <linux/mu509.h>
#include <linux/slab.h>
#include <linux/earlysuspend.h>
MODULE_LICENSE("GPL");
#define DEBUG
#ifdef DEBUG
#define MODEMDBG(x...) printk(x)
#else
#define MODEMDBG(fmt,argss...)
#endif
#define SLEEP 1
#define READY 0
static struct wake_lock modem_wakelock;
#define IRQ_BB_WAKEUP_AP_TRIGGER IRQF_TRIGGER_FALLING
//#define IRQ_BB_WAKEUP_AP_TRIGGER IRQF_TRIGGER_RISING
#define MU509_RESET 0x01
struct rk29_mu509_data *gpdata = NULL;
struct class *modem_class = NULL;
static int do_wakeup_irq = 0;
static int modem_status;
int suspend_int =0;
static void ap_wakeup_bp(struct platform_device *pdev, int wake)
{
struct rk29_mu509_data *pdata = pdev->dev.platform_data;
gpio_set_value(pdata->ap_wakeup_bp, wake);
}
extern void rk28_send_wakeup_key(void);
static void do_wakeup(struct work_struct *work)
{
if(suspend_int)
{
gpio_set_value(gpdata->ap_wakeup_bp, 0);
suspend_int = 0;
}
}
static DECLARE_DELAYED_WORK(wakeup_work, do_wakeup);
static irqreturn_t detect_irq_handler(int irq, void *dev_id)
{
if(do_wakeup_irq)
{
do_wakeup_irq = 0;
// MODEMDBG("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);
wake_lock_timeout(&modem_wakelock, 10 * HZ);
schedule_delayed_work(&wakeup_work, 2*HZ);
}
return IRQ_HANDLED;
}
int modem_poweron_off(int on_off)
{
struct rk29_mu509_data *pdata = gpdata;
if(on_off)
{
gpio_set_value(pdata->bp_reset, GPIO_HIGH);
msleep(100);
gpio_set_value(pdata->bp_reset, GPIO_LOW);
gpio_set_value(pdata->bp_power, GPIO_LOW);
msleep(1000);
gpio_set_value(pdata->bp_power, GPIO_HIGH);
msleep(700);
gpio_set_value(pdata->bp_power, GPIO_LOW);
gpio_set_value(pdata->ap_wakeup_bp, GPIO_LOW);
}
else
{
gpio_set_value(pdata->bp_power, GPIO_LOW);
gpio_set_value(pdata->bp_power, GPIO_HIGH);
msleep(2500);
gpio_set_value(pdata->bp_power, GPIO_LOW);
}
return 0;
}
static int mu509_open(struct inode *inode, struct file *file)
{
struct rk29_mu509_data *pdata = gpdata;
device_init_wakeup(pdata->dev, 1);
return 0;
}
static int mu509_release(struct inode *inode, struct file *file)
{
return 0;
}
static long mu509_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct rk29_mu509_data *pdata = gpdata;
switch(cmd)
{
case MU509_RESET:
gpio_set_value(pdata->bp_reset, GPIO_HIGH);
msleep(100);
gpio_set_value(pdata->bp_reset, GPIO_LOW);
msleep(100);
gpio_set_value(pdata->bp_power, GPIO_LOW);
msleep(1000);
gpio_set_value(pdata->bp_power, GPIO_HIGH);
msleep(700);
gpio_set_value(pdata->bp_power, GPIO_LOW);
gpio_set_value(pdata->ap_wakeup_bp, GPIO_LOW);
break;
default:
break;
}
return 0;
}
static struct file_operations mu509_fops = {
.owner = THIS_MODULE,
.open = mu509_open,
.release = mu509_release,
.unlocked_ioctl = mu509_ioctl
};
static struct miscdevice mu509_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = MODEM_NAME,
.fops = &mu509_fops
};
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
static ssize_t modem_status_read(struct class *cls, struct class_attribute *attr, char *_buf)
#else
static ssize_t modem_status_read(struct class *cls, char *_buf)
#endif
{
return sprintf(_buf, "%d\n", modem_status);
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
static ssize_t modem_status_write(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count)
#else
static ssize_t modem_status_write(struct class *cls, const char *_buf, size_t _count)
#endif
{
int new_state = simple_strtoul(_buf, NULL, 16);
if(new_state == modem_status) return _count;
if (new_state == 1){
printk("%s, c(%d), open modem \n", __FUNCTION__, new_state);
modem_poweron_off(1);
}else if(new_state == 0){
printk("%s, c(%d), close modem \n", __FUNCTION__, new_state);
modem_poweron_off(0);
}else{
printk("%s, invalid parameter \n", __FUNCTION__);
}
modem_status = new_state;
return _count;
}
static CLASS_ATTR(modem_status, 0777, modem_status_read, modem_status_write);
static void rk29_early_suspend(struct early_suspend *h)
{
}
static void rk29_early_resume(struct early_suspend *h)
{
if(suspend_int)
{
gpio_set_value(gpdata->ap_wakeup_bp, 0);
suspend_int = 0;
}
}
static struct early_suspend mu509_early_suspend = {
.suspend = rk29_early_suspend,
.resume = rk29_early_resume,
.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1,
};
static int mu509_probe(struct platform_device *pdev)
{
struct rk29_mu509_data *pdata = gpdata = pdev->dev.platform_data;
struct modem_dev *mu509_data = NULL;
int result, irq = 0;
pdata->dev = &pdev->dev;
if(pdata->io_init)
pdata->io_init();
gpio_set_value(pdata->modem_power_en, GPIO_HIGH);
msleep(1000);
modem_poweron_off(1);
modem_status = 1;
register_early_suspend(&mu509_early_suspend);
mu509_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
if(mu509_data == NULL)
{
printk("failed to request mu509_data\n");
goto err2;
}
platform_set_drvdata(pdev, mu509_data);
result = gpio_request(pdata->ap_wakeup_bp, "mu509");
if (result) {
printk("failed to request AP_BP_WAKEUP gpio\n");
goto err1;
}
irq = gpio_to_irq(pdata->bp_wakeup_ap);
enable_irq_wake(irq);
if(irq < 0)
{
gpio_free(pdata->bp_wakeup_ap);
printk("failed to request bp_wakeup_ap\n");
}
result = gpio_request(pdata->bp_wakeup_ap, "bp_wakeup_ap");
if (result < 0) {
printk("%s: gpio_request(%d) failed\n", __func__, pdata->bp_wakeup_ap);
}
wake_lock_init(&modem_wakelock, WAKE_LOCK_SUSPEND, "bp_wakeup_ap");
gpio_direction_input(pdata->bp_wakeup_ap);
gpio_pull_updown(pdata->bp_wakeup_ap, 1);
result = request_irq(irq, detect_irq_handler, IRQ_BB_WAKEUP_AP_TRIGGER, "bp_wakeup_ap", NULL);
if (result < 0) {
printk("%s: request_irq(%d) failed\n", __func__, irq);
gpio_free(pdata->bp_wakeup_ap);
goto err0;
}
enable_irq_wake(gpio_to_irq(pdata->bp_wakeup_ap));
result = misc_register(&mu509_misc);
if(result)
{
printk("misc_register err\n");
}
return result;
err0:
cancel_work_sync(&mu509_data->work);
gpio_free(pdata->bp_wakeup_ap);
err1:
gpio_free(pdata->ap_wakeup_bp);
err2:
kfree(mu509_data);
return 0;
}
int mu509_suspend(struct platform_device *pdev, pm_message_t state)
{
suspend_int = 1;
do_wakeup_irq = 1;
ap_wakeup_bp(pdev, 1);
#if defined(CONFIG_ARCH_RK29)
rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_GPIO1C1);
#endif
#if defined(CONFIG_ARCH_RK30)
rk30_mux_api_set(GPIO1A7_UART1RTSN_SPI0TXD_NAME, GPIO1A_GPIO1A7);
#endif
return 0;
}
int mu509_resume(struct platform_device *pdev)
{
#if defined(CONFIG_ARCH_RK29)
rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_UART0_RTS_N);
#endif
#if defined(CONFIG_ARCH_RK30)
rk30_mux_api_set(GPIO1A7_UART1RTSN_SPI0TXD_NAME, GPIO1A_UART1_RTS_N);
#endif
if(gpio_get_value(gpdata->bp_wakeup_ap))
{
schedule_delayed_work(&wakeup_work, 2*HZ);
}
return 0;
}
void mu509_shutdown(struct platform_device *pdev)
{
struct rk29_mu509_data *pdata = pdev->dev.platform_data;
struct modem_dev *mu509_data = platform_get_drvdata(pdev);
modem_poweron_off(0);
if(pdata->io_deinit)
pdata->io_deinit();
cancel_work_sync(&mu509_data->work);
gpio_free(pdata->modem_power_en);
gpio_free(pdata->bp_power);
gpio_free(pdata->bp_reset);
gpio_free(pdata->ap_wakeup_bp);
gpio_free(pdata->bp_wakeup_ap);
kfree(mu509_data);
}
static struct platform_driver mu509_driver = {
.probe = mu509_probe,
.shutdown = mu509_shutdown,
.suspend = mu509_suspend,
.resume = mu509_resume,
.driver = {
.name = "mu509",
.owner = THIS_MODULE,
},
};
static int __init mu509_init(void)
{
int ret ;
modem_class = class_create(THIS_MODULE, "rk291x_modem");
ret = class_create_file(modem_class, &class_attr_modem_status);
if (ret)
{
printk("Fail to class rk291x_modem.\n");
}
return platform_driver_register(&mu509_driver);
}
static void __exit mu509_exit(void)
{
platform_driver_unregister(&mu509_driver);
class_remove_file(modem_class, &class_attr_modem_status);
}
module_init(mu509_init);
module_exit(mu509_exit);

View File

@@ -1,235 +0,0 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/circ_buf.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <mach/iomux.h>
#include <mach/gpio.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/wakelock.h>
#include <linux/workqueue.h>
#include <linux/mw100.h>
#include <mach/iomux.h>
#include<linux/ioctl.h>
#include <linux/slab.h>
MODULE_LICENSE("GPL");
#ifdef DEBUG
#define MODEMDBG(x...) printk(x)
#else
#define MODEMDBG(fmt,argss...)
#endif
#define MW100IO 0XA1
#define MW_IOCTL_RESET _IO(MW100IO,0X01)
#define SLEEP 1
#define READY 0
#define MW100_RESET 0x01
#define IRQ_BB_WAKEUP_AP_TRIGGER IRQF_TRIGGER_RISING
//#define IRQ_BB_WAKEUP_AP_TRIGGER IRQF_TRIGGER_RISING
struct rk29_mw100_data *gpdata = NULL;
static int bp_wakeup_ap_irq = 0;
static struct wake_lock bp_wakelock;
static bool bpstatus_irq_enable = false;
static void do_wakeup(struct work_struct *work)
{
enable_irq(bp_wakeup_ap_irq);
}
static DECLARE_DELAYED_WORK(wakeup_work, do_wakeup);
static irqreturn_t detect_irq_handler(int irq, void *dev_id)
{
wake_lock_timeout(&bp_wakelock, 10 * HZ);
return IRQ_HANDLED;
}
static int mw100_open(struct inode *inode, struct file *file)
{
return 0;
}
static int mw100_release(struct inode *inode, struct file *file)
{
return 0;
}
static long mw100_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct rk29_mw100_data *pdata = gpdata;
switch(cmd)
{
case MW_IOCTL_RESET:
gpio_direction_output(pdata->bp_reset,GPIO_LOW);
mdelay(120);
gpio_set_value(pdata->bp_reset, GPIO_HIGH);
break;
default:
break;
}
return 0;
}
static struct file_operations mw100_fops = {
.owner = THIS_MODULE,
.open = mw100_open,
.release = mw100_release,
.unlocked_ioctl = mw100_ioctl
};
static struct miscdevice mw100_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "mw100",
.fops = &mw100_fops
};
static int mw100_probe(struct platform_device *pdev)
{
struct rk29_mw100_data *pdata = gpdata = pdev->dev.platform_data;
struct modem_dev *mw100_data = NULL;
int result, irq = 0;
gpio_request(pdata->bp_power,"bp_power");
gpio_request(pdata->bp_reset,"bp_reset");
gpio_request(pdata->bp_wakeup_ap,"bp_wakeup_ap");
gpio_request(pdata->ap_wakeup_bp,"ap_wakeup_bp");
gpio_set_value(pdata->modem_power_en, GPIO_HIGH);
msleep(1000);
gpio_direction_output(pdata->bp_reset,GPIO_LOW);
mdelay(120);
gpio_set_value(pdata->bp_reset, GPIO_HIGH);
gpio_set_value(pdata->ap_wakeup_bp, GPIO_HIGH);
gpio_direction_output(pdata->ap_wakeup_bp,GPIO_HIGH);
gpio_set_value(pdata->bp_power, GPIO_HIGH);
gpio_direction_output(pdata->bp_power,GPIO_HIGH);
mdelay(120);
gpio_set_value(pdata->bp_power, GPIO_LOW);
gpio_direction_output(pdata->bp_power,GPIO_LOW);
mw100_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
if(mw100_data == NULL){
printk("failed to request mw100_data\n");
goto err2;
}
platform_set_drvdata(pdev, mw100_data);
gpio_direction_input(pdata->bp_wakeup_ap);
irq = gpio_to_irq(pdata->bp_wakeup_ap);
if(irq < 0){
gpio_free(pdata->bp_wakeup_ap);
printk("failed to request bp_wakeup_ap\n");
}
bp_wakeup_ap_irq = irq;
result = request_irq(irq, detect_irq_handler, IRQ_BB_WAKEUP_AP_TRIGGER, "bp_wakeup_ap", NULL);
if (result < 0) {
printk("%s: request_irq(%d) failed\n", __func__, irq);
gpio_free(pdata->bp_wakeup_ap);
goto err0;
}
enable_irq_wake(bp_wakeup_ap_irq);
wake_lock_init(&bp_wakelock, WAKE_LOCK_SUSPEND, "bp_resume");
result = misc_register(&mw100_misc);
if(result){
MODEMDBG("misc_register err\n");
}
return result;
err0:
gpio_free(pdata->bp_wakeup_ap);
err2:
kfree(mw100_data);
return 0;
}
int mw100_suspend(struct platform_device *pdev, pm_message_t state)
{
struct rk29_mw100_data *pdata = pdev->dev.platform_data;
int irq;
gpio_set_value(pdata->ap_wakeup_bp, GPIO_LOW);
irq = gpio_to_irq(pdata->bp_wakeup_ap);
if (irq < 0) {
printk("can't get pdata->bp_statue irq \n");
}
else
{
bpstatus_irq_enable = true;
enable_irq_wake(irq);
}
return 0;
}
int mw100_resume(struct platform_device *pdev)
{
struct rk29_mw100_data *pdata = pdev->dev.platform_data;
int irq;
gpio_set_value(pdata->ap_wakeup_bp, GPIO_HIGH);
irq = gpio_to_irq(pdata->bp_wakeup_ap);
if (irq ) {
disable_irq_wake(irq);
bpstatus_irq_enable = false;
}
return 0;
}
void mw100_shutdown(struct platform_device *pdev)
{
struct rk29_mw100_data *pdata = pdev->dev.platform_data;
struct modem_dev *mw100_data = platform_get_drvdata(pdev);
gpio_set_value(pdata->bp_power, GPIO_HIGH);
mdelay(2010);
gpio_free(pdata->modem_power_en);
gpio_free(pdata->bp_power);
gpio_free(pdata->bp_reset);
gpio_free(pdata->ap_wakeup_bp);
gpio_free(pdata->bp_wakeup_ap);
kfree(mw100_data);
}
static struct platform_driver mw100_driver = {
.probe = mw100_probe,
.shutdown = mw100_shutdown,
.suspend = mw100_suspend,
.resume = mw100_resume,
.driver = {
.name = "mw100",
.owner = THIS_MODULE,
},
};
static int __init mw100_init(void)
{
return platform_driver_register(&mw100_driver);
}
static void __exit mw100_exit(void)
{
platform_driver_unregister(&mw100_driver);
}
module_init(mw100_init);
module_exit(mw100_exit);

View File

@@ -1,231 +0,0 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/circ_buf.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <mach/iomux.h>
#include <mach/gpio.h>
#include <asm/gpio.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/wakelock.h>
#include <linux/workqueue.h>
#include <linux/sc6610.h>
#include <linux/slab.h>
#include <linux/earlysuspend.h>
MODULE_LICENSE("GPL");
#define DEBUG 1
#ifdef DEBUG
#define MODEMDBG(x...) printk(x)
#else
#define MODEMDBG(fmt,argss...)
#endif
#define MODEM_RESET 2
#define MODEM_ON 1
#define MODEM_OFF 0
struct rk29_sc6610_data *s_gpdata = NULL;
struct class *modem_class = NULL;
static int do_wakeup_irq = 0;
static struct wake_lock modem_wakelock;
//#define IRQ_BB_WAKEUP_AP_TRIGGER IRQF_TRIGGER_FALLING
#define IRQ_BB_WAKEUP_AP_TRIGGER IRQF_TRIGGER_RISING
int modem_poweron_off(int on_off)
{
struct rk29_sc6610_data *pdata = s_gpdata;
if(on_off){
gpio_set_value(pdata->bp_power, GPIO_HIGH);
}else{
gpio_set_value(pdata->bp_power, GPIO_LOW);
}
return 0;
}
static irqreturn_t detect_irq_handler(int irq, void *dev_id)
{
if(do_wakeup_irq)
{
do_wakeup_irq = 0;
wake_lock_timeout(&modem_wakelock, 10 * HZ);
}
return IRQ_HANDLED;
}
static int sc6610_open(struct inode *inode, struct file *file)
{
return 0;
}
static int sc6610_release(struct inode *inode, struct file *file)
{
return 0;
}
static long sc6610_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct rk29_sc6610_data *pdata = s_gpdata;
switch(cmd)
{
case MODEM_RESET:
gpio_set_value(pdata->bp_reset, GPIO_LOW);
msleep(2000);
gpio_set_value(pdata->bp_reset, GPIO_HIGH);
break;
case MODEM_ON:
modem_poweron_off(MODEM_ON);
break;
case MODEM_OFF:
modem_poweron_off(MODEM_OFF);
break;
default:
break;
}
return 0;
}
static struct file_operations sc6610_fops = {
.owner = THIS_MODULE,
.open = sc6610_open,
.release = sc6610_release,
.unlocked_ioctl = sc6610_ioctl
};
static struct miscdevice sc6610_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = MODEM_NAME,
.fops = &sc6610_fops
};
static int sc6610_probe(struct platform_device *pdev)
{
struct rk29_sc6610_data *pdata = s_gpdata = pdev->dev.platform_data;
struct modem_dev *sc6610_data = NULL;
int result;
int irq;
pdata->dev = &pdev->dev;
if(pdata->io_init)
pdata->io_init();
result = gpio_request(pdata->ap_wakeup_bp, "ap_wakeup_bp");
if (result) {
printk("failed to request ap_wakeup_bp gpio\n");
goto err0;
}
result = gpio_request(pdata->bp_power, "bp_power");
if (result) {
printk("failed to request bp_power gpio\n");
goto err1;
}
result = gpio_request(pdata->bp_wakeup_ap, "bp_wakeup_ap");
if (result) {
printk("failed to request bp_wakeup_ap gpio\n");
goto err2;
}
gpio_set_value(pdata->ap_wakeup_bp, GPIO_HIGH);
irq = gpio_to_irq(pdata->bp_wakeup_ap);
result = request_irq(irq, detect_irq_handler, IRQ_BB_WAKEUP_AP_TRIGGER, "bp_wakeup_ap", NULL);
if (result < 0) {
printk("%s: request_irq(%d) failed\n", __func__, irq);
goto err2;
}
enable_irq_wake(irq);
wake_lock_init(&modem_wakelock, WAKE_LOCK_SUSPEND, "bp_wakeup_ap");
sc6610_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
if(sc6610_data == NULL)
{
printk("failed to request sc6610_data\n");
goto err3;
}
platform_set_drvdata(pdev, sc6610_data);
result = misc_register(&sc6610_misc);
if(result)
{
printk("misc_register err\n");
}
modem_poweron_off(MODEM_ON);
return result;
err0:
gpio_free(pdata->ap_wakeup_bp);
err1:
gpio_free(pdata->bp_power);
err2:
gpio_free(pdata->bp_wakeup_ap);
err3:
kfree(sc6610_data);
return 0;
}
int c6610_suspend(struct platform_device *pdev, pm_message_t state)
{
struct rk29_sc6610_data *pdata = s_gpdata = pdev->dev.platform_data;
pdata->dev = &pdev->dev;
do_wakeup_irq = 1;
gpio_set_value(pdata->ap_wakeup_bp, GPIO_LOW);
return 0;
}
int c6610_resume(struct platform_device *pdev)
{
struct rk29_sc6610_data *pdata = s_gpdata = pdev->dev.platform_data;
pdata->dev = &pdev->dev;
gpio_set_value(pdata->ap_wakeup_bp, GPIO_HIGH);
return 0;
}
void c6610_shutdown(struct platform_device *pdev)
{
struct rk29_sc6610_data *pdata = pdev->dev.platform_data;
struct modem_dev *sc6610_data = platform_get_drvdata(pdev);
modem_poweron_off(MODEM_OFF);
if(pdata->io_deinit)
pdata->io_deinit();
cancel_work_sync(&sc6610_data->work);
gpio_free(pdata->bp_power);
gpio_free(pdata->ap_wakeup_bp);
gpio_free(pdata->bp_wakeup_ap);
kfree(sc6610_data);
}
static struct platform_driver sc6610_driver = {
.probe = sc6610_probe,
.shutdown = c6610_shutdown,
.suspend = c6610_suspend,
.resume = c6610_resume,
.driver = {
.name = "SC6610",
.owner = THIS_MODULE,
},
};
static int __init sc6610_init(void)
{
return platform_driver_register(&sc6610_driver);
}
static void __exit sc6610_exit(void)
{
platform_driver_unregister(&sc6610_driver);
}
module_init(sc6610_init);
module_exit(sc6610_exit);

View File

@@ -1,228 +0,0 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/circ_buf.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <mach/iomux.h>
#include <mach/gpio.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/wakelock.h>
#include <linux/workqueue.h>
#include <linux/sew868.h>
#include<linux/ioctl.h>
#include<linux/slab.h>
MODULE_LICENSE("GPL");
#define DEBUG
#ifdef DEBUG
#define MODEMDBG(x...) printk(x)
#else
#define MODEMDBG(fmt,argss...)
#endif
#define SLEEP 1
#define READY 0
#define SEW868_RESET 0x01
#define SEW868_POWON 0x02
#define SEW868_POWOFF 0x03
static struct wake_lock modem_wakelock;
#define IRQ_BB_WAKEUP_AP_TRIGGER IRQF_TRIGGER_FALLING
//#define IRQ_BB_WAKEUP_AP_TRIGGER IRQF_TRIGGER_RISING
struct rk30_sew868_data *gpdata = NULL;
static int do_wakeup_irq = 0;
extern void rk28_send_wakeup_key(void);
static void do_wakeup(struct work_struct *work)
{
rk28_send_wakeup_key();
}
static DECLARE_DELAYED_WORK(wakeup_work, do_wakeup);
static irqreturn_t detect_irq_handler(int irq, void *dev_id)
{
printk("%s\n", __FUNCTION__);
if(do_wakeup_irq)
{
do_wakeup_irq = 0;
wake_lock_timeout(&modem_wakelock, 10 * HZ);
schedule_delayed_work(&wakeup_work, HZ / 10);
}
return IRQ_HANDLED;
}
int modem_poweron_off(int on_off)
{
struct rk30_sew868_data *pdata = gpdata;
if(on_off)
{
gpio_direction_output(pdata->bp_sys, GPIO_HIGH);
gpio_set_value(pdata->bp_power, GPIO_LOW);
msleep(200);//for charge
gpio_set_value(pdata->bp_power, GPIO_HIGH);
msleep(4000);
gpio_set_value(pdata->bp_power, GPIO_LOW);
msleep(200);
}
else
{
gpio_set_value(pdata->bp_power, GPIO_HIGH);
msleep(4000);
gpio_set_value(pdata->bp_power, GPIO_LOW);
gpio_set_value(pdata->bp_sys, GPIO_LOW);
msleep(50);
gpio_set_value(pdata->bp_power, GPIO_LOW);
}
return 0;
}
static int sew868_open(struct inode *inode, struct file *file)
{
return 0;
}
static int sew868_release(struct inode *inode, struct file *file)
{
return 0;
}
static long sew868_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct rk30_sew868_data *pdata = gpdata;
switch(cmd)
{
case SEW868_RESET:
gpio_set_value(pdata->bp_reset, GPIO_HIGH);
mdelay(100);
gpio_set_value(pdata->bp_reset, GPIO_LOW);
mdelay(200);
modem_poweron_off(1);
break;
case SEW868_POWON:
modem_poweron_off(1);
break;
case SEW868_POWOFF:
modem_poweron_off(0);
break;
default:
break;
}
return 0;
}
static struct file_operations sew868_fops = {
.owner = THIS_MODULE,
.open = sew868_open,
.release = sew868_release,
.unlocked_ioctl = sew868_ioctl
};
static struct miscdevice sew868_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = MODEM_NAME,
.fops = &sew868_fops
};
static int sew868_probe(struct platform_device *pdev)
{
struct rk30_sew868_data *pdata = gpdata = pdev->dev.platform_data;
struct modem_dev *sew868_data = NULL;
int result, irq = 0;
if(pdata->io_init)
pdata->io_init();
modem_poweron_off(1);
sew868_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
if(sew868_data == NULL)
{
printk("failed to request sew868_data\n");
goto err1;
}
platform_set_drvdata(pdev, sew868_data);
irq = gpio_to_irq(pdata->bp_wakeup_ap);
if(irq < 0)
{
gpio_free(pdata->bp_wakeup_ap);
printk("failed to request bp_wakeup_ap\n");
}
wake_lock_init(&modem_wakelock, WAKE_LOCK_SUSPEND, "bp_wakeup_ap");
gpio_direction_input(pdata->bp_wakeup_ap);
gpio_pull_updown(pdata->bp_wakeup_ap, GPIONormal);
result = request_irq(irq, detect_irq_handler, IRQ_BB_WAKEUP_AP_TRIGGER, "bp_wakeup_ap", NULL);
if (result < 0) {
printk("%s: request_irq(%d) failed\n", __func__, irq);
gpio_free(pdata->bp_wakeup_ap);
goto err0;
}
enable_irq_wake(gpio_to_irq(pdata->bp_wakeup_ap));
result = misc_register(&sew868_misc);
if(result)
{
MODEMDBG("misc_register err\n");
}
return result;
err0:
cancel_work_sync(&sew868_data->work);
err1:
kfree(sew868_data);
return 0;
}
int sew868_suspend(struct platform_device *pdev, pm_message_t state)
{
do_wakeup_irq = 1;
return 0;
}
int sew868_resume(struct platform_device *pdev)
{
return 0;
}
void sew868_shutdown(struct platform_device *pdev)
{
struct rk30_sew868_data *pdata = pdev->dev.platform_data;
struct modem_dev *sew868_data = platform_get_drvdata(pdev);
modem_poweron_off(0);
if(pdata->io_deinit)
pdata->io_deinit();
cancel_work_sync(&sew868_data->work);
kfree(sew868_data);
}
static struct platform_driver sew868_driver = {
.probe = sew868_probe,
.shutdown = sew868_shutdown,
.suspend = sew868_suspend,
.resume = sew868_resume,
.driver = {
.name = "sew868",
.owner = THIS_MODULE,
},
};
static int __init sew868_init(void)
{
return platform_driver_register(&sew868_driver);
}
static void __exit sew868_exit(void)
{
platform_driver_unregister(&sew868_driver);
}
module_init(sew868_init);
module_exit(sew868_exit);

View File

@@ -564,7 +564,6 @@ source "drivers/misc/iwmc3200top/Kconfig"
source "drivers/misc/ti-st/Kconfig"
source "drivers/misc/lis3lv02d/Kconfig"
source "drivers/misc/carma/Kconfig"
source "drivers/misc/3g_module/Kconfig"
source "drivers/misc/bp/Kconfig"
source "drivers/misc/rk2928_callpad_misc/Kconfig"

View File

@@ -54,7 +54,6 @@ obj-$(CONFIG_SENSORS_AK8963) += akm8963.o
obj-$(CONFIG_MTK23D) += mtk23d.o
obj-$(CONFIG_FM580X) += fm580x.o
obj-$(CONFIG_RK29_SUPPORT_MODEM) += rk29_modem/
obj-$(CONFIG_3G_MODULE) += 3g_module/
obj-$(CONFIG_BP_AUTO) += bp/
obj-$(CONFIG_GPS_DEVICES) += gps/
obj-y += inv_mpu/

View File

@@ -2,12 +2,7 @@
# all auto modem control drivers configuration
#
menuconfig BP_AUTO
bool "auto modem control driver support"
config BP_AUTO
bool "voice modem support"
default n
if BP_AUTO
source "drivers/misc/bp/chips/Kconfig"
endif

View File

@@ -23,6 +23,7 @@
#include <linux/earlysuspend.h>
#include <linux/bp-auto.h>
#include "../../mtd/rknand/api_flash.h"
#if 0
#define DBG(x...) printk(x)
@@ -34,7 +35,9 @@ struct bp_private_data *g_bp;
static struct class *g_bp_class;
static struct bp_operate *g_bp_ops[BP_ID_NUM];
struct class *bp_class = NULL;
int get_current_bp_id(){
return g_bp->ops->bp_id;
}
static void ap_wakeup_bp(struct bp_private_data *bp, int wake)
{
if(bp->ops->ap_wake_bp)
@@ -91,7 +94,7 @@ static int bp_request_gpio(struct bp_private_data *bp)
if(bp->pdata->bp_uart_en > 0)
{
bp->ops->bp_uart_en = bp->pdata->bp_uart_en;
}
}
}
@@ -197,9 +200,10 @@ static irqreturn_t bp_wake_up_irq(int irq, void *dev_id)
{
struct bp_private_data *bp = dev_id;
if(bp->ops->bp_wake_ap)
printk("<---%s:bp_id=%d--->\n",__FUNCTION__,bp->ops->bp_id);
if(bp->ops->bp_wake_ap){
bp->ops->bp_wake_ap(bp);
}
return IRQ_HANDLED;
}
@@ -212,7 +216,7 @@ static int bp_id_open(struct inode *inode, struct file *file)
static int bp_id_release(struct inode *inode, struct file *file)
{
return 0;
}
@@ -248,7 +252,8 @@ static long bp_id_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
static int bp_dev_open(struct inode *inode, struct file *file)
{
struct bp_private_data *bp = g_bp;
device_init_wakeup(bp->dev, 1);
printk("<---%s:bp_id=%d--->\n",__FUNCTION__,bp->ops->bp_id);
device_init_wakeup(bp->dev, 1);
return 0;
}
static ssize_t bp_dev_write(struct file *file, const char __user *buf,size_t len, loff_t *off)
@@ -256,15 +261,15 @@ static ssize_t bp_dev_write(struct file *file, const char __user *buf,size_t len
static char cmd[2];
struct bp_private_data *bp = g_bp;
int ret = 0;
if (len > 2)
{
return -EINVAL;
}
ret = copy_from_user(&cmd, buf, len);
if (ret != 0) {
return -EFAULT;
}
int ret = 0;
if (len > 2)
{
return -EINVAL;
}
ret = copy_from_user(&cmd, buf, len);
if (ret != 0) {
return -EFAULT;
}
printk(" received cmd = %c\n",cmd[0]);
switch(bp->ops->bp_id)
{
@@ -305,6 +310,9 @@ static ssize_t bp_dev_write(struct file *file, const char __user *buf,size_t len
}
static int bp_dev_release(struct inode *inode, struct file *file)
{
struct bp_private_data *bp = g_bp;
printk("<---%s:bp_id=%d--->\n",__FUNCTION__,bp->ops->bp_id);
return 0;
}
@@ -312,8 +320,9 @@ static long bp_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct bp_private_data *bp = g_bp;
void __user *argp = (void __user *)arg;
char SectorBuffer[512];
int result = 0;
printk("<---%s:bp_id=%d,cmd=%d--->\n",__FUNCTION__,bp->ops->bp_id,cmd);
switch(cmd)
{
case BP_IOCTL_RESET:
@@ -321,22 +330,18 @@ static long bp_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
bp->ops->reset(bp);
}
else if(bp->ops->active)
{
bp->ops->active(bp, 0);
msleep(100);
bp->ops->active(bp, 1);
}
break;
case BP_IOCTL_POWON:
if(bp->ops->active)
bp->ops->active(bp, 1);
bp->status = BP_ON;
break;
case BP_IOCTL_POWOFF:
if(bp->ops->active)
bp->ops->active(bp, 0);
bp->status = BP_OFF;
break;
case BP_IOCTL_WRITE_STATUS:
@@ -359,6 +364,15 @@ static long bp_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
break;
case BP_IOCTL_GET_IMEI:
printk("BP_IMEI_READ\n");
GetSNSectorInfo(SectorBuffer);
if(copy_to_user(argp, &(SectorBuffer[451]), 16)) // IMEIo<49><6F><EFBFBD>䨮451??<3F><>??a<><61>?<3F><>?16bytes<65><73>?<3F>̨<EFBFBD><CCA8><EFBFBD>???byte?a3<61><33>?<3F><>1<EFBFBD><31>?<3F><>?a15
{
printk("ERROR: copy_to_user---%s\n", __FUNCTION__);
return -EFAULT;
}
break;
default:
break;
@@ -382,23 +396,39 @@ static ssize_t bp_status_write(struct class *cls, struct class_attribute *attr,
int status = 0;
status = simple_strtoul(_buf, NULL, 16);
printk("<<<<<<<<--%s:buf:%s,status=%d\n",__func__,_buf,status);
if(status == bp->status)
return _count;
bp->status = status;
if(bp->ops->write_status)
if(bp->ops->write_status){
result = bp->ops->write_status(bp);
}else{
switch(status)
{
case 1://modem power on
if(bp->ops->active)
bp->ops->active(bp, 1);
break;
case 0: // modem power off
if(bp->ops->active)
bp->ops->active(bp, 0);
break;
default:
break;
}
}
return result;
}
static CLASS_ATTR(bp_status, 0777, bp_status_read, bp_status_write);
//static CLASS_ATTR(bp_status, 0777, bp_status_read, bp_status_write);
static int bp_probe(struct platform_device *pdev)
{
struct bp_platform_data *pdata = pdev->dev.platform_data;
struct bp_private_data *bp = NULL;
int i = 0, result;
int i = 0, result,irq = 0;
if(!pdata)
return -1;
@@ -406,7 +436,8 @@ static int bp_probe(struct platform_device *pdev)
if(pdata->init_platform_hw)
pdata->init_platform_hw();
if(pdata->get_bp_id())
pdata->bp_id = pdata->get_bp_id();
bp = kzalloc(sizeof(struct bp_private_data), GFP_KERNEL);
if(bp == NULL)
{
@@ -434,25 +465,26 @@ static int bp_probe(struct platform_device *pdev)
else
{
printk("%s:bp_id=%d is out of range\n",__func__, pdata->bp_id);
return -1;
}
bp_request_gpio(bp);
if(bp->ops->init)
bp->ops->init(bp);
bp->ops->irq = 0;
wake_lock_init(&bp->bp_wakelock, WAKE_LOCK_SUSPEND, "bp_wakelock");
if((bp->ops->bp_wakeup_ap) && (bp->ops->trig != BP_UNKNOW_DATA))
{
result = request_irq(bp->ops->bp_wakeup_ap, bp_wake_up_irq, bp->ops->trig, "bp_wakeup_ap", bp);
irq = gpio_to_irq(bp->ops->bp_wakeup_ap);
result = request_irq(irq, bp_wake_up_irq, bp->ops->trig, "bp_wakeup_ap", bp);
if (result < 0) {
printk("%s: request_irq(%d) failed\n", __func__, bp->ops->bp_wakeup_ap);
gpio_free(pdata->bp_wakeup_ap);
return result;
}
bp->ops->irq = irq;
}
if(bp->ops->init)
bp->ops->init(bp);
enable_irq_wake(bp->ops->bp_wakeup_ap);
wake_lock_init(&bp->bp_wakelock, WAKE_LOCK_SUSPEND, "bp_wakelock");
bp->status = BP_OFF;
@@ -468,7 +500,7 @@ static int bp_probe(struct platform_device *pdev)
if(bp->ops->misc_name)
bp->miscdev.name = bp->ops->misc_name;
else
bp->miscdev.name = "bp-auto";
bp->miscdev.name = BP_DEV_NAME;
bp->miscdev.fops = &bp->fops;
}
else
@@ -512,14 +544,15 @@ int bp_suspend(struct platform_device *pdev, pm_message_t state)
if(bp->ops->suspend)
bp->ops->suspend(bp);
enable_irq_wake(bp->ops->irq);
return 0;
}
int bp_resume(struct platform_device *pdev)
{
struct bp_private_data *bp = platform_get_drvdata(pdev);
disable_irq_wake(bp->ops->irq);
if(bp->ops->resume)
bp->ops->resume(bp);
@@ -532,7 +565,9 @@ void bp_shutdown(struct platform_device *pdev)
if(bp->ops->shutdown)
bp->ops->shutdown(bp);
if(bp->ops->irq){
free_irq(bp->ops->irq,bp);
}
}
@@ -584,19 +619,19 @@ static struct platform_driver bp_driver = {
static int __init bp_init(void)
{
int ret ;
bp_class = class_create(THIS_MODULE, "bp-auto");
ret = class_create_file(bp_class, &class_attr_bp_status);
if (ret)
{
printk("Fail to create class bp-auto\n");
}
//bp_class = class_create(THIS_MODULE, "bp-auto");
//ret = class_create_file(bp_class, &class_attr_bp_status);
//if (ret)
//{
// printk("Fail to create class bp-auto\n");
//}
return platform_driver_register(&bp_driver);
}
static void __exit bp_exit(void)
{
platform_driver_unregister(&bp_driver);
class_remove_file(bp_class, &class_attr_bp_status);
//class_remove_file(bp_class, &class_attr_bp_status);
}
module_init(bp_init);

13
drivers/misc/bp/chips/Kconfig Normal file → Executable file
View File

@@ -4,4 +4,15 @@ bool "modem mt6229"
config BP_AUTO_MU509
bool "modem mu509"
default n
default n
config BP_AUTO_MW100
bool "modem mw100"
default n
config BP_AUTO_MI700
bool "modem mi700"
default n
config BP_AUTO_C66A
bool "modem c66a"
default n

10
drivers/misc/bp/chips/Makefile Normal file → Executable file
View File

@@ -1,2 +1,8 @@
obj-$(CONFIG_BP_AUTO_MT6229) += mt6229.o
obj-$(CONFIG_BP_AUTO_MU509) += mu509.o
obj-$(CONFIG_BP_AUTO) += mw100.o
obj-$(CONFIG_BP_AUTO) += mi700.o
obj-$(CONFIG_BP_AUTO) += mt6229.o
obj-$(CONFIG_BP_AUTO) += mu509.o
obj-$(CONFIG_BP_AUTO) += sc6610.o
obj-$(CONFIG_BP_AUTO) += m51.o
obj-$(CONFIG_BP_AUTO) += mtk6250.o
obj-$(CONFIG_BP_AUTO) += c66a.o

View File

@@ -0,0 +1,207 @@
/* drivers/misc/bp/chips/c66a.c
*
* Copyright (C) 2012-2015 ROCKCHIP.
* Author: luowei <lw@rock-chips.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/circ_buf.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <mach/iomux.h>
#include <mach/gpio.h>
#include <asm/gpio.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/wakelock.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/earlysuspend.h>
#include <linux/bp-auto.h>
#if 0
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
/****************operate according to bp chip:start************/
static int bp_active(struct bp_private_data *bp, int enable)
{
int result = 0;
if(enable)
{
printk("<-----c66a power on-------->\n");
gpio_set_value(bp->ops->bp_power, GPIO_HIGH);
}
else
{
printk("<-----c66a power on-------->\n");
gpio_set_value(bp->ops->bp_power, GPIO_LOW);
msleep(500);
}
return result;
}
static void ap_wake_bp_work(struct work_struct *work)
{
return;
}
static int bp_wake_ap(struct bp_private_data *bp)
{
int result = 0;
if(bp->suspend_status)
{
printk("<-----c66a bp_wake_ap-------->\n");
bp->suspend_status = 0;
wake_lock_timeout(&bp->bp_wakelock, 10 * HZ);
}
return result;
}
static int bp_init(struct bp_private_data *bp)
{
int result = 0;
gpio_direction_input(bp->ops->bp_wakeup_ap);
gpio_direction_output(bp->ops->bp_power,GPIO_LOW);
gpio_direction_output(bp->ops->ap_wakeup_bp,GPIO_HIGH);
INIT_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);
return result;
}
static int bp_reset(struct bp_private_data *bp)
{
printk("ioctrl c66a reset !!! \n");
gpio_set_value(bp->ops->bp_power, GPIO_LOW);
msleep(2000);
gpio_set_value(bp->ops->bp_power, GPIO_HIGH);
return 0;
}
static int bp_shutdown(struct bp_private_data *bp)
{
int result = 0;
if(bp->ops->active)
bp->ops->active(bp, 0);
cancel_delayed_work_sync(&bp->wakeup_work);
return result;
}
static int bp_suspend(struct bp_private_data *bp)
{
int result = 0;
bp->suspend_status = 1;
gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);
return result;
}
static int bp_resume(struct bp_private_data *bp)
{
printk("<-----c66a bp_resume-------->\n");
bp->suspend_status = 0;
gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_HIGH);
return 0;
}
struct bp_operate bp_c66a_ops = {
.name = "c66a",
.bp_id = BP_ID_C66A,
.bp_bus = BP_BUS_TYPE_UART,
.bp_pid = 0,
.bp_vid = 0,
.bp_power = BP_UNKNOW_DATA,//RK2928_PIN3_PC2, // 3g_power
.bp_en = BP_UNKNOW_DATA, // 3g_en
.bp_reset = BP_UNKNOW_DATA,
.ap_ready = BP_UNKNOW_DATA, //
.bp_ready = BP_UNKNOW_DATA,
.ap_wakeup_bp = BP_UNKNOW_DATA,//RK2928_PIN3_PC4,
.bp_wakeup_ap = BP_UNKNOW_DATA,//RK2928_PIN3_PC3, //
.bp_uart_en = BP_UNKNOW_DATA, //EINT9
.bp_usb_en = BP_UNKNOW_DATA, //W_disable
.bp_assert = BP_UNKNOW_DATA,//RK2928_PIN3_PC5,
.trig = IRQF_TRIGGER_RISING,
.active = bp_active,
.init = bp_init,
.reset = bp_reset,
.ap_wake_bp = NULL,
.bp_wake_ap = bp_wake_ap,
.shutdown = bp_shutdown,
.read_status = NULL,
.write_status = NULL,
.suspend = bp_suspend,
.resume = bp_resume,
.misc_name = NULL,
.private_miscdev = NULL,
};
/****************operate according to bp chip:end************/
//function name should not be changed
static struct bp_operate *bp_get_ops(void)
{
return &bp_c66a_ops;
}
static int __init bp_c66a_init(void)
{
struct bp_operate *ops = bp_get_ops();
int result = 0;
result = bp_register_slave(NULL, NULL, bp_get_ops);
if(result)
{
return result;
}
if(ops->private_miscdev)
{
result = misc_register(ops->private_miscdev);
if (result < 0) {
printk("%s:misc_register err\n",__func__);
return result;
}
}
DBG("%s\n",__func__);
return result;
}
static void __exit bp_c66a_exit(void)
{
//struct bp_operate *ops = bp_get_ops();
bp_unregister_slave(NULL, NULL, bp_get_ops);
}
subsys_initcall(bp_c66a_init);
module_exit(bp_c66a_exit);

234
drivers/misc/bp/chips/m51.c Executable file
View File

@@ -0,0 +1,234 @@
/* drivers/misc/bp/chips/m51.c
*
* Copyright (C) 2012-2015 ROCKCHIP.
* Author: luowei <lw@rock-chips.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/circ_buf.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <mach/iomux.h>
#include <mach/gpio.h>
#include <asm/gpio.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/wakelock.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/earlysuspend.h>
#include <linux/bp-auto.h>
#if 0
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
/****************operate according to bp chip:start************/
static int bp_active(struct bp_private_data *bp, int enable)
{
int result = 0;
if(enable)
{
printk("<-----m51 power on-------->\n");
gpio_set_value(bp->ops->bp_power, GPIO_HIGH);
msleep(100);
gpio_set_value(bp->ops->bp_reset, GPIO_HIGH);
msleep(500);
gpio_set_value(bp->ops->bp_reset, GPIO_LOW);
gpio_set_value(bp->ops->bp_en, GPIO_HIGH);
msleep(1000);
//gpio_set_value(bp->ops->bp_en, GPIO_LOW);
}
else
{
printk("<-----m51 power off-------->\n");
//gpio_set_value(bp->ops->bp_en, GPIO_LOW);
//msleep(1000);
gpio_set_value(bp->ops->bp_reset, GPIO_HIGH);
msleep(200);
gpio_set_value(bp->ops->bp_power, GPIO_LOW);
msleep(500);
}
return result;
}
static void ap_wake_bp_work(struct work_struct *work)
{
return;
}
static int bp_wake_ap(struct bp_private_data *bp)
{
int result = 0;
if(bp->suspend_status)
{
bp->suspend_status = 0;
wake_lock_timeout(&bp->bp_wakelock, 10 * HZ);
}
return result;
}
static int bp_init(struct bp_private_data *bp)
{
int result = 0;
if(bp->pdata->gpio_valid ==0){
}
gpio_direction_output(bp->ops->bp_power, GPIO_LOW);
gpio_direction_output(bp->ops->bp_reset, GPIO_HIGH);
gpio_direction_output(bp->ops->bp_en, GPIO_LOW);
gpio_direction_output(bp->ops->ap_ready, GPIO_LOW);
gpio_direction_output(bp->ops->ap_wakeup_bp, GPIO_LOW);
gpio_direction_input(bp->ops->bp_wakeup_ap);
gpio_pull_updown(bp->ops->bp_wakeup_ap, 1);
//if(bp->ops->active)
//bp->ops->active(bp, 1);
INIT_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);
return result;
}
static int bp_reset(struct bp_private_data *bp)
{
printk("ioctrl m51 reset !!! \n");
gpio_set_value(bp->ops->bp_reset, GPIO_HIGH);
msleep(500);
//gpio_set_value(bp->ops->bp_reset, GPIO_LOW);
gpio_set_value(bp->ops->bp_power, GPIO_LOW);
//if(bp->ops->active)
//bp->ops->active(bp, 0);
//if(bp->ops->active)
// bp->ops->active(bp, 1);
return 0;
}
static int bp_shutdown(struct bp_private_data *bp)
{
int result = 0;
printk("m51 bp_shutdown !!! \n");
if(bp->ops->active)
bp->ops->active(bp, 0);
cancel_delayed_work_sync(&bp->wakeup_work);
return result;
}
static int bp_suspend(struct bp_private_data *bp)
{
int result = 0;
bp->suspend_status = 1;
//gpio_set_value(bp->ops->ap_ready, GPIO_HIGH);
gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_HIGH);
return result;
}
static int bp_resume(struct bp_private_data *bp)
{
bp->suspend_status = 0;
//gpio_set_value(bp->ops->ap_ready, GPIO_LOW);
gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);
return 0;
}
struct bp_operate bp_m51_ops = {
.name = "m51",
.bp_id = BP_ID_M50,
.bp_bus = BP_BUS_TYPE_UART,
.bp_pid = 0,
.bp_vid = 0,
.bp_power = BP_UNKNOW_DATA, // RK2928_PIN3_PC2, // 3g_power
.bp_en = BP_UNKNOW_DATA, // RK2928_PIN3_PC5,//BP_UNKNOW_DATA, // 3g_en
.bp_reset = BP_UNKNOW_DATA, // RK2928_PIN0_PB6,
.ap_ready = BP_UNKNOW_DATA, // RK2928_PIN0_PD6, //
.bp_ready = BP_UNKNOW_DATA, // RK2928_PIN0_PD0,
.ap_wakeup_bp = BP_UNKNOW_DATA, // RK2928_PIN3_PC4,
.bp_wakeup_ap = BP_UNKNOW_DATA, // RK2928_PIN3_PC3, //
.bp_assert = BP_UNKNOW_DATA,
.bp_uart_en = BP_UNKNOW_DATA, //EINT9
.bp_usb_en = BP_UNKNOW_DATA, //W_disable
.trig = IRQF_TRIGGER_FALLING,
.active = bp_active,
.init = bp_init,
.reset = bp_reset,
.ap_wake_bp = NULL,
.bp_wake_ap = bp_wake_ap,
.shutdown = bp_shutdown,
.read_status = NULL,
.write_status = NULL,
.suspend = bp_suspend,
.resume = bp_resume,
.misc_name = NULL,
.private_miscdev = NULL,
};
/****************operate according to bp chip:end************/
//function name should not be changed
static struct bp_operate *bp_get_ops(void)
{
return &bp_m51_ops;
}
static int __init bp_m51_init(void)
{
struct bp_operate *ops = bp_get_ops();
int result = 0;
result = bp_register_slave(NULL, NULL, bp_get_ops);
if(result)
{
return result;
}
if(ops->private_miscdev)
{
result = misc_register(ops->private_miscdev);
if (result < 0) {
printk("%s:misc_register err\n",__func__);
return result;
}
}
DBG("%s\n",__func__);
return result;
}
static void __exit bp_m51_exit(void)
{
//struct bp_operate *ops = bp_get_ops();
bp_unregister_slave(NULL, NULL, bp_get_ops);
}
subsys_initcall(bp_m51_init);
module_exit(bp_m51_exit);

223
drivers/misc/bp/chips/mi700.c Executable file
View File

@@ -0,0 +1,223 @@
/* drivers/misc/bp/chips/mi700.c
*
* Copyright (C) 2012-2015 ROCKCHIP.
* Author: luowei <lw@rock-chips.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/circ_buf.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <mach/iomux.h>
#include <mach/gpio.h>
#include <asm/gpio.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/wakelock.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/earlysuspend.h>
#include <linux/bp-auto.h>
#if 0
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
/****************operate according to bp chip:start************/
static int bp_active(struct bp_private_data *bp, int enable)
{
int result = 0;
if(enable)
{
printk("mi700 power on \n");
gpio_set_value(bp->ops->bp_reset, GPIO_LOW);
msleep(100);
gpio_set_value(bp->ops->bp_reset, GPIO_HIGH);
gpio_set_value(bp->ops->bp_en, GPIO_HIGH);
msleep(1000);
gpio_set_value(bp->ops->bp_en, GPIO_LOW);
msleep(700);
gpio_set_value(bp->ops->bp_en, GPIO_HIGH);
}
else
{
printk("mi700 power off \n");
gpio_set_value(bp->ops->bp_en, GPIO_LOW);
gpio_set_value(bp->ops->bp_en, GPIO_HIGH);
msleep(2500);
gpio_set_value(bp->ops->bp_en, GPIO_LOW);
}
return result;
}
static void ap_wake_bp_work(struct work_struct *work)
{
return;
}
static int bp_wake_ap(struct bp_private_data *bp)
{
int result = 0;
if(bp->suspend_status)
{
bp->suspend_status = 0;
wake_lock_timeout(&bp->bp_wakelock, 10 * HZ);
}
return result;
}
static int bp_init(struct bp_private_data *bp)
{
int result = 0;
//if(bp->ops->active)
// bp->ops->active(bp, 1);
INIT_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);
return result;
}
static int bp_reset(struct bp_private_data *bp)
{
printk("ioctrl mi700 reset !!! \n");
gpio_set_value(bp->ops->bp_reset, GPIO_LOW);
msleep(100);
gpio_set_value(bp->ops->bp_reset, GPIO_HIGH);
msleep(100);
gpio_set_value(bp->ops->bp_en, GPIO_HIGH);
msleep(1000);
gpio_set_value(bp->ops->bp_en, GPIO_LOW);
msleep(700);
gpio_set_value(bp->ops->bp_en, GPIO_HIGH);
return 0;
}
static int bp_shutdown(struct bp_private_data *bp)
{
int result = 0;
if(bp->ops->active)
bp->ops->active(bp, 0);
cancel_delayed_work_sync(&bp->wakeup_work);
return result;
}
static int bp_suspend(struct bp_private_data *bp)
{
int result = 0;
if(!bp->suspend_status)
{
bp->suspend_status = 1;
//gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);
}
return result;
}
static int bp_resume(struct bp_private_data *bp)
{
bp->suspend_status = 0;
//gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_HIGH);
return 0;
}
struct bp_operate bp_mi700_ops = {
.name = "mi700",
.bp_id = BP_ID_MI700,
.bp_bus = BP_BUS_TYPE_USB,
.bp_pid = 0,
.bp_vid = 0,
.bp_power = BP_UNKNOW_DATA, // 3g_power
.bp_en = BP_UNKNOW_DATA, // 3g_en
.bp_reset = BP_UNKNOW_DATA,
.ap_ready = BP_UNKNOW_DATA, //
.bp_ready = BP_UNKNOW_DATA,
.ap_wakeup_bp = BP_UNKNOW_DATA,
.bp_wakeup_ap = BP_UNKNOW_DATA, //
.bp_uart_en = BP_UNKNOW_DATA, //EINT9
.bp_usb_en = BP_UNKNOW_DATA, //W_disable
.trig = IRQF_TRIGGER_FALLING,
.active = bp_active,
.init = bp_init,
.reset = bp_reset,
.ap_wake_bp = NULL,
.bp_wake_ap = bp_wake_ap,
.shutdown = bp_shutdown,
.read_status = NULL,
.write_status = NULL,
.suspend = bp_suspend,
.resume = bp_resume,
.misc_name = NULL,
.private_miscdev = NULL,
};
/****************operate according to bp chip:end************/
//function name should not be changed
static struct bp_operate *bp_get_ops(void)
{
return &bp_mi700_ops;
}
static int __init bp_mi700_init(void)
{
struct bp_operate *ops = bp_get_ops();
int result = 0;
result = bp_register_slave(NULL, NULL, bp_get_ops);
if(result)
{
return result;
}
if(ops->private_miscdev)
{
result = misc_register(ops->private_miscdev);
if (result < 0) {
printk("%s:misc_register err\n",__func__);
return result;
}
}
DBG("%s\n",__func__);
return result;
}
static void __exit bp_mi700_exit(void)
{
//struct bp_operate *ops = bp_get_ops();
bp_unregister_slave(NULL, NULL, bp_get_ops);
}
subsys_initcall(bp_mi700_init);
module_exit(bp_mi700_exit);

View File

@@ -53,6 +53,8 @@ static int bp_active(struct bp_private_data *bp, int enable)
int result = 0;
if(enable)
{
gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);
msleep(1000);
gpio_direction_output(bp->ops->bp_en, GPIO_LOW);
gpio_direction_output(bp->ops->bp_usb_en, GPIO_HIGH);
gpio_direction_output(bp->ops->bp_uart_en, GPIO_LOW);
@@ -61,6 +63,8 @@ static int bp_active(struct bp_private_data *bp, int enable)
}
else
{
gpio_direction_output(bp->ops->bp_power, GPIO_LOW);
msleep(10);
gpio_direction_output(bp->ops->bp_en, GPIO_HIGH);
gpio_direction_output(bp->ops->bp_usb_en, GPIO_LOW);
gpio_direction_output(bp->ops->bp_uart_en, GPIO_HIGH);
@@ -112,11 +116,10 @@ static void ap_wake_bp_work(struct work_struct *work)
static int bp_init(struct bp_private_data *bp)
{
int result = 0;
gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);
msleep(1000);
if(bp->ops->active)
bp->ops->active(bp, 1);
//gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);
//msleep(1000);
//if(bp->ops->active)
// bp->ops->active(bp, 1);
INIT_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);
return result;
}
@@ -148,35 +151,6 @@ static int bp_shutdown(struct bp_private_data *bp)
}
static int read_status(struct bp_private_data *bp)
{
int result = 0;
return result;
}
static int write_status(struct bp_private_data *bp)
{
int result = 0;
if (bp->status == BP_ON)
{
gpio_direction_output(bp->ops->bp_usb_en, GPIO_HIGH);
gpio_direction_output(bp->ops->bp_uart_en,GPIO_LOW);
}
else if(bp->status == BP_OFF)
{
gpio_direction_output(bp->ops->bp_usb_en, GPIO_LOW);
gpio_direction_output(bp->ops->bp_uart_en,GPIO_HIGH);
}
else
{
printk("%s, invalid parameter \n", __FUNCTION__);
}
return result;
}
static int bp_suspend(struct bp_private_data *bp)
@@ -192,19 +166,12 @@ static int bp_suspend(struct bp_private_data *bp)
return result;
}
static int bp_resume(struct bp_private_data *bp)
{
if(bp->suspend_status)
{
bp->suspend_status = 0;
PREPARE_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);
schedule_delayed_work(&bp->wakeup_work, 0);
}
bp->suspend_status = 0;
PREPARE_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);
schedule_delayed_work(&bp->wakeup_work, 0);
return 0;
}
@@ -215,15 +182,15 @@ struct bp_operate bp_mt6229_ops = {
.bp_bus = BP_BUS_TYPE_USB_UART,
.bp_pid = 0,
.bp_vid = 0,
.bp_power = RK30_PIN6_PB2, // 3g_power
.bp_en = RK30_PIN2_PB6, // 3g_en
.bp_reset = BP_UNKNOW_DATA,
.ap_ready = RK30_PIN2_PB7, //
.bp_power = BP_UNKNOW_DATA, // 3g_power
.bp_en = BP_UNKNOW_DATA, // 3g_en
.bp_reset = BP_UNKNOW_DATA,
.ap_ready = BP_UNKNOW_DATA, //
.bp_ready = BP_UNKNOW_DATA,
.ap_wakeup_bp = BP_UNKNOW_DATA,
.bp_wakeup_ap = RK30_PIN6_PA1, //
.bp_uart_en = RK30_PIN2_PC1, //EINT9
.bp_usb_en = RK30_PIN2_PC0, //W_disable
.bp_wakeup_ap = BP_UNKNOW_DATA, //
.bp_uart_en = BP_UNKNOW_DATA, //EINT9
.bp_usb_en = BP_UNKNOW_DATA, //W_disable
.trig = IRQF_TRIGGER_RISING,
.active = bp_active,
@@ -231,11 +198,11 @@ struct bp_operate bp_mt6229_ops = {
.ap_wake_bp = ap_wake_bp,
.bp_wake_ap = bp_wake_ap,
.shutdown = bp_shutdown,
.read_status = read_status,
.write_status = write_status,
.read_status = NULL,
.write_status = NULL,
.suspend = bp_suspend,
.resume = bp_resume,
.misc_name = "mt6229",
.misc_name = NULL,
.private_miscdev = NULL,
};

View File

@@ -0,0 +1,231 @@
/* drivers/misc/bp/chips/mt6250.c
*
* Copyright (C) 2012-2015 ROCKCHIP.
* Author: luowei <lw@rock-chips.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/circ_buf.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <mach/iomux.h>
#include <mach/gpio.h>
#include <asm/gpio.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/wakelock.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/earlysuspend.h>
#include <linux/bp-auto.h>
#if 0
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
/****************operate according to bp chip:start************/
static int bp_active(struct bp_private_data *bp, int enable)
{
int result = 0;
if(enable)
{
printk("<-----mt6250 power on-------->\n");
gpio_set_value(bp->ops->bp_power, GPIO_HIGH);
msleep(100);
gpio_set_value(bp->ops->bp_en,GPIO_HIGH);
mdelay(100);
gpio_set_value(bp->ops->bp_reset, GPIO_LOW);
mdelay(2500);
gpio_set_value(bp->ops->bp_en,GPIO_LOW);
}
else
{
printk("<-----mt6250 power on-------->\n");
gpio_set_value(bp->ops->bp_en, GPIO_LOW);
msleep(2500);
gpio_set_value(bp->ops->bp_en, GPIO_HIGH);
msleep(500);
gpio_set_value(bp->ops->bp_reset, GPIO_HIGH);
gpio_set_value(bp->ops->bp_power, GPIO_LOW);
}
return result;
}
static void ap_wake_bp_work(struct work_struct *work)
{
return;
}
static int bp_wake_ap(struct bp_private_data *bp)
{
int result = 0;
if(bp->suspend_status)
{
bp->suspend_status = 0;
wake_lock_timeout(&bp->bp_wakelock, 10 * HZ);
}
return result;
}
static int bp_init(struct bp_private_data *bp)
{
int result = 0;
if(bp->pdata->gpio_valid ==0){
}
gpio_direction_output(bp->ops->bp_power, GPIO_LOW);
gpio_direction_output(bp->ops->bp_reset, GPIO_HIGH);
gpio_direction_output(bp->ops->bp_en, GPIO_LOW);
gpio_direction_output(bp->ops->ap_ready, GPIO_LOW);
gpio_direction_output(bp->ops->ap_wakeup_bp, GPIO_HIGH);
//gpio_direction_input(bp->ops->bp_ready);
gpio_direction_input(bp->ops->bp_wakeup_ap);
gpio_pull_updown(bp->ops->bp_wakeup_ap, 1);
//if(bp->ops->active)
//bp->ops->active(bp, 1);
INIT_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);
return result;
}
static int bp_reset(struct bp_private_data *bp)
{
printk("ioctrl mt6250 reset !!! \n");
gpio_set_value(bp->ops->bp_reset, GPIO_HIGH);
msleep(2000);
gpio_set_value(bp->ops->bp_reset, GPIO_LOW);
return 0;
}
static int bp_shutdown(struct bp_private_data *bp)
{
int result = 0;
if(bp->ops->active)
bp->ops->active(bp, 0);
cancel_delayed_work_sync(&bp->wakeup_work);
return result;
}
static int bp_suspend(struct bp_private_data *bp)
{
int result = 0;
bp->suspend_status = 1;
gpio_set_value(bp->ops->ap_ready, GPIO_HIGH);
gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);
return result;
}
static int bp_resume(struct bp_private_data *bp)
{
bp->suspend_status = 0;
gpio_set_value(bp->ops->ap_ready, GPIO_LOW);
gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_HIGH);
msleep(100);
gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);
return 0;
}
struct bp_operate bp_mt6250_ops = {
.name = "mt6250",
.bp_id = BP_ID_MT6250,
.bp_bus = BP_BUS_TYPE_UART,
.bp_pid = 0,
.bp_vid = 0,
.bp_power = BP_UNKNOW_DATA, // RK2928_PIN3_PC2, // 3g_power
.bp_en = BP_UNKNOW_DATA, // RK2928_PIN3_PC5,//BP_UNKNOW_DATA, // 3g_en
.bp_reset = BP_UNKNOW_DATA, // RK2928_PIN0_PB6,
.ap_ready = BP_UNKNOW_DATA, // RK2928_PIN0_PD0, //
.bp_ready = BP_UNKNOW_DATA, // RK2928_PIN0_PD6,
.ap_wakeup_bp = BP_UNKNOW_DATA, // RK2928_PIN3_PC4,
.bp_wakeup_ap = BP_UNKNOW_DATA, // RK2928_PIN3_PC3, //
.bp_assert = BP_UNKNOW_DATA,
.bp_uart_en = BP_UNKNOW_DATA, //EINT9
.bp_usb_en = BP_UNKNOW_DATA, //W_disable
.trig = IRQF_TRIGGER_FALLING,
.active = bp_active,
.init = bp_init,
.reset = bp_reset,
.ap_wake_bp = NULL,
.bp_wake_ap = bp_wake_ap,
.shutdown = bp_shutdown,
.read_status = NULL,
.write_status = NULL,
.suspend = bp_suspend,
.resume = bp_resume,
.misc_name = NULL,
.private_miscdev = NULL,
};
/****************operate according to bp chip:end************/
//function name should not be changed
static struct bp_operate *bp_get_ops(void)
{
return &bp_mt6250_ops;
}
static int __init bp_mt6250_init(void)
{
struct bp_operate *ops = bp_get_ops();
int result = 0;
result = bp_register_slave(NULL, NULL, bp_get_ops);
if(result)
{
return result;
}
if(ops->private_miscdev)
{
result = misc_register(ops->private_miscdev);
if (result < 0) {
printk("%s:misc_register err\n",__func__);
return result;
}
}
DBG("%s\n",__func__);
return result;
}
static void __exit bp_mt6250_exit(void)
{
//struct bp_operate *ops = bp_get_ops();
bp_unregister_slave(NULL, NULL, bp_get_ops);
}
subsys_initcall(bp_mt6250_init);
module_exit(bp_mt6250_exit);

View File

@@ -53,18 +53,21 @@ static int bp_active(struct bp_private_data *bp, int enable)
int result = 0;
if(enable)
{
gpio_direction_output(bp->ops->bp_reset, GPIO_HIGH);
// gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);
// msleep(500);
gpio_set_value(bp->ops->bp_reset, GPIO_HIGH);
msleep(100);
gpio_direction_output(bp->ops->bp_reset, GPIO_LOW);
gpio_direction_output(bp->ops->bp_en, GPIO_LOW);
gpio_set_value(bp->ops->bp_reset, GPIO_LOW);
gpio_set_value(bp->ops->bp_en, GPIO_LOW);
msleep(1000);
gpio_direction_output(bp->ops->bp_en, GPIO_HIGH);
gpio_set_value(bp->ops->bp_en, GPIO_HIGH);
msleep(700);
gpio_direction_output(bp->ops->bp_en, GPIO_LOW);
gpio_direction_output(bp->ops->ap_wakeup_bp, GPIO_LOW);
gpio_set_value(bp->ops->bp_en, GPIO_LOW);
gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);
}
else
{
// gpio_direction_output(bp->ops->bp_power, GPIO_LOW);
gpio_set_value(bp->ops->bp_en, GPIO_LOW);
gpio_set_value(bp->ops->bp_en, GPIO_HIGH);
msleep(2500);
@@ -78,7 +81,7 @@ static int ap_wake_bp(struct bp_private_data *bp, int wake)
{
int result = 0;
gpio_direction_output(bp->ops->ap_wakeup_bp, wake);
gpio_set_value(bp->ops->ap_wakeup_bp, wake);
return result;
@@ -93,6 +96,7 @@ static void ap_wake_bp_work(struct work_struct *work)
{
if(bp->ops->ap_wake_bp)
bp->ops->ap_wake_bp(bp, 0);
bp->suspend_status = 0;
}
else
{
@@ -106,19 +110,32 @@ static int bp_init(struct bp_private_data *bp)
{
int result = 0;
gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);
msleep(1000);
if(bp->ops->active)
bp->ops->active(bp, 1);
gpio_set_value(bp->ops->bp_power, GPIO_HIGH);
msleep(500);
//if(bp->ops->active)
// bp->ops->active(bp, 1);
gpio_direction_input(bp->ops->bp_wakeup_ap);
gpio_pull_updown(bp->ops->bp_wakeup_ap, 1);
gpio_direction_output(bp->ops->bp_reset, GPIO_LOW);
gpio_direction_output(bp->ops->bp_en, GPIO_LOW);
gpio_direction_output(bp->ops->ap_wakeup_bp, GPIO_LOW);
INIT_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);
return result;
}
static int bp_reset(struct bp_private_data *bp)
{
gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);
// gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);
// msleep(500);
gpio_set_value(bp->ops->bp_reset, GPIO_HIGH);
msleep(100);
gpio_direction_output(bp->ops->bp_power, GPIO_LOW);
gpio_set_value(bp->ops->bp_reset, GPIO_LOW);
gpio_set_value(bp->ops->bp_en, GPIO_LOW);
msleep(1000);
gpio_set_value(bp->ops->bp_en, GPIO_HIGH);
msleep(700);
gpio_set_value(bp->ops->bp_en, GPIO_LOW);
gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);
return 0;
}
@@ -143,50 +160,29 @@ static int bp_shutdown(struct bp_private_data *bp)
if(bp->ops->active)
bp->ops->active(bp, 0);
gpio_set_value(bp->ops->bp_power, GPIO_LOW);
cancel_delayed_work_sync(&bp->wakeup_work);
return result;
}
static int read_status(struct bp_private_data *bp)
{
int result = 0;
return result;
}
static int write_status(struct bp_private_data *bp)
{
int result = 0;
if (bp->status == BP_ON)
{
gpio_direction_output(bp->ops->bp_usb_en, GPIO_HIGH);
gpio_direction_output(bp->ops->bp_uart_en,GPIO_LOW);
}
else if(bp->status == BP_OFF)
{
gpio_direction_output(bp->ops->bp_usb_en, GPIO_LOW);
gpio_direction_output(bp->ops->bp_uart_en,GPIO_HIGH);
}
else
{
printk("%s, invalid parameter \n", __FUNCTION__);
}
return result;
}
static int bp_suspend(struct bp_private_data *bp)
{
int result = 0;
printk("<-----mu509 bp_suspend-------->\n");
#if defined(CONFIG_ARCH_RK29)
rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_GPIO1C1);
#elif defined(CONFIG_ARCH_RK30)
rk30_mux_api_set(GPIO1A7_UART1RTSN_SPI0TXD_NAME, GPIO1A_GPIO1A7);
#endif
if(!bp->suspend_status)
{
bp->suspend_status = 1;
//printk("<-----mu509 bp_suspend----ap_wakeup_bp, GPIO_HIGH---->\n");
gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_HIGH);
}
return result;
@@ -196,12 +192,17 @@ static int bp_suspend(struct bp_private_data *bp)
static int bp_resume(struct bp_private_data *bp)
{
if(bp->suspend_status)
{
bp->suspend_status = 0;
gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);
}
{
#if defined(CONFIG_ARCH_RK29)
rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_UART0_RTS_N);
#elif defined(CONFIG_ARCH_RK30)
rk30_mux_api_set(GPIO1A7_UART1RTSN_SPI0TXD_NAME, GPIO1A_UART1_RTS_N);
#endif
//bp->suspend_status = 0;
//gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);
schedule_delayed_work(&bp->wakeup_work, 4*HZ);
return 0;
}
@@ -213,13 +214,13 @@ struct bp_operate bp_mu509_ops = {
.bp_bus = BP_BUS_TYPE_USB_UART,
.bp_pid = 0,
.bp_vid = 0,
.bp_power = RK30_PIN6_PB2, // 3g_power
.bp_en = RK30_PIN2_PB6, // 3g_en
.bp_reset = RK30_PIN2_PC1,
.bp_power = BP_UNKNOW_DATA,//RK2928_PIN3_PC2, // 3g_power
.bp_en = BP_UNKNOW_DATA, // 3g_en
.bp_reset = BP_UNKNOW_DATA,//RK2928_PIN1_PA3,
.ap_ready = BP_UNKNOW_DATA, //
.bp_ready = BP_UNKNOW_DATA,
.ap_wakeup_bp = RK30_PIN2_PB7,
.bp_wakeup_ap = RK30_PIN6_PA1, //
.ap_wakeup_bp = BP_UNKNOW_DATA,//RK2928_PIN3_PC4,
.bp_wakeup_ap = BP_UNKNOW_DATA,//RK2928_PIN3_PC3, //
.bp_uart_en = BP_UNKNOW_DATA, //EINT9
.bp_usb_en = BP_UNKNOW_DATA, //W_disable
.trig = IRQF_TRIGGER_FALLING,
@@ -230,11 +231,11 @@ struct bp_operate bp_mu509_ops = {
.ap_wake_bp = ap_wake_bp,
.bp_wake_ap = bp_wake_ap,
.shutdown = bp_shutdown,
.read_status = read_status,
.write_status = write_status,
.read_status = NULL,
.write_status = NULL,
.suspend = bp_suspend,
.resume = bp_resume,
.misc_name = "mu509",
.misc_name = NULL,
.private_miscdev = NULL,
};

242
drivers/misc/bp/chips/mw100.c Executable file
View File

@@ -0,0 +1,242 @@
/* drivers/misc/bp/chips/mw100.c
*
* Copyright (C) 2012-2015 ROCKCHIP.
* Author: luowei <lw@rock-chips.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/circ_buf.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <mach/iomux.h>
#include <mach/gpio.h>
#include <asm/gpio.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/wakelock.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/earlysuspend.h>
#include <linux/bp-auto.h>
#if 0
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
/****************operate according to bp chip:start************/
static int bp_active(struct bp_private_data *bp, int enable)
{
int result = 0;
if(enable)
{
printk("mw100 power on \n");
/* gpio_set_value(bp->ops->bp_power, GPIO_HIGH);
msleep(500);
gpio_set_value(bp->ops->bp_en, GPIO_LOW);
gpio_set_value(bp->ops->bp_reset, GPIO_LOW);
mdelay(10);
gpio_set_value(bp->ops->bp_en, GPIO_HIGH);
gpio_set_value(bp->ops->bp_reset, GPIO_HIGH);
mdelay(500);
//gpio_set_value(bp->ops->bp_en, GPIO_LOW);
*/
gpio_set_value(bp->ops->bp_power, GPIO_HIGH);
msleep(100);
gpio_set_value(bp->ops->bp_reset, GPIO_HIGH);
msleep(500);
gpio_set_value(bp->ops->bp_reset, GPIO_LOW);
gpio_set_value(bp->ops->bp_en, GPIO_HIGH);
msleep(1000);
//gpio_set_value(bp->ops->bp_en, GPIO_LOW);
}
else
{
printk("mw100 power off \n");
gpio_set_value(bp->ops->bp_power, GPIO_LOW);
gpio_set_value(bp->ops->bp_en, GPIO_LOW);
gpio_set_value(bp->ops->bp_reset, GPIO_LOW);
msleep(500);
}
return result;
}
static void ap_wake_bp_work(struct work_struct *work)
{
return;
}
static int bp_wake_ap(struct bp_private_data *bp)
{
int result = 0;
if(bp->suspend_status)
{
bp->suspend_status = 0;
wake_lock_timeout(&bp->bp_wakelock, 10 * HZ);
}
return result;
}
static int bp_init(struct bp_private_data *bp)
{
int result = 0;
//if(bp->ops->active)
// bp->ops->active(bp, 1);
//if(!bp->pdata->gpio_valid){
//rk30_mux_api_set(GPIO1A3_I2S_LRCKTX_NAME,GPIO1A_GPIO1A3);
//}
gpio_direction_output(bp->ops->bp_power,GPIO_LOW);
gpio_direction_output(bp->ops->bp_en,GPIO_LOW);
gpio_direction_output(bp->ops->bp_reset,GPIO_LOW);
gpio_direction_output(bp->ops->ap_wakeup_bp,GPIO_HIGH);
gpio_direction_input(bp->ops->bp_wakeup_ap);
INIT_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);
return result;
}
static int bp_reset(struct bp_private_data *bp)
{
printk("ioctrl mw100 reset !!! \n");
gpio_set_value(bp->ops->bp_en, GPIO_LOW);
gpio_set_value(bp->ops->bp_power, GPIO_HIGH);
//gpio_set_value(bp->ops->bp_reset, GPIO_HIGH);
//mdelay(10);
gpio_set_value(bp->ops->bp_reset, GPIO_LOW);
mdelay(100);
gpio_set_value(bp->ops->bp_reset, GPIO_HIGH);
return 0;
}
static int bp_shutdown(struct bp_private_data *bp)
{
int result = 0;
if(bp->ops->active)
bp->ops->active(bp, 0);
cancel_delayed_work_sync(&bp->wakeup_work);
return result;
}
static int bp_suspend(struct bp_private_data *bp)
{
int result = 0;
if(!bp->suspend_status)
{
bp->suspend_status = 1;
gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);
}
return result;
}
static int bp_resume(struct bp_private_data *bp)
{
bp->suspend_status = 0;
gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_HIGH);
return 0;
}
struct bp_operate bp_mw100_ops = {
.name = "mw100",
.bp_id = BP_ID_MW100,
.bp_bus = BP_BUS_TYPE_USB,
.bp_pid = 0,
.bp_vid = 0,
.bp_power = BP_UNKNOW_DATA,//RK2928_PIN3_PC2, // 3g_power
.bp_en = BP_UNKNOW_DATA,//RK2928_PIN3_PC5, // 3g_en
.bp_reset = BP_UNKNOW_DATA,//RK2928_PIN1_PA3,
.ap_ready = BP_UNKNOW_DATA, //
.bp_ready = BP_UNKNOW_DATA,
.ap_wakeup_bp = BP_UNKNOW_DATA,//RK2928_PIN3_PC4,
.bp_wakeup_ap = BP_UNKNOW_DATA,//RK2928_PIN3_PC3, //
.bp_uart_en = BP_UNKNOW_DATA, //EINT9
.bp_usb_en = BP_UNKNOW_DATA, //W_disable
.trig = IRQF_TRIGGER_FALLING,
.active = bp_active,
.init = bp_init,
.reset = bp_reset,
.ap_wake_bp = NULL,
.bp_wake_ap = bp_wake_ap,
.shutdown = bp_shutdown,
.read_status = NULL,
.write_status = NULL,
.suspend = bp_suspend,
.resume = bp_resume,
.misc_name = NULL,
.private_miscdev = NULL,
};
/****************operate according to bp chip:end************/
//function name should not be changed
static struct bp_operate *bp_get_ops(void)
{
return &bp_mw100_ops;
}
static int __init bp_mw100_init(void)
{
struct bp_operate *ops = bp_get_ops();
int result = 0;
result = bp_register_slave(NULL, NULL, bp_get_ops);
if(result)
{
return result;
}
if(ops->private_miscdev)
{
result = misc_register(ops->private_miscdev);
if (result < 0) {
printk("%s:misc_register err\n",__func__);
return result;
}
}
DBG("%s\n",__func__);
return result;
}
static void __exit bp_mw100_exit(void)
{
//struct bp_operate *ops = bp_get_ops();
bp_unregister_slave(NULL, NULL, bp_get_ops);
}
subsys_initcall(bp_mw100_init);
module_exit(bp_mw100_exit);

207
drivers/misc/bp/chips/sc6610.c Executable file
View File

@@ -0,0 +1,207 @@
/* drivers/misc/bp/chips/sc6610.c
*
* Copyright (C) 2012-2015 ROCKCHIP.
* Author: luowei <lw@rock-chips.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/circ_buf.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <mach/iomux.h>
#include <mach/gpio.h>
#include <asm/gpio.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/wakelock.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/earlysuspend.h>
#include <linux/bp-auto.h>
#if 0
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
/****************operate according to bp chip:start************/
static int bp_active(struct bp_private_data *bp, int enable)
{
int result = 0;
if(enable)
{
printk("<-----sc6610 power on-------->\n");
gpio_set_value(bp->ops->bp_power, GPIO_HIGH);
}
else
{
printk("<-----sc6610 power off-------->\n");
gpio_set_value(bp->ops->bp_power, GPIO_LOW);
msleep(500);
}
return result;
}
static void ap_wake_bp_work(struct work_struct *work)
{
return;
}
static int bp_wake_ap(struct bp_private_data *bp)
{
int result = 0;
if(bp->suspend_status)
{
printk("<-----sc6610 bp_wake_ap-------->\n");
bp->suspend_status = 0;
wake_lock_timeout(&bp->bp_wakelock, 10 * HZ);
}
return result;
}
static int bp_init(struct bp_private_data *bp)
{
int result = 0;
gpio_direction_input(bp->ops->bp_wakeup_ap);
gpio_direction_output(bp->ops->bp_power,GPIO_LOW);
gpio_direction_output(bp->ops->ap_wakeup_bp,GPIO_HIGH);
INIT_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);
return result;
}
static int bp_reset(struct bp_private_data *bp)
{
printk("ioctrl sc6610 reset !!! \n");
gpio_set_value(bp->ops->bp_power, GPIO_LOW);
msleep(2000);
gpio_set_value(bp->ops->bp_power, GPIO_HIGH);
return 0;
}
static int bp_shutdown(struct bp_private_data *bp)
{
int result = 0;
if(bp->ops->active)
bp->ops->active(bp, 0);
cancel_delayed_work_sync(&bp->wakeup_work);
return result;
}
static int bp_suspend(struct bp_private_data *bp)
{
int result = 0;
bp->suspend_status = 1;
gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);
return result;
}
static int bp_resume(struct bp_private_data *bp)
{
printk("<-----sc6610 bp_resume-------->\n");
bp->suspend_status = 0;
gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_HIGH);
return 0;
}
struct bp_operate bp_sc6610_ops = {
.name = "sc6610",
.bp_id = BP_ID_SC6610,
.bp_bus = BP_BUS_TYPE_UART,
.bp_pid = 0,
.bp_vid = 0,
.bp_power = BP_UNKNOW_DATA, // RK2928_PIN3_PC2, // 3g_power
.bp_en = BP_UNKNOW_DATA, // 3g_en
.bp_reset = BP_UNKNOW_DATA,
.ap_ready = BP_UNKNOW_DATA, //
.bp_ready = BP_UNKNOW_DATA,
.ap_wakeup_bp = BP_UNKNOW_DATA, // RK2928_PIN3_PC4,
.bp_wakeup_ap = BP_UNKNOW_DATA, // RK2928_PIN3_PC3, //
.bp_uart_en = BP_UNKNOW_DATA, //EINT9
.bp_usb_en = BP_UNKNOW_DATA, //W_disable
.bp_assert = BP_UNKNOW_DATA, // RK2928_PIN3_PC5,
.trig = IRQF_TRIGGER_RISING,
.active = bp_active,
.init = bp_init,
.reset = bp_reset,
.ap_wake_bp = NULL,
.bp_wake_ap = bp_wake_ap,
.shutdown = bp_shutdown,
.read_status = NULL,
.write_status = NULL,
.suspend = bp_suspend,
.resume = bp_resume,
.misc_name = NULL,
.private_miscdev = NULL,
};
/****************operate according to bp chip:end************/
//function name should not be changed
static struct bp_operate *bp_get_ops(void)
{
return &bp_sc6610_ops;
}
static int __init bp_sc6610_init(void)
{
struct bp_operate *ops = bp_get_ops();
int result = 0;
result = bp_register_slave(NULL, NULL, bp_get_ops);
if(result)
{
return result;
}
if(ops->private_miscdev)
{
result = misc_register(ops->private_miscdev);
if (result < 0) {
printk("%s:misc_register err\n",__func__);
return result;
}
}
DBG("%s\n",__func__);
return result;
}
static void __exit bp_sc6610_exit(void)
{
//struct bp_operate *ops = bp_get_ops();
bp_unregister_slave(NULL, NULL, bp_get_ops);
}
subsys_initcall(bp_sc6610_init);
module_exit(bp_sc6610_exit);

View File

@@ -365,4 +365,12 @@ config TWL60xx_VBAT_LOW_DETECTION
tristate "Support for twl60xx low battery detection."
default n
config CHARGER_SMB347
tristate "Summit Microelectronics SMB347 Battery Charger"
depends on I2C
select REGMAP_I2C
help
Say Y to include support for Summit Microelectronics SMB347
Battery Charger.
endif # POWER_SUPPLY

View File

@@ -41,9 +41,11 @@ obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o
obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o
obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o
obj-$(CONFIG_TWL6030_BCI_BATTERY) += twl6030_bci_battery.o
obj-$(CONFIG_BATTERY_RK29_ADC) += rk29_adc_battery.o
obj-$(CONFIG_BATTERY_RK30_ADC) += rk30_adc_battery.o
obj-$(CONFIG_PLAT_RK) += rk29_charger_display.o
obj-$(CONFIG_BATTERY_RK30_ADC_FAC) += rk30_factory_adc_battery.o
obj-$(CONFIG_CW2015_BATTERY) += cw2015_battery.o

View File

@@ -0,0 +1,515 @@
/*
* smb347 battery driver
*
* This package is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#include <linux/module.h>
#include <linux/param.h>
#include <linux/jiffies.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/idr.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <asm/unaligned.h>
#include <mach/gpio.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <mach/board.h>
#include <mach/iomux.h>
#include <linux/power/smb347-charger.h>
#include <linux/interrupt.h>
#include "../usb/dwc_otg/dwc_otg_driver.h"
#if 1
#define xhc_printk(format, ...) printk(format, ## __VA_ARGS__)
#else
#define xhc_printk(format, ...)
#endif
#define SMB347_STATUS_D 0x3d
#define SMB347_SPEED (300 * 1000)
#define MAX_REG_INDEX 0x3f
struct workqueue_struct *wq;
struct smb347_device{
struct i2c_client *client;
struct delayed_work work;
struct smb347_info *info;
struct work_struct full_power_work_struct;
int usb_host_in;
};
/* Input current limit in mA */
static const unsigned int icl_tbl[] = {
300,
500,
700,
900,
1200,
1500,
1800,
2000,
2200,
2500,
};
extern dwc_otg_device_t* g_otgdev;
struct smb347_device * g_smb347_dev;
static void smb347_init(struct i2c_client *client);
static int smb347_read(struct i2c_client *client, const char reg, char *buf, int len)
{
int ret;
ret = i2c_master_reg8_recv(client, reg, buf, len, SMB347_SPEED);
return ret;
}
static int smb347_write(struct i2c_client *client,const char reg, char *buf, int len)
{
int ret;
ret = i2c_master_reg8_send(client, reg, buf, len, SMB347_SPEED);
return ret;
}
static int dump_smb347_reg(struct smb347_device *dev)
{
int ret = 0;
char buf = 0;
int reg = 0;
if(!dev)
{
xhc_printk("dev is null");
return -1;
}
for(reg = 0; reg <= MAX_REG_INDEX; reg++)
{
ret = i2c_master_reg8_recv(dev->client, reg, &buf, 1, SMB347_SPEED);
if(ret < 0)
{
printk("read smb137 reg error:%d\n",ret);
}
else
{
printk("reg 0x%x:0x%x\n",reg,buf);
}
}
return 0;
}
static ssize_t smb_debug_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t _count)
{
int temp;
u8 reg;
u8 val;
struct smb347_device *smb347_dev = dev_get_drvdata(dev);
if (sscanf(buf, "%x", &temp) != 1)
return -EINVAL;
val = temp & 0x00ff;
reg = temp >> 8;
smb347_write(smb347_dev->client, reg, &val,1);
return _count;
}
static ssize_t smb_debug_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct smb347_device *smb347_dev = dev_get_drvdata(dev);
dump_smb347_reg(smb347_dev);
return 0;
}
static struct device_attribute smb_debug =
__ATTR(smb_debug, S_IRUGO | S_IWUSR, smb_debug_show, smb_debug_store);
int smb347_is_chg_ok(void)
{
u8 reg = 0;
int ret = 0;
smb347_read(g_smb347_dev->client, 0x37, &reg, 1);
ret = (reg & 0x03);
return ret;
}
EXPORT_SYMBOL(smb347_is_chg_ok);
int smb347_is_charging(void)
{
int status = 0;//POWER_SUPPLY_STATUS_UNKNOWN;
u8 data = 0;
smb347_read(g_smb347_dev->client, SMB347_STATUS_D, &data, 1);
if (data & 0x06)
status = 1;
return status;
}
EXPORT_SYMBOL(smb347_is_charging);
void smb347_set_something(void)
{
u8 reg;
smb347_init(g_smb347_dev->client);
return;
}
EXPORT_SYMBOL(smb347_set_something);
void smb347_set_charging(void)
{
u8 val;
val = 0x26;
smb347_write(g_smb347_dev->client, 0x03, &val, 1);
smb347_read(g_smb347_dev->client, 0x04, &val, 1);
val &= 0x7f;
smb347_write(g_smb347_dev->client, 0x04, &val, 1);
return;
}
EXPORT_SYMBOL(smb347_set_charging);
void smb347_set_discharging(void)
{
u8 val;
val = 0x20;
smb347_write(g_smb347_dev->client, 0x03, &val, 1);
smb347_read(g_smb347_dev->client, 0x04, &val, 1);
val |= 0x80;
smb347_write(g_smb347_dev->client, 0x04, &val, 1);
return;
}
EXPORT_SYMBOL(smb347_set_discharging);
/* Convert current to register value using lookup table */
static int current_to_hw(const unsigned int *tbl, size_t size, unsigned int val)
{
size_t i;
for (i = 0; i < size; i++) {
if (val < tbl[i]) {
break;
}
}
return i > 0 ? i - 1 : -EINVAL;
}
static int smb347_set_current_limits(struct smb347_device *smb_dev)
{
char ret;
if (smb_dev->info->max_current) {
xhc_printk("xhc_test_smb_dev->info->max_current = %d\n", smb_dev->info->max_current);
ret = current_to_hw (icl_tbl, ARRAY_SIZE(icl_tbl),
smb_dev->info->max_current);
if (ret < 0) {
return ret;
}
ret = (ret << 4) + ret;
ret = 0x77; //Hardcode 2000mA 2012-11-06
xhc_printk("ret = %x\n", ret);
ret = smb347_write(smb_dev->client, 0x01, &ret, 1);
xhc_printk("ret = %x\n", ret);
if (ret < 0) {
return ret;
}
}
return 0;
}
static void suspend_smb347(struct smb347_device *smb347_dev)
{
u8 reg;
reg = 0x80;
smb347_write(smb347_dev->client,0x30,&reg,1);
smb347_read(smb347_dev->client, 0x02, &reg, 1);
reg = (reg&0x7f);
smb347_write(smb347_dev->client,0x02,&reg,1);
xhc_printk("%s\n", __func__);
}
static void active_smb347(struct smb347_device *smb347_dev)
{
u8 reg;
reg = 0x80;
smb347_write(smb347_dev->client,0x30,&reg,1);
smb347_read(smb347_dev->client, 0x02, &reg, 1);
reg = (reg | 0x80);
smb347_write(smb347_dev->client,0x02,&reg,1);
xhc_printk("%s\n", __func__);
}
static int smb347_set_otg_control(struct smb347_device *smb_dev)
{
char ret;
char reg;
if (smb_dev->info->otg_power_form_smb == 1) {
ret = smb347_read(smb_dev->client, 0x09, &reg, 1);
if (ret < 0) {
xhc_printk("error,ret = %x\n", ret);
return ret;
}
reg &= 0xef;
reg |= 0x40;
reg |= 0x20;
ret = smb347_write(smb_dev->client,0x09,&reg,1);
if (ret < 0) {
xhc_printk("error,ret = %x\n", ret);
return ret;
}
reg = 0x76;
smb347_write(smb_dev->client,0x0a,&reg,1);
if (ret < 0) {
xhc_printk("error,ret = %x\n", ret);
return ret;
}
}
return 0;
}
static void smb347_init(struct i2c_client *client)
{
u8 reg;
reg = 0x80;
smb347_write(client, 0x30, &reg, 1);
reg = 0xfd;
smb347_write(client, 0x00, &reg, 1);
reg = 0x77;
smb347_write(client, 0x01, &reg, 1);
reg = 0x26;
smb347_write(client, 0x03, &reg, 1);
smb347_read(client, 0x05, &reg, 1);
reg |= 0x80;
smb347_write(client, 0x05, &reg, 1);
/* close interrupt */
smb347_read(client, 0x38, &reg, 1);
smb347_read(client, 0x3a, &reg, 1);
reg = 0x0;
smb347_write(client, 0x0c, &reg, 1);
smb347_write(client, 0x0d, &reg, 1);
/* set dc charge when bosh inser dc and usb */
smb347_read(client, 0x02, &reg, 1);
reg = reg & 0xfb;
smb347_write(client, 0x02, &reg, 1);
smb347_set_otg_control(g_smb347_dev);
smb347_set_current_limits(g_smb347_dev);
dump_smb347_reg(g_smb347_dev);
}
static void smb347_set_current_work(struct work_struct *work)
{
struct smb347_device *smb347_dev = container_of(to_delayed_work(work), struct smb347_device, work);
u8 reg;
if (g_otgdev->core_if->op_state == A_HOST && smb347_dev->usb_host_in == 0) {
xhc_printk("otg_dev->core_if->op_state = %d\n", g_otgdev->core_if->op_state);
if (g_smb347_dev->info->otg_power_form_smb == 1) {
reg = 0x7e;
smb347_write(smb347_dev->client,0x0a,&reg,1);
} else {
suspend_smb347(smb347_dev);
}
smb347_dev->usb_host_in = 1;
} else if (g_otgdev->core_if->op_state != A_HOST && smb347_dev->usb_host_in == 1) {
xhc_printk("otg_dev->core_if->op_state = %d\n", g_otgdev->core_if->op_state);
if (g_smb347_dev->info->otg_power_form_smb == 1) {
reg = 0x76;
smb347_write(smb347_dev->client,0x0a,&reg,1);
} else {
active_smb347(smb347_dev);
}
smb347_dev->usb_host_in = 0;
}
schedule_delayed_work(&smb347_dev->work, 100);
}
static int smb347_battery_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
struct smb347_device *smb347_dev;
struct smb347_info *info = client->dev.platform_data;;
xhc_printk("__xhc__%s, line = %d\n", __func__, __LINE__);
smb347_dev = kzalloc(sizeof(struct smb347_device), GFP_KERNEL);
smb347_dev->usb_host_in = 0;
if (!smb347_dev) {
dev_err(&client->dev, "failed to allocate device info data\n");
ret = -ENOMEM;
return ret;
}
xhc_printk("__xhc__%s, line = %d\n", __func__, __LINE__);
i2c_set_clientdata(client, smb347_dev);
dev_set_drvdata(&client->dev,smb347_dev);
smb347_dev->client = client;
smb347_dev->info = info;
g_smb347_dev = smb347_dev;
wq = create_singlethread_workqueue("smb347_det");
if(info->chg_susp_pin) {
rk30_mux_api_set(GPIO4D1_SMCDATA9_TRACEDATA9_NAME, 0);
ret = gpio_request(info->chg_susp_pin, "chg susp pin");
if (ret != 0) {
gpio_free(info->chg_susp_pin);
xhc_printk("smb347 gpio_request chg_susp_pin error\n");
return -EIO;
}
gpio_direction_output(info->chg_susp_pin, 0);
gpio_set_value(info->chg_susp_pin, GPIO_HIGH);
}
//msleep(200);
if(info->chg_ctl_pin) {
ret = gpio_request(info->chg_ctl_pin, "chg ctl pin");
if (ret != 0) {
gpio_free(info->chg_ctl_pin);
xhc_printk("smb347 gpio_request chg_ctl_pin error\n");
return -EIO;
}
xhc_printk("__xhc__%s, line = %d\n", __func__, __LINE__);
gpio_direction_output(info->chg_ctl_pin, 0);
// gpio_set_value(info->chg_ctl_pin, GPIO_HIGH);
}
if(info->chg_en_pin)
{
rk30_mux_api_set(GPIO4D5_SMCDATA13_TRACEDATA13_NAME, 0);
ret = gpio_request(info->chg_en_pin, "chg en pin");
if (ret != 0) {
gpio_free(info->chg_en_pin);
xhc_printk("smb347 gpio_request chg_en_pin error\n");
return -EIO;
}
gpio_direction_output(info->chg_en_pin, 0);
gpio_set_value(info->chg_en_pin, GPIO_LOW);
}
mdelay(100);
smb347_init(client);
INIT_DELAYED_WORK(&smb347_dev->work,smb347_set_current_work);
schedule_delayed_work(&smb347_dev->work, msecs_to_jiffies(3*1000));
ret = device_create_file(&client->dev,&smb_debug);
if(ret) {
dev_err(&client->dev, "failed to create sysfs file\n");
return ret;
}
return 0;
}
static int smb347_battery_remove(struct i2c_client *client)
{
return 0;
}
static int smb347_battery_suspend(struct i2c_client *client, pm_message_t mesg)
{
xhc_printk("__xhc__%s,", __func__);
return 0;
}
static int smb347_battery_resume(struct i2c_client *client)
{
xhc_printk("__xhc__%s,", __func__);
return 0;
}
static void smb347_battery_shutdown(struct i2c_client *client)
{
u8 reg = 0x0e;
smb347_write(client,0x09,&reg,1);
xhc_printk("%s,----xhc----\n", __func__);
}
static const struct i2c_device_id smb347_id[] = {
{ "smb347", 0 },
{}
};
static struct i2c_driver smb347_battery_driver = {
.probe = smb347_battery_probe,
.remove = smb347_battery_remove,
.suspend = smb347_battery_suspend,
.resume = smb347_battery_resume,
.shutdown = smb347_battery_shutdown,
.id_table = smb347_id,
.driver = {
.name = "smb347",
},
};
static int __init smb347_battery_init(void)
{
int ret;
ret = i2c_add_driver(&smb347_battery_driver);
if (ret)
xhc_printk(KERN_ERR "Unable to register smb347 driver\n");
return ret;
}
static void __exit smb347_battery_exit(void)
{
if (g_smb347_dev->info->otg_power_form_smb != 1) {
active_smb347(g_smb347_dev);
}
i2c_del_driver(&smb347_battery_driver);
}
//subsys_initcall_sync(smb347_battery_init);
subsys_initcall(smb347_battery_init);
module_exit(smb347_battery_exit);
/*
delay 500ms to fix the problam
that sometime limit 500ma when startup when insert the hc charger
*/
static int __init delay_for_smb347(void)
{
xhc_printk("function: %s\n", __func__);
mdelay(500);
return 0;
}
core_initcall(delay_for_smb347);
MODULE_AUTHOR("xhc@rock-chips.com");
MODULE_DESCRIPTION("smb347 battery monitor driver");
MODULE_LICENSE("GPL");

View File

@@ -42,7 +42,9 @@
*/
#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
#define DRIVER_DESC "USB Serial Driver core"
#ifdef CONFIG_BP_AUTO
extern int get_current_bp_id();
#endif
/* Driver structure we register with the USB core */
static struct usb_driver usb_serial_driver = {
.name = "usbserial",
@@ -53,23 +55,12 @@ static struct usb_driver usb_serial_driver = {
.no_dynamic_id = 1,
.supports_autosuspend = 1,
};
#if defined(CONFIG_MU509) || defined(CONFIG_BP_AUTO_MU509)
static int MU509_USB = 0;
#define MU509_USB_PORT (SERIAL_TTY_MINORS - 10)
#endif
#if defined(CONFIG_MW100) || defined(CONFIG_BP_AUTO_MW100)
static int MW100_USB = 0;
#define MW100_USB_PORT (SERIAL_TTY_MINORS - 10)
#endif
#if defined(CONFIG_MT6229) || defined(CONFIG_BP_AUTO_MT6229)
static int MT6229_USB = 0;
#define MT6229_USB_PORT (SERIAL_TTY_MINORS - 10)
#endif
#if defined(CONFIG_SEW868) || defined(CONFIG_BP_AUTO_SEW868)
static int SEW868_USB = 0;
#define SEW868_USB_PORT (SERIAL_TTY_MINORS - 10)
#ifdef CONFIG_BP_AUTO
static int BP_USB = 0;
#define BP_USB_PORT (SERIAL_TTY_MINORS - 10)
#endif
/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
the MODULE_DEVICE_TABLE declarations in each serial driver
cause the "hotplug" program to pull in whatever module is necessary
@@ -119,22 +110,11 @@ static struct usb_serial *get_free_serial(struct usb_serial *serial,
*minor = 0;
mutex_lock(&table_lock);
#if defined(CONFIG_MU509) || defined(CONFIG_BP_AUTO_MU509)
if (MU509_USB)
a= MU509_USB_PORT;
#endif
#if defined(CONFIG_MW100) || defined(CONFIG_BP_AUTO_MW100)
if (MW100_USB)
a= MW100_USB_PORT;
#endif
#if defined(CONFIG_MT6229) || defined(CONFIG_BP_AUTO_MT6229)
if (MT6229_USB)
a= MT6229_USB_PORT;
#endif
#if defined(CONFIG_SEW868) || defined(CONFIG_BP_AUTO_SEW868)
if (SEW868_USB)
a= SEW868_USB_PORT;
#ifdef CONFIG_BP_AUTO
if (BP_USB)
a= BP_USB_PORT;
#endif
for (i = a; i < SERIAL_TTY_MINORS; ++i) {
if (serial_table[i])
continue;
@@ -1093,29 +1073,19 @@ int usb_serial_probe(struct usb_interface *interface,
} else {
serial->attached = 1;
}
#if defined(CONFIG_MU509) || defined(CONFIG_BP_AUTO_MU509)
if ((le16_to_cpu(dev->descriptor.idVendor) == 0x12D1 ) && (le16_to_cpu(dev->descriptor.idProduct) == 0x1001))
MU509_USB =1;
else
MU509_USB = 0;
#endif
#if defined(CONFIG_MW100) || defined(CONFIG_BP_AUTO_MW100)
if ((le16_to_cpu(dev->descriptor.idVendor) == 0x19f5) && (le16_to_cpu(dev->descriptor.idProduct) == 0x9013))
MW100_USB =1;
else
MW100_USB = 0;
#endif
#if defined(CONFIG_MT6229) || defined(CONFIG_BP_AUTO_MT6229)
if ((le16_to_cpu(dev->descriptor.idVendor) == 0x0E8D) && (le16_to_cpu(dev->descriptor.idProduct) == 0x00A2))
MT6229_USB =1;
else
MT6229_USB = 0;
#endif
#if defined(CONFIG_SEW868) || defined(CONFIG_BP_AUTO_SEW868)
if ((le16_to_cpu(dev->descriptor.idVendor) == 0x19d2) && (le16_to_cpu(dev->descriptor.idProduct) == 0xffeb))
SEW868_USB =1;
else
SEW868_USB = 0;
#ifdef CONFIG_BP_AUTO
int bp_id = get_current_bp_id();
if (((le16_to_cpu(dev->descriptor.idVendor) == 0x12D1 ) && (le16_to_cpu(dev->descriptor.idProduct) == 0x1001) && (bp_id == 2))
|| ((le16_to_cpu(dev->descriptor.idVendor) == 0x19f5) && (le16_to_cpu(dev->descriptor.idProduct) == 0x9013) && (bp_id == 4))
|| ((le16_to_cpu(dev->descriptor.idVendor) == 0x0E8D) && (le16_to_cpu(dev->descriptor.idProduct) == 0x00A2) && (bp_id == 1))
){
BP_USB =1;
}
else{
BP_USB = 0;
}
#endif
/* Avoid race with tty_open and serial_install by setting the

View File

@@ -85,7 +85,16 @@ void set_lcd_info(struct rk29fb_screen *screen, struct rk29lcd_info *lcd_info )
screen->standby = standby;
}
size_t get_fb_size(void)
{
size_t size = 0;
#if defined(CONFIG_THREE_FB_BUFFER)
size = ((H_VD)*(V_VD)<<2)* 3; //three buffer
#else
size = ((H_VD)*(V_VD)<<2)<<1; //two buffer
#endif
return ALIGN(size,SZ_1M);
}
static int standby(u8 enable)
{
printk(KERN_INFO "byd1024x600 lcd standby, enable=%d\n", enable);

View File

@@ -4,33 +4,38 @@
#include <linux/wakelock.h>
struct bp_private_data;
#define BP_DEV_NAME "voice_modem"
#define BP_UNKNOW_DATA -1
#define BP_OFF 0
#define BP_ON 1
#define BP_SUSPEND 2
#define BP_WAKE 3
#define BP_IOCTL_BASE 'm'
#define BP_IOCTL_BASE 0x1a
#define BP_IOCTL_RESET _IOW(BP_IOCTL_BASE, 0x00, int)
#define BP_IOCTL_POWON _IOW(BP_IOCTL_BASE, 0x01, int)
#define BP_IOCTL_RESET _IOW(BP_IOCTL_BASE, 0x01, int)
#define BP_IOCTL_POWOFF _IOW(BP_IOCTL_BASE, 0x02, int)
#define BP_IOCTL_WRITE_STATUS _IOW(BP_IOCTL_BASE, 0x03, int)
#define BP_IOCTL_GET_STATUS _IOR(BP_IOCTL_BASE, 0x04, int)
#define BP_IOCTL_SET_PVID _IOW(BP_IOCTL_BASE, 0x05, int)
#define BP_IOCTL_GET_BPID _IOR(BP_IOCTL_BASE, 0x06, int)
#define BP_IOCTL_POWON _IOW(BP_IOCTL_BASE, 0x03, int)
#define BP_IOCTL_WRITE_STATUS _IOW(BP_IOCTL_BASE, 0x04, int)
#define BP_IOCTL_GET_STATUS _IOR(BP_IOCTL_BASE, 0x05, int)
#define BP_IOCTL_SET_PVID _IOW(BP_IOCTL_BASE, 0x06, int)
#define BP_IOCTL_GET_BPID _IOR(BP_IOCTL_BASE, 0x07, int)
#define BP_IOCTL_GET_IMEI _IOR(BP_IOCTL_BASE, 0x08, int)
enum bp_id{
BP_ID_INVALID = 0,
BP_ID_INVALID = 0,//no bp
BP_ID_MT6229,
BP_ID_MU509,
BP_ID_MI700,
BP_ID_MW100,
BP_ID_TD8801,
BP_ID_NUM,
BP_ID_MT6229, //USI MT6229 WCDMA
BP_ID_MU509, //huawei MU509 WCDMA
BP_ID_MI700, //thinkwill MI700 WCDMA
BP_ID_MW100, //thinkwill MW100 WCDMA
BP_ID_TD8801, //spreadtrum SC8803 TD-SCDMA
BP_ID_SC6610, //spreadtrum SC6610 GSM
BP_ID_M50, //spreadtrum RDA GSM
BP_ID_MT6250, //ZINN M50 EDGE
BP_ID_C66A, //zhongben
BP_ID_NUM,
};
@@ -54,14 +59,15 @@ struct bp_platform_data {
int bp_id;
int (*init_platform_hw)(void);
int (*exit_platform_hw)(void);
int (*get_bp_id)(void);
int bp_power;
int bp_en;
int bp_reset;
int ap_ready;
int bp_ready;
int ap_wakeup_bp;
int bp_wakeup_ap;
int bp_wakeup_ap;
int bp_assert;
int bp_usb_en;
int bp_uart_en;
@@ -70,23 +76,25 @@ struct bp_platform_data {
struct bp_operate {
char *name;
int bp_id;
int bp_bus;
int bp_pid;
int bp_vid;
int bp_power;
int bp_en;
int bp_reset;
int ap_ready;
int bp_ready;
int ap_wakeup_bp;
int bp_wakeup_ap;
int bp_usb_en;
int bp_uart_en;
int trig;
char *name; //bp name can be null
int bp_id; //bp id the value must be one of enum bp_id
int bp_bus; // bp bus the value must be one of enum bp_bus_type
int bp_pid; // the pid of usb device if used usb else the value is BP_UNKNOW_DATA
int bp_vid; // the vid of usb device if used usb else the value is BP_UNKNOW_DATA
int bp_power;//bp power if used GPIO value else the is BP_UNKNOW_DATA
int bp_en;//bp power key if used GPIO value else the is BP_UNKNOW_DATA
int bp_reset;//bo reset if used GPIO value else the is BP_UNKNOW_DATA
int ap_ready;//bp ready if used GPIO value else the is BP_UNKNOW_DATA
int bp_ready;// bp ready if used GPIO value else the is BP_UNKNOW_DATA
int ap_wakeup_bp; //ap wakeup bp if used GPIO value else the is BP_UNKNOW_DATA
int bp_wakeup_ap;// bp wakeup ap if used GPIO value else the is BP_UNKNOW_DATA
int bp_assert;
int bp_usb_en;//not used
int bp_uart_en;//not used
int trig;//if 1:used board gpio define else used bp driver
int irq;
int (*active)(struct bp_private_data *bp, int enable);
int (*init)(struct bp_private_data *bp);
int (*reset)(struct bp_private_data *bp);
@@ -96,8 +104,7 @@ struct bp_operate {
int (*read_status)(struct bp_private_data *bp);
int (*write_status)(struct bp_private_data *bp);
int (*suspend)(struct bp_private_data *bp);
int (*resume)(struct bp_private_data *bp);
int (*resume)(struct bp_private_data *bp);
char *misc_name;
struct miscdevice *private_miscdev;
@@ -116,9 +123,7 @@ struct bp_private_data {
struct miscdevice miscdev;
struct file_operations id_fops;
struct miscdevice id_miscdev;
#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend early_suspend;
#endif
};
extern int bp_register_slave(struct bp_private_data *bp,

View File

@@ -0,0 +1,26 @@
#ifndef SMB347_CHARGER_H
#define SMB347_CHARGER_H
/*
* @chg_en_pin: charge enable pin (smb347's c4 pin)
* @chg_ctl_pin: charge control pin (smb347's d2 pin)
* @chg_stat_pin: charge stat pin (smb347's f5 pin)
* @chg_susp_pin: charge usb suspend pin (smb347's d3 pin)
* @max_current: dc and hc input current limit
* can set 300ma/500ma/700ma/900ma/1200ma
* or 1500ma/1800ma/2000ma/2200ma/2500ma
* @otg_power_form_smb: if otg 5v power form smb347 set 1 otherwise set 0
*/
struct smb347_info{
unsigned int chg_en_pin;
unsigned int chg_ctl_pin;
unsigned int chg_stat_pin;
unsigned int chg_susp_pin;
unsigned int max_current;
bool otg_power_form_smb;
};
extern int smb347_is_chg_ok(void);
extern int smb347_is_charging(void);
#endif