Revert "temp revert rk change"
This reverts commit 15f7fabcb8.
Conflicts:
.gitignore
arch/arm/boot/compressed/head.S
arch/arm/common/gic.c
arch/arm/kernel/Makefile
arch/arm/mm/proc-v7.S
arch/arm/tools/mach-types
arch/arm/vfp/vfphw.S
drivers/Kconfig
drivers/Makefile
drivers/char/Makefile
drivers/cpufreq/cpufreq_ondemand.c
drivers/gpio/gpiolib.c
drivers/gpio/tps65910-gpio.c
drivers/input/Makefile
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/touchscreen/Kconfig
drivers/media/video/Makefile
drivers/media/video/ov2640.c
drivers/media/video/soc_camera.c
drivers/media/video/uvc/uvc_v4l2.c
drivers/media/video/v4l2-ioctl.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/wm831x-core.c
drivers/mfd/wm831x-i2c.c
drivers/mfd/wm831x-irq.c
drivers/mfd/wm831x-spi.c
drivers/mfd/wm8994-core.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/pmem.c
drivers/mmc/card/block.c
drivers/mmc/core/core.c
drivers/mmc/core/mmc.c
drivers/mmc/core/sd.c
drivers/mmc/core/sdio.c
drivers/mmc/host/Makefile
drivers/net/wireless/Kconfig
drivers/net/wireless/Makefile
drivers/net/wireless/bcm4329/bcmsdh_linux.c
drivers/net/wireless/bcm4329/dhd.h
drivers/net/wireless/bcm4329/dhd_linux.c
drivers/net/wireless/bcm4329/wl_iw.c
drivers/net/wireless/bcm4329/wl_iw.h
drivers/power/wm831x_power.c
drivers/regulator/Makefile
drivers/regulator/core.c
drivers/regulator/tps65910-regulator.c
drivers/regulator/wm831x-dcdc.c
drivers/regulator/wm831x-isink.c
drivers/regulator/wm831x-ldo.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/serial/Kconfig
drivers/serial/Makefile
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/usb/Makefile
drivers/usb/gadget/Kconfig
drivers/usb/gadget/android.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/serial/option.c
drivers/video/backlight/wm831x_bl.c
fs/fat/dir.c
fs/fat/fatent.c
fs/fat/inode.c
fs/yaffs2/yaffs_fs.c
fs/yaffs2/yaffs_mtdif2.c
include/linux/i2c.h
include/linux/mfd/wm831x/core.h
include/linux/mfd/wm831x/pdata.h
include/linux/mfd/wm8994/core.h
include/linux/mfd/wm8994/pdata.h
include/linux/regulator/consumer.h
include/media/v4l2-chip-ident.h
kernel/power/earlysuspend.c
kernel/power/wakelock.c
kernel/sys.c
mm/page_alloc.c
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/wm8900.c
sound/soc/codecs/wm8988.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8994.h
sound/soc/codecs/wm_hubs.c
sound/soc/soc-cache.c
This commit is contained in:
parent
677ea8d595
commit
1bcabbad76
140 changed files with 9469 additions and 5111 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -32,6 +32,7 @@ modules.builtin
|
|||
*.lzo
|
||||
*.patch
|
||||
*.gcno
|
||||
Untitled Project.*
|
||||
|
||||
#
|
||||
# Top-level generic files
|
||||
|
|
@ -44,6 +45,7 @@ modules.builtin
|
|||
/System.map
|
||||
/Module.markers
|
||||
/Module.symvers
|
||||
/kernel.img
|
||||
|
||||
#
|
||||
# git files that we don't want to ignore even it they are dot-files
|
||||
|
|
|
|||
|
|
@ -862,6 +862,7 @@ config ARCH_RK29
|
|||
bool "Rockchip Soc Rk29"
|
||||
select CPU_V7
|
||||
select HAVE_CLK
|
||||
select CLKDEV_LOOKUP
|
||||
select COMMON_CLKDEV
|
||||
select HAVE_SCHED_CLOCK
|
||||
select ARCH_HAS_CPUFREQ
|
||||
|
|
|
|||
|
|
@ -177,6 +177,10 @@ not_angel:
|
|||
#endif
|
||||
|
||||
bl cache_on
|
||||
#ifdef CONFIG_ARCH_RK29
|
||||
bl cache_off
|
||||
bl cache_on
|
||||
#endif
|
||||
|
||||
restart: adr r0, LC0
|
||||
ldmia r0, {r1, r2, r3, r6, r10, r11, r12}
|
||||
|
|
|
|||
|
|
@ -92,6 +92,9 @@ static void gic_mask_irq(struct irq_data *d)
|
|||
writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
|
||||
if (gic_arch_extn.irq_mask)
|
||||
gic_arch_extn.irq_mask(d);
|
||||
#ifdef CONFIG_ARCH_RK29
|
||||
dsb();
|
||||
#endif
|
||||
spin_unlock(&irq_controller_lock);
|
||||
}
|
||||
|
||||
|
|
@ -103,6 +106,9 @@ static void gic_unmask_irq(struct irq_data *d)
|
|||
if (gic_arch_extn.irq_unmask)
|
||||
gic_arch_extn.irq_unmask(d);
|
||||
writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
|
||||
#ifdef CONFIG_ARCH_RK29
|
||||
dsb();
|
||||
#endif
|
||||
spin_unlock(&irq_controller_lock);
|
||||
}
|
||||
|
||||
|
|
@ -115,6 +121,9 @@ static void gic_eoi_irq(struct irq_data *d)
|
|||
}
|
||||
|
||||
writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
|
||||
#ifdef CONFIG_ARCH_RK29
|
||||
dsb();
|
||||
#endif
|
||||
}
|
||||
|
||||
static int gic_set_type(struct irq_data *d, unsigned int type)
|
||||
|
|
@ -203,6 +212,9 @@ static int gic_set_wake(struct irq_data *d, unsigned int on)
|
|||
{
|
||||
int ret = -ENXIO;
|
||||
|
||||
#ifdef CONFIG_ARCH_RK29
|
||||
return 0;
|
||||
#endif
|
||||
if (gic_arch_extn.irq_set_wake)
|
||||
ret = gic_arch_extn.irq_set_wake(d, on);
|
||||
|
||||
|
|
@ -278,8 +290,13 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
|
|||
* Find out how many interrupts are supported.
|
||||
* The GIC only supports up to 1020 interrupt sources.
|
||||
*/
|
||||
#ifdef CONFIG_ARCH_RK29
|
||||
/* rk29 read GIC_DIST_CTR is 2, why? */
|
||||
gic_irqs = NR_AIC_IRQS;
|
||||
#else
|
||||
gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
|
||||
gic_irqs = (gic_irqs + 1) * 32;
|
||||
#endif
|
||||
if (gic_irqs > 1020)
|
||||
gic_irqs = 1020;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ CFLAGS_REMOVE_return_address.o = -pg
|
|||
|
||||
obj-y := elf.o entry-armv.o entry-common.o irq.o \
|
||||
process.o ptrace.o return_address.o setup.o signal.o \
|
||||
sys_arm.o stacktrace.o time.o traps.o
|
||||
sys_arm.o stacktrace.o time.o traps.o dma.o
|
||||
|
||||
obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += compat.o
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,12 @@
|
|||
.equ swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000
|
||||
|
||||
.macro pgtbl, rd, phys
|
||||
#ifdef CONFIG_ARCH_RK29
|
||||
add \rd, \phys, #((TEXT_OFFSET - 0x4000) & 0xffff0000)
|
||||
add \rd, \rd, #((TEXT_OFFSET - 0x4000) & 0x0000ffff)
|
||||
#else
|
||||
add \rd, \phys, #TEXT_OFFSET - 0x4000
|
||||
#endif
|
||||
.endm
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
obj-y += timer.o io.o devices.o iomux.o clock.o rk29-pl330.o dma.o gpio.o ddr.o sram.o memcpy_dma.o reset.o
|
||||
obj-y += timer.o io.o devices.o iomux.o clock.o rk29-pl330.o dma.o ddr.o sram.o memcpy_dma.o reset.o
|
||||
obj-y += tests.o memtester.o
|
||||
obj-y += early_printk.o
|
||||
ifndef CONFIG_DEBUG_LL
|
||||
|
|
|
|||
|
|
@ -20,10 +20,13 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/android_pmem.h>
|
||||
#ifdef CONFIG_USB_ANDROID
|
||||
#include <linux/usb/android_composite.h>
|
||||
#endif
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/setup.h>
|
||||
|
|
@ -2935,8 +2938,12 @@ static struct spi_board_info board_spi_devices[] = {
|
|||
|
||||
static void __init rk29_gic_init_irq(void)
|
||||
{
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))
|
||||
gic_init(0, 32, (void __iomem *)RK29_GICPERI_BASE, (void __iomem *)RK29_GICCPU_BASE);
|
||||
#else
|
||||
gic_dist_init(0, (void __iomem *)RK29_GICPERI_BASE, 32);
|
||||
gic_cpu_init(0, (void __iomem *)RK29_GICCPU_BASE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __init machine_rk29_init_irq(void)
|
||||
|
|
@ -3016,9 +3023,11 @@ static void __init machine_rk29_mapio(void)
|
|||
}
|
||||
|
||||
MACHINE_START(RK29, "RK29board")
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37))
|
||||
/* UART for LL DEBUG */
|
||||
.phys_io = RK29_UART1_PHYS & 0xfff00000,
|
||||
.io_pg_offst = ((RK29_UART1_BASE) >> 18) & 0xfffc,
|
||||
#endif
|
||||
.boot_params = RK29_SDRAM_PHYS + 0x88000,
|
||||
.fixup = machine_rk29_fixup,
|
||||
.map_io = machine_rk29_mapio,
|
||||
|
|
|
|||
|
|
@ -27,7 +27,11 @@
|
|||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
|
||||
#include <linux/clkdev.h>
|
||||
#else
|
||||
#include <asm/clkdev.h>
|
||||
#endif
|
||||
#include <mach/rk29_iomap.h>
|
||||
#include <mach/cru.h>
|
||||
#include <mach/pmu.h>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,9 @@
|
|||
#include <linux/fs.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#ifdef CONFIG_USB_ANDROID
|
||||
#include <linux/usb/android_composite.h>
|
||||
#endif
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <asm/pmu.h>
|
||||
|
|
@ -746,7 +748,7 @@ struct platform_device usb_mass_storage_device = {
|
|||
};
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_USB_ANDROID_RNDIS
|
||||
static struct usb_ether_platform_data rndis_pdata = {
|
||||
/* ethaddr is filled by board_serialno_setup */
|
||||
.ethaddr = {0xf0, 0xde, 0xf1, 0x42, 0xe8, 0x10},
|
||||
|
|
@ -761,6 +763,7 @@ struct platform_device rk29_device_rndis = {
|
|||
.platform_data = &rndis_pdata,
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB11_HOST
|
||||
static struct resource usb11_host_resource[] = {
|
||||
|
|
|
|||
|
|
@ -1,617 +0,0 @@
|
|||
/* arch/arm/mach-rk29/gpio.c
|
||||
*
|
||||
* Copyright (C) 2010 ROCKCHIP, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/rk29_iomap.h>
|
||||
#include <mach/iomux.h>
|
||||
#include <asm/gpio.h>
|
||||
|
||||
|
||||
#define to_rk29_gpio_chip(c) container_of(c, struct rk29_gpio_chip, chip)
|
||||
|
||||
struct rk29_gpio_chip {
|
||||
struct gpio_chip chip;
|
||||
unsigned short id;
|
||||
short irq;
|
||||
unsigned char __iomem *regbase; /* Base of register bank */
|
||||
struct clk *clk;
|
||||
u32 suspend_wakeup;
|
||||
u32 saved_wakeup;
|
||||
};
|
||||
|
||||
static struct lock_class_key gpio_lock_class;
|
||||
|
||||
static void rk29_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip);
|
||||
static void rk29_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val);
|
||||
static int rk29_gpiolib_get(struct gpio_chip *chip, unsigned offset);
|
||||
static int rk29_gpiolib_direction_output(struct gpio_chip *chip,unsigned offset, int val);
|
||||
static int rk29_gpiolib_direction_input(struct gpio_chip *chip,unsigned offset);
|
||||
static int rk29_gpiolib_PullUpDown(struct gpio_chip *chip, unsigned offset, unsigned enable);
|
||||
static int rk29_gpiolib_to_irq(struct gpio_chip *chip,unsigned offset);
|
||||
|
||||
#define RK29_GPIO_CHIP(ID) \
|
||||
{ \
|
||||
.chip = { \
|
||||
.label = "gpio" #ID, \
|
||||
.direction_input = rk29_gpiolib_direction_input, \
|
||||
.direction_output = rk29_gpiolib_direction_output, \
|
||||
.get = rk29_gpiolib_get, \
|
||||
.set = rk29_gpiolib_set, \
|
||||
.pull_updown = rk29_gpiolib_PullUpDown, \
|
||||
.dbg_show = rk29_gpiolib_dbg_show, \
|
||||
.to_irq = rk29_gpiolib_to_irq, \
|
||||
.base = PIN_BASE + ID*NUM_GROUP, \
|
||||
.ngpio = NUM_GROUP, \
|
||||
}, \
|
||||
.id = ID, \
|
||||
.irq = IRQ_GPIO##ID, \
|
||||
.regbase = (unsigned char __iomem *) RK29_GPIO##ID##_BASE, \
|
||||
}
|
||||
|
||||
static struct rk29_gpio_chip rk29gpio_chip[] = {
|
||||
RK29_GPIO_CHIP(0),
|
||||
RK29_GPIO_CHIP(1),
|
||||
RK29_GPIO_CHIP(2),
|
||||
RK29_GPIO_CHIP(3),
|
||||
RK29_GPIO_CHIP(4),
|
||||
RK29_GPIO_CHIP(5),
|
||||
RK29_GPIO_CHIP(6),
|
||||
};
|
||||
|
||||
static inline void rk29_gpio_write(unsigned char __iomem *regbase, unsigned int regOff,unsigned int val)
|
||||
{
|
||||
__raw_writel(val,regbase + regOff);
|
||||
}
|
||||
|
||||
static inline unsigned int rk29_gpio_read(unsigned char __iomem *regbase, unsigned int regOff)
|
||||
{
|
||||
return __raw_readl(regbase + regOff);
|
||||
}
|
||||
|
||||
static inline void rk29_gpio_bitOp(unsigned char __iomem *regbase, unsigned int regOff,unsigned int mask,unsigned char opFlag)
|
||||
{
|
||||
unsigned int valTemp = 0;
|
||||
|
||||
if(opFlag == 0)//对寄存器相应位进行与0操作
|
||||
{
|
||||
valTemp = rk29_gpio_read(regbase,regOff);
|
||||
valTemp &= (~mask);;
|
||||
rk29_gpio_write(regbase,regOff,valTemp);
|
||||
}
|
||||
else if(opFlag == 1)//对寄存器相应位进行或1操作
|
||||
{
|
||||
valTemp = rk29_gpio_read(regbase,regOff);
|
||||
valTemp |= mask;
|
||||
rk29_gpio_write(regbase,regOff,valTemp);
|
||||
}
|
||||
}
|
||||
|
||||
static inline struct gpio_chip *pin_to_gpioChip(unsigned pin)
|
||||
{
|
||||
if(pin < PIN_BASE)
|
||||
return NULL;
|
||||
|
||||
pin -= PIN_BASE;
|
||||
pin /= NUM_GROUP;
|
||||
if (likely(pin < MAX_BANK))
|
||||
return &(rk29gpio_chip[pin].chip);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline unsigned pin_to_mask(unsigned pin)
|
||||
{
|
||||
if(pin < PIN_BASE)
|
||||
return 0;
|
||||
pin -= PIN_BASE;
|
||||
return 1ul << (pin % NUM_GROUP);
|
||||
}
|
||||
|
||||
static inline unsigned offset_to_mask(unsigned offset)
|
||||
{
|
||||
return 1ul << (offset % NUM_GROUP);
|
||||
}
|
||||
|
||||
static int GPIOSetPinLevel(struct gpio_chip *chip, unsigned int mask,eGPIOPinLevel_t level)
|
||||
{
|
||||
struct rk29_gpio_chip *rk29_gpio = to_rk29_gpio_chip(chip);
|
||||
unsigned char __iomem *gpioRegBase = rk29_gpio->regbase;
|
||||
unsigned long flags;
|
||||
|
||||
if(!rk29_gpio || !gpioRegBase)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
local_irq_save(flags);
|
||||
rk29_gpio_bitOp(gpioRegBase,GPIO_SWPORT_DDR,mask,1);
|
||||
rk29_gpio_bitOp(gpioRegBase,GPIO_SWPORT_DR,mask,level);
|
||||
local_irq_restore(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int GPIOGetPinLevel(struct gpio_chip *chip, unsigned int mask)
|
||||
{
|
||||
unsigned int valTemp;
|
||||
struct rk29_gpio_chip *rk29_gpio = to_rk29_gpio_chip(chip);
|
||||
unsigned char __iomem *gpioRegBase = rk29_gpio->regbase;
|
||||
|
||||
if(!rk29_gpio || !gpioRegBase)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
valTemp = rk29_gpio_read(gpioRegBase,GPIO_EXT_PORT);
|
||||
return ((valTemp & mask) != 0);
|
||||
}
|
||||
|
||||
static int GPIOSetPinDirection(struct gpio_chip *chip, unsigned int mask,eGPIOPinDirection_t direction)
|
||||
{
|
||||
struct rk29_gpio_chip *rk29_gpio = to_rk29_gpio_chip(chip);
|
||||
unsigned char __iomem *gpioRegBase = rk29_gpio->regbase;
|
||||
unsigned long flags;
|
||||
|
||||
if(!rk29_gpio || !gpioRegBase)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
local_irq_save(flags);
|
||||
rk29_gpio_bitOp(gpioRegBase,GPIO_SWPORT_DDR,mask,direction);
|
||||
/* Enable debounce may halt cpu on wfi, disable it by default */
|
||||
//rk29_gpio_bitOp(gpioRegBase,GPIO_DEBOUNCE,mask,1);
|
||||
local_irq_restore(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int GPIOEnableIntr(struct gpio_chip *chip, unsigned int mask)
|
||||
{
|
||||
struct rk29_gpio_chip *rk29_gpio = to_rk29_gpio_chip(chip);
|
||||
unsigned char __iomem *gpioRegBase = rk29_gpio->regbase;
|
||||
|
||||
if(!rk29_gpio || !gpioRegBase)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
rk29_gpio_bitOp(gpioRegBase,GPIO_INTEN,mask,1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int GPIODisableIntr(struct gpio_chip *chip, unsigned int mask)
|
||||
{
|
||||
struct rk29_gpio_chip *rk29_gpio = to_rk29_gpio_chip(chip);
|
||||
unsigned char __iomem *gpioRegBase = rk29_gpio->regbase;
|
||||
|
||||
if(!rk29_gpio || !gpioRegBase)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
rk29_gpio_bitOp(gpioRegBase,GPIO_INTEN,mask,0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int GPIOSetIntrType(struct gpio_chip *chip, unsigned int mask, eGPIOIntType_t IntType)
|
||||
{
|
||||
struct rk29_gpio_chip *rk29_gpio = to_rk29_gpio_chip(chip);
|
||||
unsigned char __iomem *gpioRegBase = rk29_gpio->regbase;
|
||||
|
||||
if(!rk29_gpio || !gpioRegBase)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch ( IntType )
|
||||
{
|
||||
case GPIOLevelLow:
|
||||
rk29_gpio_bitOp(gpioRegBase,GPIO_INT_POLARITY,mask,0);
|
||||
rk29_gpio_bitOp(gpioRegBase,GPIO_INTTYPE_LEVEL,mask,0);
|
||||
break;
|
||||
case GPIOLevelHigh:
|
||||
rk29_gpio_bitOp(gpioRegBase,GPIO_INTTYPE_LEVEL,mask,0);
|
||||
rk29_gpio_bitOp(gpioRegBase,GPIO_INT_POLARITY,mask,1);
|
||||
break;
|
||||
case GPIOEdgelFalling:
|
||||
rk29_gpio_bitOp(gpioRegBase,GPIO_INTTYPE_LEVEL,mask,1);
|
||||
rk29_gpio_bitOp(gpioRegBase,GPIO_INT_POLARITY,mask,0);
|
||||
break;
|
||||
case GPIOEdgelRising:
|
||||
rk29_gpio_bitOp(gpioRegBase,GPIO_INTTYPE_LEVEL,mask,1);
|
||||
rk29_gpio_bitOp(gpioRegBase,GPIO_INT_POLARITY,mask,1);
|
||||
break;
|
||||
default:
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int gpio_irq_set_wake(unsigned int irq, unsigned int on)
|
||||
{
|
||||
unsigned int pin = irq_to_gpio(irq);
|
||||
unsigned bank = (pin - PIN_BASE) / NUM_GROUP;
|
||||
struct rk29_gpio_chip *rk29_gpio;
|
||||
unsigned mask = pin_to_mask(pin);
|
||||
|
||||
if (unlikely(bank >= MAX_BANK))
|
||||
return -EINVAL;
|
||||
|
||||
rk29_gpio = &rk29gpio_chip[bank];
|
||||
if (on)
|
||||
rk29_gpio->suspend_wakeup |= mask;
|
||||
else
|
||||
rk29_gpio->suspend_wakeup &= ~mask;
|
||||
|
||||
set_irq_wake(rk29_gpio->irq, on);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_irq_type(unsigned irq, unsigned type)
|
||||
{
|
||||
unsigned int pin = irq_to_gpio(irq);
|
||||
struct gpio_chip *chip = pin_to_gpioChip(pin);
|
||||
unsigned mask = pin_to_mask(pin);
|
||||
|
||||
if(!chip || !mask)
|
||||
return -EINVAL;
|
||||
//设置为中断之前,必须先设置为输入状态
|
||||
GPIOSetPinDirection(chip,mask,GPIO_IN);
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_NONE:
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
GPIOSetIntrType(chip,mask,GPIOEdgelRising);
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
GPIOSetIntrType(chip,mask,GPIOEdgelFalling);
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
GPIOSetIntrType(chip,mask,GPIOLevelHigh);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
GPIOSetIntrType(chip,mask,GPIOLevelLow);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
|
||||
__set_irq_handler_unlocked(irq, handle_level_irq);
|
||||
else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
|
||||
__set_irq_handler_unlocked(irq, handle_edge_irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int GPIOAckIntr(struct gpio_chip *chip, unsigned int mask)
|
||||
{
|
||||
struct rk29_gpio_chip *rk29_gpio = to_rk29_gpio_chip(chip);
|
||||
unsigned char __iomem *gpioRegBase = rk29_gpio->regbase;
|
||||
|
||||
if(!rk29_gpio || !gpioRegBase)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
rk29_gpio_bitOp(gpioRegBase,GPIO_PORTS_EOI,mask,1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gpio_irq_unmask(unsigned irq)
|
||||
{
|
||||
unsigned int pin = irq_to_gpio(irq);
|
||||
struct gpio_chip *chip = pin_to_gpioChip(pin);
|
||||
unsigned mask = pin_to_mask(pin);
|
||||
|
||||
if(chip && mask)
|
||||
GPIOEnableIntr(chip,mask);
|
||||
}
|
||||
|
||||
static void gpio_irq_mask(unsigned irq)
|
||||
{
|
||||
unsigned int pin = irq_to_gpio(irq);
|
||||
struct gpio_chip *chip = pin_to_gpioChip(pin);
|
||||
unsigned mask = pin_to_mask(pin);
|
||||
|
||||
if(chip && mask)
|
||||
GPIODisableIntr(chip,mask);
|
||||
}
|
||||
|
||||
static void gpio_ack_irq(u32 irq)
|
||||
{
|
||||
unsigned int pin = irq_to_gpio(irq);
|
||||
struct gpio_chip *chip = pin_to_gpioChip(pin);
|
||||
unsigned mask = pin_to_mask(pin);
|
||||
|
||||
if(chip && mask)
|
||||
GPIOAckIntr(chip,mask);
|
||||
}
|
||||
|
||||
static int GPIOPullUpDown(struct gpio_chip *chip, unsigned int offset, unsigned enable)
|
||||
{
|
||||
unsigned int temp = 0;
|
||||
struct rk29_gpio_chip *rk29_gpio = to_rk29_gpio_chip(chip);
|
||||
unsigned char __iomem *pGrfRegBase = (unsigned char __iomem *)RK29_GRF_BASE;
|
||||
unsigned long flags;
|
||||
|
||||
if(!rk29_gpio || !pGrfRegBase)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(offset >= 32)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
local_irq_save(flags);
|
||||
temp = __raw_readl(pGrfRegBase + 0x78 +(rk29_gpio->id)*4);
|
||||
if(!enable)
|
||||
temp |= 1<<offset;
|
||||
else
|
||||
temp &= ~(1<<offset);
|
||||
|
||||
__raw_writel(temp,pGrfRegBase + 0x78 +(rk29_gpio->id)*4);
|
||||
local_irq_restore(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int rk29_gpiolib_direction_output(struct gpio_chip *chip,unsigned offset, int val)
|
||||
{
|
||||
unsigned mask = offset_to_mask(offset);
|
||||
|
||||
if(GPIOSetPinDirection(chip,mask,GPIO_OUT) == 0)
|
||||
{
|
||||
return GPIOSetPinLevel(chip,mask,val);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int rk29_gpiolib_direction_input(struct gpio_chip *chip,unsigned offset)
|
||||
{
|
||||
unsigned mask = offset_to_mask(offset);
|
||||
|
||||
return GPIOSetPinDirection(chip,mask,GPIO_IN);
|
||||
}
|
||||
|
||||
|
||||
static int rk29_gpiolib_get(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
unsigned mask = offset_to_mask(offset);
|
||||
|
||||
return GPIOGetPinLevel(chip,mask);
|
||||
}
|
||||
|
||||
static void rk29_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val)
|
||||
{
|
||||
unsigned mask = offset_to_mask(offset);
|
||||
|
||||
GPIOSetPinLevel(chip,mask,val);
|
||||
}
|
||||
|
||||
static int rk29_gpiolib_PullUpDown(struct gpio_chip *chip, unsigned offset, unsigned enable)
|
||||
{
|
||||
return GPIOPullUpDown(chip, offset, enable);
|
||||
}
|
||||
|
||||
static int rk29_gpiolib_to_irq(struct gpio_chip *chip,
|
||||
unsigned offset)
|
||||
{
|
||||
struct rk29_gpio_chip *rk29_gpio = to_rk29_gpio_chip(chip);
|
||||
|
||||
if(!rk29_gpio)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return offset + NR_IRQS;
|
||||
}
|
||||
|
||||
static void rk29_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < chip->ngpio; i++) {
|
||||
unsigned pin = chip->base + i;
|
||||
struct gpio_chip *chip = pin_to_gpioChip(pin);
|
||||
unsigned mask = pin_to_mask(pin);
|
||||
const char *gpio_label;
|
||||
|
||||
if(!chip ||!mask)
|
||||
return;
|
||||
|
||||
gpio_label = gpiochip_is_requested(chip, i);
|
||||
if (gpio_label) {
|
||||
seq_printf(s, "[%s] GPIO%s%d: ",
|
||||
gpio_label, chip->label, i);
|
||||
|
||||
if (!chip || !mask)
|
||||
{
|
||||
seq_printf(s, "!chip || !mask\t");
|
||||
return;
|
||||
}
|
||||
|
||||
GPIOSetPinDirection(chip,mask,GPIO_IN);
|
||||
seq_printf(s, "pin=%d,level=%d\t", pin,GPIOGetPinLevel(chip,mask));
|
||||
seq_printf(s, "\t");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
|
||||
{
|
||||
unsigned gpio_irq;
|
||||
struct rk29_gpio_chip *rk29_gpio;
|
||||
u32 isr;
|
||||
|
||||
rk29_gpio = get_irq_chip_data(irq+13);
|
||||
|
||||
// temporarily mask parent IRQ
|
||||
desc->chip->mask(irq);
|
||||
if(desc->chip->ack)
|
||||
desc->chip->ack(irq);
|
||||
|
||||
isr = rk29_gpio_read(rk29_gpio->regbase, GPIO_INT_STATUS);
|
||||
|
||||
gpio_irq = gpio_to_irq(rk29_gpio->chip.base);
|
||||
|
||||
while (isr) {
|
||||
int irqoffset = fls(isr) - 1;
|
||||
generic_handle_irq(gpio_irq + irqoffset);
|
||||
isr &= ~(1 << irqoffset);
|
||||
}
|
||||
|
||||
desc->chip->unmask(irq);
|
||||
/* now it may re-trigger */
|
||||
}
|
||||
|
||||
static struct irq_chip rk29gpio_irqchip = {
|
||||
.name = "GPIO",
|
||||
.ack = gpio_ack_irq,
|
||||
.disable = gpio_irq_mask,
|
||||
.mask = gpio_irq_mask,
|
||||
.unmask = gpio_irq_unmask,
|
||||
.set_type = gpio_irq_type,
|
||||
.set_wake = gpio_irq_set_wake,
|
||||
};
|
||||
|
||||
static void __init rk29_gpio_irq_setup(void)
|
||||
{
|
||||
unsigned int i, j, pin;
|
||||
struct rk29_gpio_chip *this;
|
||||
|
||||
this = rk29gpio_chip;
|
||||
pin = NR_AIC_IRQS;
|
||||
for (i = 0; i < MAX_BANK; i++) {
|
||||
rk29_gpio_write(this->regbase,GPIO_INTEN,0);
|
||||
for (j = 0; j < 32; j++) {
|
||||
lockdep_set_class(&irq_desc[pin+j].lock, &gpio_lock_class);
|
||||
set_irq_chip(pin+j, &rk29gpio_irqchip);
|
||||
set_irq_handler(pin+j, handle_level_irq);
|
||||
set_irq_flags(pin+j, IRQF_VALID);
|
||||
}
|
||||
|
||||
set_irq_chip_data(NR_AIC_IRQS + this->id, this);
|
||||
set_irq_chained_handler(this->irq, gpio_irq_handler);
|
||||
this += 1;
|
||||
pin += 32;
|
||||
}
|
||||
printk("rk29_gpio_irq_setup: %d gpio irqs in 7 banks\n", pin - PIN_BASE);
|
||||
}
|
||||
|
||||
void __init rk29_gpio_init(void)
|
||||
{
|
||||
unsigned i;
|
||||
struct rk29_gpio_chip *rk29_gpio;
|
||||
|
||||
for (i = 0; i < MAX_BANK; i++) {
|
||||
rk29_gpio = &rk29gpio_chip[i];
|
||||
rk29_gpio->clk = clk_get(NULL, rk29_gpio->chip.label);
|
||||
clk_enable(rk29_gpio->clk);
|
||||
gpiochip_add(&rk29_gpio->chip);
|
||||
}
|
||||
rk29_gpio_irq_setup();
|
||||
}
|
||||
|
||||
__weak void rk29_setgpio_suspend_board(void)
|
||||
{
|
||||
}
|
||||
|
||||
__weak void rk29_setgpio_resume_board(void)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int rk29_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
rk29_setgpio_suspend_board();
|
||||
|
||||
for (i = 0; i < MAX_BANK; i++) {
|
||||
struct rk29_gpio_chip *rk29_gpio = &rk29gpio_chip[i];
|
||||
|
||||
rk29_gpio->saved_wakeup = rk29_gpio_read(rk29_gpio->regbase, GPIO_INTEN);
|
||||
rk29_gpio_write(rk29_gpio->regbase, GPIO_INTEN, rk29_gpio->suspend_wakeup);
|
||||
|
||||
if (!rk29_gpio->suspend_wakeup)
|
||||
clk_disable(rk29_gpio->clk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk29_gpio_resume(struct sys_device *dev)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < MAX_BANK; i++) {
|
||||
struct rk29_gpio_chip *rk29_gpio = &rk29gpio_chip[i];
|
||||
|
||||
if (!rk29_gpio->suspend_wakeup)
|
||||
clk_enable(rk29_gpio->clk);
|
||||
|
||||
/* keep enable for resume irq */
|
||||
rk29_gpio_write(rk29_gpio->regbase, GPIO_INTEN, rk29_gpio->saved_wakeup | (rk29_gpio->suspend_wakeup & rk29_gpio_read(rk29_gpio->regbase, GPIO_INT_STATUS)));
|
||||
}
|
||||
rk29_setgpio_resume_board();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_class rk29_gpio_sysclass = {
|
||||
.name = "gpio",
|
||||
.suspend = rk29_gpio_suspend,
|
||||
.resume = rk29_gpio_resume,
|
||||
};
|
||||
|
||||
static struct sys_device rk29_gpio_device = {
|
||||
.cls = &rk29_gpio_sysclass,
|
||||
};
|
||||
|
||||
static int __init rk29_gpio_sysinit(void)
|
||||
{
|
||||
int ret = sysdev_class_register(&rk29_gpio_sysclass);
|
||||
if (ret == 0)
|
||||
ret = sysdev_register(&rk29_gpio_device);
|
||||
return ret;
|
||||
}
|
||||
|
||||
arch_initcall(rk29_gpio_sysinit);
|
||||
#endif
|
||||
|
|
@ -124,6 +124,7 @@ struct rk29_bl_info{
|
|||
unsigned int delay_ms; /* in milliseconds */
|
||||
};
|
||||
|
||||
#ifndef _LINUX_WLAN_PLAT_H_
|
||||
struct wifi_platform_data {
|
||||
int (*set_power)(int val);
|
||||
int (*set_reset)(int val);
|
||||
|
|
@ -131,6 +132,7 @@ struct wifi_platform_data {
|
|||
void *(*mem_prealloc)(int section, unsigned long size);
|
||||
int (*get_mac_addr)(unsigned char *buf);
|
||||
};
|
||||
#endif
|
||||
|
||||
struct rk29_sdmmc_platform_data {
|
||||
unsigned int host_caps;
|
||||
|
|
|
|||
|
|
@ -18,12 +18,12 @@
|
|||
#include <linux/version.h>
|
||||
#include <mach/rk29_iomap.h>
|
||||
|
||||
/* note, for the boot process to work we have to keep the UART
|
||||
* virtual address aligned to an 1MiB boundary for the L1
|
||||
* mapping the head code makes. We keep the UART virtual address
|
||||
* aligned and add in the offset when we load the value here.
|
||||
*/
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
|
||||
.macro addruart, rp, rv
|
||||
ldr \rp, = RK29_UART1_PHYS
|
||||
ldr \rv, = RK29_UART1_BASE
|
||||
.endm
|
||||
#else
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34))
|
||||
.macro addruart, rx, tmp
|
||||
#else
|
||||
|
|
@ -34,6 +34,7 @@
|
|||
ldreq \rx, = RK29_UART1_PHYS
|
||||
ldrne \rx, = RK29_UART1_BASE
|
||||
.endm
|
||||
#endif
|
||||
|
||||
#define UART_SHIFT 2
|
||||
#include <asm/hardware/debug-8250.S>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@
|
|||
*/
|
||||
#ifndef __ARCH_ARM_MACH_RK29_GPIO_H
|
||||
#define __ARCH_ARM_MACH_RK29_GPIO_H
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <mach/irqs.h>
|
||||
|
||||
typedef enum eGPIOPinLevel
|
||||
{
|
||||
|
|
@ -67,7 +68,7 @@ typedef enum GPIOIntType {
|
|||
#define RK29_ID_GPIO6 6
|
||||
|
||||
#define NUM_GROUP 32
|
||||
#define PIN_BASE 0
|
||||
#define PIN_BASE NR_AIC_IRQS
|
||||
#define MAX_BANK 7
|
||||
|
||||
#define RK29_TOTOL_GPIO_NUM (NUM_GROUP*MAX_BANK)
|
||||
|
|
@ -105,7 +106,7 @@ typedef enum GPIOIntType {
|
|||
#endif
|
||||
|
||||
//定义GPIO的PIN口最大数目。CONFIG_SPI_FPGA_GPIO_NUM表示FPGA的PIN脚数。
|
||||
#define ARCH_NR_GPIOS (RK29_TOTOL_GPIO_NUM + TCA6424_TOTOL_GPIO_NUM + WM831X_TOTOL_GPIO_NUM + CONFIG_SPI_FPGA_GPIO_NUM+CONFIG_GPIO_WM8994_NUM)
|
||||
#define ARCH_NR_GPIOS (PIN_BASE + RK29_TOTOL_GPIO_NUM + TCA6424_TOTOL_GPIO_NUM + WM831X_TOTOL_GPIO_NUM + CONFIG_SPI_FPGA_GPIO_NUM+CONFIG_GPIO_WM8994_NUM)
|
||||
|
||||
|
||||
#define RK29_PIN0_PA0 (0*NUM_GROUP + PIN_BASE + 0)
|
||||
|
|
@ -506,7 +507,6 @@ extern void __init rk29_gpio_init(void);
|
|||
|
||||
#include <asm/errno.h>
|
||||
#include <asm-generic/gpio.h> /* cansleep wrappers */
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#define gpio_get_value __gpio_get_value
|
||||
#define gpio_set_value __gpio_set_value
|
||||
|
|
@ -514,15 +514,14 @@ extern void __init rk29_gpio_init(void);
|
|||
|
||||
static inline int gpio_to_irq(unsigned gpio)
|
||||
{
|
||||
return (gpio + NR_AIC_IRQS);
|
||||
return gpio - PIN_BASE + NR_AIC_IRQS;
|
||||
}
|
||||
|
||||
static inline int irq_to_gpio(unsigned irq)
|
||||
{
|
||||
return (irq - NR_AIC_IRQS);
|
||||
return irq - NR_AIC_IRQS + PIN_BASE;
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -375,6 +375,16 @@ __v7_setup:
|
|||
ALT_SMP(orr r8, r8, #TTB_FLAGS_SMP)
|
||||
ALT_UP(orr r8, r8, #TTB_FLAGS_UP)
|
||||
mcr p15, 0, r8, c2, c0, 1 @ load TTB1
|
||||
#ifdef CONFIG_ARCH_RK29
|
||||
/* Setup L2 cache */
|
||||
mrc p15, 1, r5, c9, c0, 2
|
||||
bic r5, r5, #1 << 29 @ L2 data RAM read multiplexer select: 0 = two cycles
|
||||
bic r5, r5, #7 << 6
|
||||
bic r5, r5, #15
|
||||
orr r5, r5, #2 << 6 @ Tag RAM latency: b010 = 3 cycles
|
||||
orr r5, r5, #3 @ Data RAM latency: b0011 = 4 cycles
|
||||
mcr p15, 1, r5, c9, c0, 2
|
||||
#endif
|
||||
ldr r5, =PRRR @ PRRR
|
||||
ldr r6, =NMRR @ NMRR
|
||||
mcr p15, 0, r5, c10, c2, 0 @ write PRRR
|
||||
|
|
|
|||
|
|
@ -569,7 +569,8 @@ smdkv310 MACH_SMDKV310 SMDKV310 2925
|
|||
siemens_l0 MACH_SIEMENS_L0 SIEMENS_L0 2926
|
||||
ventana MACH_VENTANA VENTANA 2927
|
||||
wm8505_7in_netbook MACH_WM8505_7IN_NETBOOK WM8505_7IN_NETBOOK 2928
|
||||
ec4350sdb MACH_EC4350SDB EC4350SDB 2929
|
||||
rk29 MACH_RK29 RK29 2929
|
||||
#ec4350sdb MACH_EC4350SDB EC4350SDB 2929
|
||||
mimas MACH_MIMAS MIMAS 2930
|
||||
titan MACH_TITAN TITAN 2931
|
||||
craneboard MACH_CRANEBOARD CRANEBOARD 2932
|
||||
|
|
|
|||
|
|
@ -206,6 +206,25 @@ ENTRY(vfp_save_state)
|
|||
mov pc, lr
|
||||
ENDPROC(vfp_save_state)
|
||||
|
||||
#ifdef CONFIG_ARCH_RK29
|
||||
ENTRY(vfp_load_state)
|
||||
@ Save the current VFP state
|
||||
@ r0 - save location
|
||||
@ r1 - FPEXC
|
||||
DBGSTR1 "save VFP state %p", r0
|
||||
VFPFLDMIA r0, r2 @ save the working registers
|
||||
ldmia r0, {r1,r2,r3,r12}
|
||||
tst r1, #FPEXC_EX @ is there additional state to save?
|
||||
beq 1f
|
||||
tst r1, #FPEXC_FP2V @ is there an FPINST2 to read?
|
||||
beq 1f
|
||||
1:
|
||||
VFPFMXR FPSCR, r2
|
||||
VFPFMXR FPEXC, r1
|
||||
mov pc, lr
|
||||
ENDPROC(vfp_load_state)
|
||||
#endif
|
||||
|
||||
.align
|
||||
last_VFP_context_address:
|
||||
.word last_VFP_context
|
||||
|
|
|
|||
|
|
@ -52,6 +52,10 @@ source "drivers/i2c/Kconfig"
|
|||
|
||||
source "drivers/spi/Kconfig"
|
||||
|
||||
source "drivers/adc/Kconfig"
|
||||
|
||||
source "drivers/headset_observe/Kconfig"
|
||||
|
||||
source "drivers/pps/Kconfig"
|
||||
|
||||
source "drivers/ptp/Kconfig"
|
||||
|
|
@ -128,4 +132,12 @@ source "drivers/hwspinlock/Kconfig"
|
|||
|
||||
source "drivers/clocksource/Kconfig"
|
||||
|
||||
source "drivers/cmmb/Kconfig"
|
||||
|
||||
source "drivers/testcode/Kconfig"
|
||||
|
||||
source "drivers/smc/Kconfig"
|
||||
|
||||
source "drivers/cir/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ obj-$(CONFIG_ATA) += ata/
|
|||
obj-$(CONFIG_TARGET_CORE) += target/
|
||||
obj-$(CONFIG_MTD) += mtd/
|
||||
obj-$(CONFIG_SPI) += spi/
|
||||
obj-y += headset_observe/
|
||||
obj-y += net/
|
||||
obj-$(CONFIG_ATM) += atm/
|
||||
obj-$(CONFIG_FUSION) += message/
|
||||
|
|
@ -77,6 +78,7 @@ obj-$(CONFIG_INPUT) += input/
|
|||
obj-$(CONFIG_I2O) += message/
|
||||
obj-$(CONFIG_RTC_LIB) += rtc/
|
||||
obj-y += i2c/ media/
|
||||
obj-y += adc/
|
||||
obj-$(CONFIG_PPS) += pps/
|
||||
obj-$(CONFIG_PTP_1588_CLOCK) += ptp/
|
||||
obj-$(CONFIG_W1) += w1/
|
||||
|
|
@ -123,3 +125,8 @@ obj-y += ieee802154/
|
|||
obj-y += clk/
|
||||
|
||||
obj-$(CONFIG_HWSPINLOCK) += hwspinlock/
|
||||
obj-$(CONFIG_CMMB) += cmmb/
|
||||
obj-$(CONFIG_TEST_CODE) += testcode/
|
||||
obj-y += smc/
|
||||
obj-y += cir/
|
||||
obj-y += dbg/
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@
|
|||
#include <linux/async.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/timer.h>
|
||||
#ifdef CONFIG_ARCH_RK29
|
||||
#include <linux/console.h>
|
||||
#endif
|
||||
|
||||
#include "../base.h"
|
||||
#include "power.h"
|
||||
|
|
@ -608,6 +611,9 @@ static void dpm_drv_timeout(unsigned long data)
|
|||
printk(KERN_EMERG "**** DPM device timeout: %s (%s)\n", dev_name(dev),
|
||||
(dev->driver ? dev->driver->name : "no driver"));
|
||||
|
||||
#ifdef CONFIG_ARCH_RK29
|
||||
resume_console();
|
||||
#endif
|
||||
printk(KERN_EMERG "dpm suspend stack:\n");
|
||||
show_stack(tsk, NULL);
|
||||
|
||||
|
|
|
|||
|
|
@ -32,8 +32,13 @@
|
|||
#define DEF_FREQUENCY_UP_THRESHOLD (80)
|
||||
#define DEF_SAMPLING_DOWN_FACTOR (1)
|
||||
#define MAX_SAMPLING_DOWN_FACTOR (100000)
|
||||
#ifdef CONFIG_ARCH_RK29
|
||||
#define MICRO_FREQUENCY_DOWN_DIFFERENTIAL (10)
|
||||
#define MICRO_FREQUENCY_UP_THRESHOLD (80)
|
||||
#else
|
||||
#define MICRO_FREQUENCY_DOWN_DIFFERENTIAL (3)
|
||||
#define MICRO_FREQUENCY_UP_THRESHOLD (95)
|
||||
#endif
|
||||
#define MICRO_FREQUENCY_MIN_SAMPLE_RATE (10000)
|
||||
#define MIN_FREQUENCY_UP_THRESHOLD (11)
|
||||
#define MAX_FREQUENCY_UP_THRESHOLD (100)
|
||||
|
|
|
|||
|
|
@ -268,13 +268,6 @@ config GPIO_TWL4030
|
|||
Say yes here to access the GPIO signals of various multi-function
|
||||
power management chips from Texas Instruments.
|
||||
|
||||
config GPIO_TPS65910
|
||||
bool "TPS65910 GPIOs"
|
||||
depends on TPS65910_CORE
|
||||
help
|
||||
Say yes here to access the GPIO signal of TPS65910x multi-function
|
||||
power management chips from Texas Instruments.
|
||||
|
||||
config GPIO_WM831X
|
||||
tristate "WM831x GPIOs"
|
||||
depends on MFD_WM831X
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o
|
|||
obj-$(CONFIG_GPIO_TC3589X) += tc3589x-gpio.o
|
||||
obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o
|
||||
obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o
|
||||
obj-$(CONFIG_GPIO_TPS65910) += tps65910-gpio.o
|
||||
obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o
|
||||
obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o
|
||||
obj-$(CONFIG_GPIO_CS5535) += cs5535-gpio.o
|
||||
|
|
@ -46,6 +45,7 @@ obj-$(CONFIG_GPIO_SCH) += sch_gpio.o
|
|||
obj-$(CONFIG_MACH_U300) += gpio-u300.o
|
||||
obj-$(CONFIG_PLAT_NOMADIK) += gpio-nomadik.o
|
||||
obj-$(CONFIG_GPIO_RDC321X) += rdc321x-gpio.o
|
||||
obj-$(CONFIG_ARCH_RK29) += gpio-rk29.o
|
||||
obj-$(CONFIG_GPIO_JANZ_TTL) += janz-ttl.o
|
||||
obj-$(CONFIG_GPIO_SX150X) += sx150x.o
|
||||
obj-$(CONFIG_GPIO_VX855) += vx855_gpio.o
|
||||
|
|
|
|||
484
drivers/gpio/gpio-rk29.c
Executable file
484
drivers/gpio/gpio-rk29.c
Executable file
|
|
@ -0,0 +1,484 @@
|
|||
/* arch/arm/mach-rk29/gpio.c
|
||||
*
|
||||
* Copyright (C) 2010 ROCKCHIP, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/rk29_iomap.h>
|
||||
#include <mach/iomux.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
#define MAX_PIN RK29_PIN6_PD7
|
||||
|
||||
#define to_rk29_gpio_bank(c) container_of(c, struct rk29_gpio_bank, chip)
|
||||
|
||||
struct rk29_gpio_bank {
|
||||
struct gpio_chip chip;
|
||||
unsigned short id;
|
||||
short irq;
|
||||
void __iomem *regbase; /* Base of register bank */
|
||||
struct clk *clk;
|
||||
u32 suspend_wakeup;
|
||||
u32 saved_wakeup;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
static struct lock_class_key gpio_lock_class;
|
||||
|
||||
static void rk29_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip);
|
||||
static void rk29_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val);
|
||||
static int rk29_gpiolib_get(struct gpio_chip *chip, unsigned offset);
|
||||
static int rk29_gpiolib_direction_output(struct gpio_chip *chip,unsigned offset, int val);
|
||||
static int rk29_gpiolib_direction_input(struct gpio_chip *chip,unsigned offset);
|
||||
static int rk29_gpiolib_pull_updown(struct gpio_chip *chip, unsigned offset, unsigned enable);
|
||||
static int rk29_gpiolib_to_irq(struct gpio_chip *chip,unsigned offset);
|
||||
|
||||
#define RK29_GPIO_BANK(ID) \
|
||||
{ \
|
||||
.chip = { \
|
||||
.label = "gpio" #ID, \
|
||||
.direction_input = rk29_gpiolib_direction_input, \
|
||||
.direction_output = rk29_gpiolib_direction_output, \
|
||||
.get = rk29_gpiolib_get, \
|
||||
.set = rk29_gpiolib_set, \
|
||||
.pull_updown = rk29_gpiolib_pull_updown, \
|
||||
.dbg_show = rk29_gpiolib_dbg_show, \
|
||||
.to_irq = rk29_gpiolib_to_irq, \
|
||||
.base = PIN_BASE + ID*NUM_GROUP, \
|
||||
.ngpio = NUM_GROUP, \
|
||||
}, \
|
||||
.id = ID, \
|
||||
.irq = IRQ_GPIO##ID, \
|
||||
.regbase = (unsigned char __iomem *) RK29_GPIO##ID##_BASE, \
|
||||
}
|
||||
|
||||
static struct rk29_gpio_bank rk29_gpio_banks[] = {
|
||||
RK29_GPIO_BANK(0),
|
||||
RK29_GPIO_BANK(1),
|
||||
RK29_GPIO_BANK(2),
|
||||
RK29_GPIO_BANK(3),
|
||||
RK29_GPIO_BANK(4),
|
||||
RK29_GPIO_BANK(5),
|
||||
RK29_GPIO_BANK(6),
|
||||
};
|
||||
|
||||
static inline void rk29_gpio_bit_op(void __iomem *regbase, unsigned int offset, u32 bit, unsigned char flag)
|
||||
{
|
||||
u32 val = __raw_readl(regbase + offset);
|
||||
if (flag)
|
||||
val |= bit;
|
||||
else
|
||||
val &= ~bit;
|
||||
__raw_writel(val, regbase + offset);
|
||||
}
|
||||
|
||||
static inline struct gpio_chip *pin_to_gpio_chip(unsigned pin)
|
||||
{
|
||||
if (pin < PIN_BASE || pin > MAX_PIN)
|
||||
return NULL;
|
||||
|
||||
pin -= PIN_BASE;
|
||||
pin /= NUM_GROUP;
|
||||
if (likely(pin < ARRAY_SIZE(rk29_gpio_banks)))
|
||||
return &(rk29_gpio_banks[pin].chip);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline unsigned gpio_to_bit(unsigned gpio)
|
||||
{
|
||||
gpio -= PIN_BASE;
|
||||
return 1u << (gpio % NUM_GROUP);
|
||||
}
|
||||
|
||||
static inline unsigned offset_to_bit(unsigned offset)
|
||||
{
|
||||
return 1u << offset;
|
||||
}
|
||||
|
||||
static void GPIOSetPinLevel(void __iomem *regbase, unsigned int bit, eGPIOPinLevel_t level)
|
||||
{
|
||||
rk29_gpio_bit_op(regbase, GPIO_SWPORT_DDR, bit, 1);
|
||||
rk29_gpio_bit_op(regbase, GPIO_SWPORT_DR, bit, level);
|
||||
}
|
||||
|
||||
static int GPIOGetPinLevel(void __iomem *regbase, unsigned int bit)
|
||||
{
|
||||
return ((__raw_readl(regbase + GPIO_EXT_PORT) & bit) != 0);
|
||||
}
|
||||
|
||||
static void GPIOSetPinDirection(void __iomem *regbase, unsigned int bit, eGPIOPinDirection_t direction)
|
||||
{
|
||||
rk29_gpio_bit_op(regbase, GPIO_SWPORT_DDR, bit, direction);
|
||||
/* Enable debounce may halt cpu on wfi, disable it by default */
|
||||
//rk29_gpio_bit_op(regbase, GPIO_DEBOUNCE, bit, 1);
|
||||
}
|
||||
|
||||
static void GPIOEnableIntr(void __iomem *regbase, unsigned int bit)
|
||||
{
|
||||
rk29_gpio_bit_op(regbase, GPIO_INTEN, bit, 1);
|
||||
}
|
||||
|
||||
static void GPIODisableIntr(void __iomem *regbase, unsigned int bit)
|
||||
{
|
||||
rk29_gpio_bit_op(regbase, GPIO_INTEN, bit, 0);
|
||||
}
|
||||
|
||||
static void GPIOAckIntr(void __iomem *regbase, unsigned int bit)
|
||||
{
|
||||
rk29_gpio_bit_op(regbase, GPIO_PORTS_EOI, bit, 1);
|
||||
}
|
||||
|
||||
static void GPIOSetIntrType(void __iomem *regbase, unsigned int bit, eGPIOIntType_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case GPIOLevelLow:
|
||||
rk29_gpio_bit_op(regbase, GPIO_INT_POLARITY, bit, 0);
|
||||
rk29_gpio_bit_op(regbase, GPIO_INTTYPE_LEVEL, bit, 0);
|
||||
break;
|
||||
case GPIOLevelHigh:
|
||||
rk29_gpio_bit_op(regbase, GPIO_INTTYPE_LEVEL, bit, 0);
|
||||
rk29_gpio_bit_op(regbase, GPIO_INT_POLARITY, bit, 1);
|
||||
break;
|
||||
case GPIOEdgelFalling:
|
||||
rk29_gpio_bit_op(regbase, GPIO_INTTYPE_LEVEL, bit, 1);
|
||||
rk29_gpio_bit_op(regbase, GPIO_INT_POLARITY, bit, 0);
|
||||
break;
|
||||
case GPIOEdgelRising:
|
||||
rk29_gpio_bit_op(regbase, GPIO_INTTYPE_LEVEL, bit, 1);
|
||||
rk29_gpio_bit_op(regbase, GPIO_INT_POLARITY, bit, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int rk29_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
struct rk29_gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
u32 bit = gpio_to_bit(irq_to_gpio(d->irq));
|
||||
eGPIOIntType_t int_type;
|
||||
unsigned long flags;
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
int_type = GPIOEdgelRising;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
int_type = GPIOEdgelFalling;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
int_type = GPIOLevelHigh;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
int_type = GPIOLevelLow;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
//设置为中断之前,必须先设置为输入状态
|
||||
GPIOSetPinDirection(bank->regbase, bit, GPIO_IN);
|
||||
GPIOSetIntrType(bank->regbase, bit, int_type);
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
|
||||
__irq_set_handler_locked(d->irq, handle_level_irq);
|
||||
else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
|
||||
__irq_set_handler_locked(d->irq, handle_edge_irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk29_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
|
||||
{
|
||||
struct rk29_gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
u32 bit = gpio_to_bit(irq_to_gpio(d->irq));
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
if (on)
|
||||
bank->suspend_wakeup |= bit;
|
||||
else
|
||||
bank->suspend_wakeup &= ~bit;
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rk29_gpio_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct rk29_gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
u32 bit = gpio_to_bit(irq_to_gpio(d->irq));
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
GPIOEnableIntr(bank->regbase, bit);
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
}
|
||||
|
||||
static void rk29_gpio_irq_mask(struct irq_data *d)
|
||||
{
|
||||
struct rk29_gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
u32 bit = gpio_to_bit(irq_to_gpio(d->irq));
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
GPIODisableIntr(bank->regbase, bit);
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
}
|
||||
|
||||
static void rk29_gpio_irq_ack(struct irq_data *d)
|
||||
{
|
||||
struct rk29_gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
u32 bit = gpio_to_bit(irq_to_gpio(d->irq));
|
||||
|
||||
GPIOAckIntr(bank->regbase, bit);
|
||||
}
|
||||
|
||||
static int rk29_gpiolib_direction_output(struct gpio_chip *chip, unsigned offset, int val)
|
||||
{
|
||||
struct rk29_gpio_bank *bank = to_rk29_gpio_bank(chip);
|
||||
u32 bit = offset_to_bit(offset);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
GPIOSetPinDirection(bank->regbase, bit, GPIO_OUT);
|
||||
GPIOSetPinLevel(bank->regbase, bit, val);
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk29_gpiolib_direction_input(struct gpio_chip *chip,unsigned offset)
|
||||
{
|
||||
struct rk29_gpio_bank *bank = to_rk29_gpio_bank(chip);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
GPIOSetPinDirection(bank->regbase, offset_to_bit(offset), GPIO_IN);
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int rk29_gpiolib_get(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
return GPIOGetPinLevel(to_rk29_gpio_bank(chip)->regbase, offset_to_bit(offset));
|
||||
}
|
||||
|
||||
static void rk29_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val)
|
||||
{
|
||||
struct rk29_gpio_bank *bank = to_rk29_gpio_bank(chip);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
GPIOSetPinLevel(bank->regbase, offset_to_bit(offset), val);
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
}
|
||||
|
||||
static int rk29_gpiolib_pull_updown(struct gpio_chip *chip, unsigned offset, unsigned enable)
|
||||
{
|
||||
struct rk29_gpio_bank *bank = to_rk29_gpio_bank(chip);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
rk29_gpio_bit_op((void *__iomem) RK29_GRF_BASE, 0x78 + bank->id * 4, offset_to_bit(offset), !enable);
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk29_gpiolib_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
return chip->base + offset;
|
||||
}
|
||||
|
||||
static void rk29_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
{
|
||||
#if 0
|
||||
int i;
|
||||
|
||||
for (i = 0; i < chip->ngpio; i++) {
|
||||
unsigned pin = chip->base + i;
|
||||
struct gpio_chip *chip = pin_to_gpioChip(pin);
|
||||
u32 bit = pin_to_bit(pin);
|
||||
const char *gpio_label;
|
||||
|
||||
if(!chip ||!bit)
|
||||
return;
|
||||
|
||||
gpio_label = gpiochip_is_requested(chip, i);
|
||||
if (gpio_label) {
|
||||
seq_printf(s, "[%s] GPIO%s%d: ",
|
||||
gpio_label, chip->label, i);
|
||||
|
||||
if (!chip || !bit)
|
||||
{
|
||||
seq_printf(s, "!chip || !bit\t");
|
||||
return;
|
||||
}
|
||||
|
||||
GPIOSetPinDirection(chip,bit,GPIO_IN);
|
||||
seq_printf(s, "pin=%d,level=%d\t", pin,GPIOGetPinLevel(chip,bit));
|
||||
seq_printf(s, "\t");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void rk29_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct rk29_gpio_bank *bank = irq_get_handler_data(irq);
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
unsigned gpio_irq;
|
||||
u32 isr, ilr;
|
||||
unsigned pin;
|
||||
unsigned unmasked = 0;
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
|
||||
isr = __raw_readl(bank->regbase + GPIO_INT_STATUS);
|
||||
ilr = __raw_readl(bank->regbase + GPIO_INTTYPE_LEVEL);
|
||||
|
||||
gpio_irq = gpio_to_irq(bank->chip.base);
|
||||
|
||||
while (isr) {
|
||||
pin = fls(isr) - 1;
|
||||
/* if gpio is edge triggered, clear condition
|
||||
* before executing the hander so that we don't
|
||||
* miss edges
|
||||
*/
|
||||
if (ilr & (1 << pin)) {
|
||||
unmasked = 1;
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
generic_handle_irq(gpio_irq + pin);
|
||||
isr &= ~(1 << pin);
|
||||
}
|
||||
|
||||
if (!unmasked)
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
static struct irq_chip rk29_gpio_irq_chip = {
|
||||
.name = "GPIO",
|
||||
.irq_ack = rk29_gpio_irq_ack,
|
||||
.irq_disable = rk29_gpio_irq_mask,
|
||||
.irq_mask = rk29_gpio_irq_mask,
|
||||
.irq_unmask = rk29_gpio_irq_unmask,
|
||||
.irq_set_type = rk29_gpio_irq_set_type,
|
||||
.irq_set_wake = rk29_gpio_irq_set_wake,
|
||||
};
|
||||
|
||||
void __init rk29_gpio_init(void)
|
||||
{
|
||||
unsigned int i, j, pin;
|
||||
struct rk29_gpio_bank *bank;
|
||||
|
||||
bank = rk29_gpio_banks;
|
||||
pin = PIN_BASE;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rk29_gpio_banks); i++, bank++, pin += 32) {
|
||||
spin_lock_init(&bank->lock);
|
||||
bank->clk = clk_get(NULL, bank->chip.label);
|
||||
clk_enable(bank->clk);
|
||||
gpiochip_add(&bank->chip);
|
||||
|
||||
__raw_writel(0, bank->regbase + GPIO_INTEN);
|
||||
for (j = 0; j < 32; j++) {
|
||||
unsigned int irq = gpio_to_irq(pin + j);
|
||||
irq_set_lockdep_class(irq, &gpio_lock_class);
|
||||
irq_set_chip_data(irq, bank);
|
||||
irq_set_chip_and_handler(irq, &rk29_gpio_irq_chip, handle_level_irq);
|
||||
set_irq_flags(irq, IRQF_VALID);
|
||||
}
|
||||
|
||||
irq_set_handler_data(bank->irq, bank);
|
||||
irq_set_chained_handler(bank->irq, rk29_gpio_irq_handler);
|
||||
}
|
||||
printk("%s: %d gpio irqs in %d banks\n", __func__, pin - PIN_BASE, ARRAY_SIZE(rk29_gpio_banks));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
__weak void rk29_setgpio_suspend_board(void)
|
||||
{
|
||||
}
|
||||
|
||||
__weak void rk29_setgpio_resume_board(void)
|
||||
{
|
||||
}
|
||||
|
||||
static int rk29_gpio_suspend(void)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
rk29_setgpio_suspend_board();
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rk29_gpio_banks); i++) {
|
||||
struct rk29_gpio_bank *bank = &rk29_gpio_banks[i];
|
||||
|
||||
bank->saved_wakeup = __raw_readl(bank->regbase + GPIO_INTEN);
|
||||
__raw_writel(bank->suspend_wakeup, bank->regbase + GPIO_INTEN);
|
||||
|
||||
if (!bank->suspend_wakeup)
|
||||
clk_disable(bank->clk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rk29_gpio_resume(void)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rk29_gpio_banks); i++) {
|
||||
struct rk29_gpio_bank *bank = &rk29_gpio_banks[i];
|
||||
u32 isr;
|
||||
|
||||
if (!bank->suspend_wakeup)
|
||||
clk_enable(bank->clk);
|
||||
|
||||
/* keep enable for resume irq */
|
||||
isr = __raw_readl(bank->regbase + GPIO_INT_STATUS);
|
||||
__raw_writel(bank->saved_wakeup | (bank->suspend_wakeup & isr), bank->regbase + GPIO_INTEN);
|
||||
}
|
||||
|
||||
rk29_setgpio_resume_board();
|
||||
}
|
||||
|
||||
static struct syscore_ops rk29_gpio_syscore_ops = {
|
||||
.suspend = rk29_gpio_suspend,
|
||||
.resume = rk29_gpio_resume,
|
||||
};
|
||||
|
||||
static int __init rk29_gpio_sysinit(void)
|
||||
{
|
||||
register_syscore_ops(&rk29_gpio_syscore_ops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_initcall(rk29_gpio_sysinit);
|
||||
#endif
|
||||
|
|
@ -1429,6 +1429,8 @@ int gpio_direction_output(unsigned gpio, int value)
|
|||
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
|
||||
if (value !=0 && value !=1)
|
||||
goto fail;
|
||||
if (!gpio_is_valid(gpio))
|
||||
goto fail;
|
||||
chip = desc->chip;
|
||||
|
|
@ -1475,6 +1477,67 @@ fail:
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(gpio_direction_output);
|
||||
|
||||
/*
|
||||
gpio pull up or pull down
|
||||
value = 0, normal
|
||||
value = 1, pull up
|
||||
value = 2, pull down
|
||||
*/
|
||||
int gpio_pull_updown(unsigned gpio, unsigned value)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct gpio_chip *chip;
|
||||
struct gpio_desc *desc = &gpio_desc[gpio];
|
||||
int status = -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
|
||||
if (value >3)
|
||||
goto fail;
|
||||
if (!gpio_is_valid(gpio))
|
||||
goto fail;
|
||||
chip = desc->chip;
|
||||
if (!chip || !chip->get || !chip->pull_updown)
|
||||
goto fail;
|
||||
gpio -= chip->base;
|
||||
if (gpio >= chip->ngpio)
|
||||
goto fail;
|
||||
status = gpio_ensure_requested(desc, gpio);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
/* now we know the gpio is valid and chip won't vanish */
|
||||
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
|
||||
might_sleep_if(extra_checks && chip->can_sleep);
|
||||
|
||||
if (status) {
|
||||
status = chip->request(chip, gpio);
|
||||
if (status < 0) {
|
||||
pr_debug("GPIO-%d: chip request fail, %d\n",
|
||||
chip->base + gpio, status);
|
||||
/* and it's not available to anyone else ...
|
||||
* gpio_request() is the fully clean solution.
|
||||
*/
|
||||
goto lose;
|
||||
}
|
||||
}
|
||||
status = chip->pull_updown(chip, gpio,value);
|
||||
if (status == 0)
|
||||
clear_bit(FLAG_IS_OUT, &desc->flags);
|
||||
|
||||
lose:
|
||||
return status;
|
||||
fail:
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
if (status)
|
||||
pr_debug("%s: gpio-%d status %d\n",
|
||||
__func__, gpio, status);
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gpio_pull_updown);
|
||||
|
||||
/**
|
||||
* gpio_set_debounce - sets @debounce time for a @gpio
|
||||
* @gpio: the gpio to set debounce time
|
||||
|
|
@ -1555,6 +1618,8 @@ int __gpio_get_value(unsigned gpio)
|
|||
struct gpio_chip *chip;
|
||||
int value;
|
||||
|
||||
if (!gpio_is_valid(gpio))
|
||||
return -1;
|
||||
chip = gpio_to_chip(gpio);
|
||||
WARN_ON(chip->can_sleep);
|
||||
value = chip->get ? chip->get(chip, gpio - chip->base) : 0;
|
||||
|
|
@ -1576,6 +1641,10 @@ void __gpio_set_value(unsigned gpio, int value)
|
|||
{
|
||||
struct gpio_chip *chip;
|
||||
|
||||
if(value !=0 && value !=1)
|
||||
return;
|
||||
if (!gpio_is_valid(gpio))
|
||||
return;
|
||||
chip = gpio_to_chip(gpio);
|
||||
WARN_ON(chip->can_sleep);
|
||||
trace_gpio_value(gpio, 0, value);
|
||||
|
|
@ -1614,9 +1683,13 @@ EXPORT_SYMBOL_GPL(__gpio_cansleep);
|
|||
int __gpio_to_irq(unsigned gpio)
|
||||
{
|
||||
struct gpio_chip *chip;
|
||||
|
||||
|
||||
if (!gpio_is_valid(gpio))
|
||||
return -1;
|
||||
|
||||
chip = gpio_to_chip(gpio);
|
||||
return chip->to_irq ? chip->to_irq(chip, gpio - chip->base) : -ENXIO;
|
||||
|
||||
return chip->to_irq ? chip->to_irq(chip, gpio - chip->base) : -1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__gpio_to_irq);
|
||||
|
||||
|
|
|
|||
|
|
@ -1426,8 +1426,9 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
|||
}
|
||||
}
|
||||
EXPORT_SYMBOL(i2c_transfer);
|
||||
|
||||
#if defined (CONFIG_I2C_RK2818) || defined(CONFIG_I2C_RK29)
|
||||
int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
|
||||
int i2c_master_send(const struct i2c_client *client, const char *buf, int count)
|
||||
{
|
||||
int ret;
|
||||
struct i2c_adapter *adap=client->adapter;
|
||||
|
|
@ -1445,7 +1446,7 @@ int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
|
|||
}
|
||||
EXPORT_SYMBOL(i2c_master_send);
|
||||
|
||||
int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
|
||||
int i2c_master_recv(const struct i2c_client *client, char *buf, int count)
|
||||
{
|
||||
struct i2c_adapter *adap=client->adapter;
|
||||
struct i2c_msg msg;
|
||||
|
|
@ -1464,7 +1465,7 @@ int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
|
|||
}
|
||||
EXPORT_SYMBOL(i2c_master_recv);
|
||||
|
||||
int i2c_master_normal_send(struct i2c_client *client,const char *buf ,int count, int scl_rate)
|
||||
int i2c_master_normal_send(const struct i2c_client *client, const char *buf, int count, int scl_rate)
|
||||
{
|
||||
int ret;
|
||||
struct i2c_adapter *adap=client->adapter;
|
||||
|
|
@ -1482,7 +1483,7 @@ int i2c_master_normal_send(struct i2c_client *client,const char *buf ,int count,
|
|||
}
|
||||
EXPORT_SYMBOL(i2c_master_normal_send);
|
||||
|
||||
int i2c_master_normal_recv(struct i2c_client *client, char *buf ,int count, int scl_rate)
|
||||
int i2c_master_normal_recv(const struct i2c_client *client, char *buf, int count, int scl_rate)
|
||||
{
|
||||
struct i2c_adapter *adap=client->adapter;
|
||||
struct i2c_msg msg;
|
||||
|
|
@ -1501,7 +1502,7 @@ int i2c_master_normal_recv(struct i2c_client *client, char *buf ,int count, int
|
|||
}
|
||||
EXPORT_SYMBOL(i2c_master_normal_recv);
|
||||
|
||||
int i2c_master_reg8_send(struct i2c_client *client, const char reg, const char *buf, int count, int scl_rate)
|
||||
int i2c_master_reg8_send(const struct i2c_client *client, const char reg, const char *buf, int count, int scl_rate)
|
||||
{
|
||||
struct i2c_adapter *adap=client->adapter;
|
||||
struct i2c_msg msg;
|
||||
|
|
@ -1526,7 +1527,7 @@ int i2c_master_reg8_send(struct i2c_client *client, const char reg, const char *
|
|||
}
|
||||
EXPORT_SYMBOL(i2c_master_reg8_send);
|
||||
|
||||
int i2c_master_reg8_recv(struct i2c_client *client, const char reg, char *buf, int count, int scl_rate)
|
||||
int i2c_master_reg8_recv(const struct i2c_client *client, const char reg, char *buf, int count, int scl_rate)
|
||||
{
|
||||
struct i2c_adapter *adap=client->adapter;
|
||||
struct i2c_msg msgs[2];
|
||||
|
|
@ -1554,13 +1555,13 @@ int i2c_master_reg8_recv(struct i2c_client *client, const char reg, char *buf, i
|
|||
|
||||
EXPORT_SYMBOL(i2c_master_reg8_recv);
|
||||
|
||||
int i2c_master_reg8_direct_send(struct i2c_client *client, const char reg, const char *buf, int count, int scl_rate)
|
||||
int i2c_master_reg8_direct_send(const struct i2c_client *client, const char reg, const char *buf, int count, int scl_rate)
|
||||
{
|
||||
return i2c_master_reg8_send(client, reg, buf, count, scl_rate);
|
||||
}
|
||||
EXPORT_SYMBOL(i2c_master_reg8_direct_send);
|
||||
|
||||
int i2c_master_reg8_direct_recv(struct i2c_client *client, const char reg, char *buf, int count, int scl_rate)
|
||||
int i2c_master_reg8_direct_recv(const struct i2c_client *client, const char reg, char *buf, int count, int scl_rate)
|
||||
{
|
||||
struct i2c_adapter *adap=client->adapter;
|
||||
struct i2c_msg msg;
|
||||
|
|
@ -1581,7 +1582,7 @@ int i2c_master_reg8_direct_recv(struct i2c_client *client, const char reg, char
|
|||
}
|
||||
EXPORT_SYMBOL(i2c_master_reg8_direct_recv);
|
||||
|
||||
int i2c_master_reg16_send(struct i2c_client *client, const short regs, const short *buf, int count, int scl_rate)
|
||||
int i2c_master_reg16_send(const struct i2c_client *client, const short regs, const short *buf, int count, int scl_rate)
|
||||
{
|
||||
struct i2c_adapter *adap=client->adapter;
|
||||
struct i2c_msg msg;
|
||||
|
|
@ -1605,7 +1606,7 @@ int i2c_master_reg16_send(struct i2c_client *client, const short regs, const sho
|
|||
}
|
||||
EXPORT_SYMBOL(i2c_master_reg16_send);
|
||||
|
||||
int i2c_master_reg16_recv(struct i2c_client *client, const short regs, short *buf, int count, int scl_rate)
|
||||
int i2c_master_reg16_recv(const struct i2c_client *client, const short regs, short *buf, int count, int scl_rate)
|
||||
{
|
||||
struct i2c_adapter *adap=client->adapter;
|
||||
struct i2c_msg msgs[2];
|
||||
|
|
|
|||
|
|
@ -22,6 +22,11 @@ obj-$(CONFIG_INPUT_JOYSTICK) += joystick/
|
|||
obj-$(CONFIG_INPUT_TABLET) += tablet/
|
||||
obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/
|
||||
obj-$(CONFIG_INPUT_MISC) += misc/
|
||||
obj-$(CONFIG_G_SENSOR_DEVICE) += gsensor/
|
||||
obj-$(CONFIG_GYRO_SENSOR_DEVICE) += gyroscope/
|
||||
obj-$(CONFIG_INPUT_JOGBALL) += jogball/
|
||||
obj-$(CONFIG_LIGHT_SENSOR_DEVICE) += lightsensor/
|
||||
obj-$(CONFIG_MAG_SENSORS) += magnetometer/
|
||||
|
||||
obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o
|
||||
obj-$(CONFIG_INPUT_KEYRESET) += keyreset.o
|
||||
|
|
|
|||
|
|
@ -12,6 +12,25 @@ menuconfig INPUT_KEYBOARD
|
|||
|
||||
if INPUT_KEYBOARD
|
||||
|
||||
config KEYS_RK29
|
||||
tristate "rk29 keyboard"
|
||||
depends on ARCH_RK29
|
||||
default y
|
||||
help
|
||||
rk29 keyboard drivers(gpio and adc)
|
||||
|
||||
config KEYS_RK29_NEWTON
|
||||
tristate "rk29 newton keyboard"
|
||||
depends on ARCH_RK29
|
||||
help
|
||||
rk29 newton keyboard drivers(gpio and adc)
|
||||
|
||||
config SYNAPTICS_SO340010
|
||||
tristate "Synaptics So340010 TouchPad KEY"
|
||||
depends on I2C
|
||||
help
|
||||
Synaptics So340010 Touch Key (I2C) driver
|
||||
|
||||
config KEYBOARD_ADP5520
|
||||
tristate "Keypad Support for ADP5520 PMIC"
|
||||
depends on PMIC_ADP5520
|
||||
|
|
@ -203,6 +222,21 @@ config KEYBOARD_GPIO_POLLED
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called gpio_keys_polled.
|
||||
|
||||
config KEYBOARD_WM831X_GPIO
|
||||
tristate "WM831X_GPIO Buttons"
|
||||
depends on GENERIC_GPIO
|
||||
help
|
||||
This driver implements support for buttons connected
|
||||
to GPIO pins of various CPUs (and some other chips).
|
||||
|
||||
Say Y here if your device has buttons connected
|
||||
directly to such GPIO pins. Your board-specific
|
||||
setup logic must also provide a platform device,
|
||||
with configuration data saying which GPIOs are used.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called wm831x_gpio_keys.
|
||||
|
||||
config KEYBOARD_TCA6416
|
||||
tristate "TCA6416/TCA6408A Keypad Support"
|
||||
depends on I2C
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
# Each configuration option enables a list of files.
|
||||
|
||||
obj-$(CONFIG_KEYS_RK29) += rk29_keys.o
|
||||
obj-$(CONFIG_KEYS_RK29_NEWTON) += rk29_newton_keys.o
|
||||
obj-$(CONFIG_KEYBOARD_ADP5520) += adp5520-keys.o
|
||||
obj-$(CONFIG_KEYBOARD_ADP5588) += adp5588-keys.o
|
||||
obj-$(CONFIG_KEYBOARD_ADP5589) += adp5589-keys.o
|
||||
|
|
@ -15,6 +17,7 @@ obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o
|
|||
obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o
|
||||
obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
|
||||
obj-$(CONFIG_KEYBOARD_GPIO_POLLED) += gpio_keys_polled.o
|
||||
obj-$(CONFIG_KEYBOARD_WM831X_GPIO) += wm831x_gpio_keys.o
|
||||
obj-$(CONFIG_KEYBOARD_TCA6416) += tca6416-keypad.o
|
||||
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
|
||||
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
|
||||
|
|
@ -51,3 +54,4 @@ obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o
|
|||
obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o
|
||||
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
|
||||
obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o
|
||||
obj-$(CONFIG_SYNAPTICS_SO340010) += synaptics_so340010.o
|
||||
|
|
|
|||
|
|
@ -271,16 +271,6 @@ config INPUT_CM109
|
|||
To compile this driver as a module, choose M here: the module will be
|
||||
called cm109.
|
||||
|
||||
config INPUT_TPS65910_PWRBUTTON
|
||||
tristate "TPS65910 Power button Driver"
|
||||
depends on TPS65910_CORE
|
||||
help
|
||||
Say Y here if you want to enable power key reporting via the
|
||||
TPS65910 family of chips.
|
||||
|
||||
To compile this driver as a module, choose M here. The module will
|
||||
be called tps65910_pwrbutton.
|
||||
|
||||
config INPUT_TWL4030_PWRBUTTON
|
||||
tristate "TWL4030 Power button Driver"
|
||||
depends on TWL4030_CORE
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
|
|||
obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o
|
||||
obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
|
||||
obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
|
||||
obj-$(CONFIG_INPUT_TPS65910_PWRBUTTON) += tps65910-pwrbutton.o
|
||||
obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o
|
||||
obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o
|
||||
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
|
||||
|
|
@ -50,3 +49,4 @@ obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
|
|||
obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
|
||||
obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o
|
||||
obj-$(CONFIG_INPUT_YEALINK) += yealink.o
|
||||
|
||||
|
|
|
|||
|
|
@ -1,148 +0,0 @@
|
|||
/**
|
||||
* tps65910-pwrbutton.c - TPS65910 Power Button Input Driver
|
||||
*
|
||||
* Copyright (C) 2010 Mistral Solutions Pvt Ltd <www.mistralsolutions.com>
|
||||
*
|
||||
* Based on twl4030-pwrbutton.c
|
||||
*
|
||||
* Written by Srinath.R <srinath@mistralsolutions.com>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License. See the file "COPYING" in the main directory of this
|
||||
* archive for more details.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c/tps65910.h>
|
||||
|
||||
#define TPS65910_PWR_PWRON_IRQ (1 << 2)
|
||||
|
||||
|
||||
static irqreturn_t powerbutton_irq(int irq, void *_pwr)
|
||||
{
|
||||
struct input_dev *pwr = _pwr;
|
||||
int err;
|
||||
u8 value;
|
||||
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
/* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
|
||||
* we don't want and can't tolerate since this is a threaded
|
||||
* IRQ and can sleep due to the i2c reads it has to issue.
|
||||
* Although it might be friendlier not to borrow this thread
|
||||
* context...
|
||||
*/
|
||||
local_irq_enable();
|
||||
#endif
|
||||
err = tps65910_i2c_read_u8(TPS65910_I2C_ID0, &value,
|
||||
TPS65910_REG_INT_STS);
|
||||
if (!err && (value & TPS65910_PWR_PWRON_IRQ)) {
|
||||
|
||||
if (value & TPS65910_PWR_PWRON_IRQ) {
|
||||
|
||||
input_report_key(pwr, KEY_POWER,
|
||||
TPS65910_PWR_PWRON_IRQ);
|
||||
input_sync(pwr);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
} else {
|
||||
dev_err(pwr->dev.parent, "tps65910: i2c error %d while reading"
|
||||
" TPS65910_REG_INT_STS register\n", err);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int __devinit tps65910_pwrbutton_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct input_dev *pwr;
|
||||
int irq = platform_get_irq(pdev, 0);
|
||||
int err;
|
||||
|
||||
pwr = input_allocate_device();
|
||||
if (!pwr) {
|
||||
dev_dbg(&pdev->dev, "Can't allocate power button\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pwr->evbit[0] = BIT_MASK(EV_KEY);
|
||||
pwr->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
|
||||
pwr->name = "tps65910_pwrbutton";
|
||||
pwr->phys = "tps65910_pwrbutton/input0";
|
||||
pwr->dev.parent = &pdev->dev;
|
||||
|
||||
err = request_irq(irq, powerbutton_irq,
|
||||
(IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
|
||||
IRQF_SHARED), "tps65910_pwrbutton", pwr);
|
||||
if (err < 0) {
|
||||
dev_dbg(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err);
|
||||
goto free_input_dev;
|
||||
}
|
||||
|
||||
err = input_register_device(pwr);
|
||||
if (err) {
|
||||
dev_dbg(&pdev->dev, "Can't register power button: %d\n", err);
|
||||
goto free_irq;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, pwr);
|
||||
|
||||
return 0;
|
||||
|
||||
free_irq:
|
||||
free_irq(irq, NULL);
|
||||
free_input_dev:
|
||||
input_free_device(pwr);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit tps65910_pwrbutton_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct input_dev *pwr = platform_get_drvdata(pdev);
|
||||
int irq = platform_get_irq(pdev, 0);
|
||||
|
||||
free_irq(irq, pwr);
|
||||
input_unregister_device(pwr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct platform_driver tps65910_pwrbutton_driver = {
|
||||
.probe = tps65910_pwrbutton_probe,
|
||||
.remove = __devexit_p(tps65910_pwrbutton_remove),
|
||||
.driver = {
|
||||
.name = "tps65910_pwrbutton",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init tps65910_pwrbutton_init(void)
|
||||
{
|
||||
return platform_driver_register(&tps65910_pwrbutton_driver);
|
||||
}
|
||||
module_init(tps65910_pwrbutton_init);
|
||||
|
||||
static void __exit tps65910_pwrbutton_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&tps65910_pwrbutton_driver);
|
||||
}
|
||||
module_exit(tps65910_pwrbutton_exit);
|
||||
|
||||
MODULE_ALIAS("platform:tps65910_pwrbutton");
|
||||
MODULE_DESCRIPTION("TPS65910 Power Button");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Srinath R <srinath@mistralsolutions.com>");
|
||||
|
||||
|
|
@ -11,6 +11,58 @@ menuconfig INPUT_TOUCHSCREEN
|
|||
|
||||
if INPUT_TOUCHSCREEN
|
||||
|
||||
config TOUCHSCREEN_XPT2046_SPI
|
||||
tristate "XPT2046 based touchscreens:SPI Interface"
|
||||
depends on SPIM_RK29
|
||||
|
||||
config TOUCHSCREEN_XPT2046_NORMAL_SPI
|
||||
tristate "normal mode"
|
||||
depends on TOUCHSCREEN_XPT2046_SPI
|
||||
|
||||
config TOUCHSCREEN_480X800
|
||||
tristate "480X800 resolution"
|
||||
depends on TOUCHSCREEN_XPT2046_NORMAL_SPI
|
||||
|
||||
config TOUCHSCREEN_800X480
|
||||
tristate "800X480 resolution"
|
||||
depends on TOUCHSCREEN_XPT2046_NORMAL_SPI
|
||||
|
||||
config TOUCHSCREEN_320X480
|
||||
tristate "320X480 resolution"
|
||||
depends on TOUCHSCREEN_XPT2046_NORMAL_SPI
|
||||
|
||||
config TOUCHSCREEN_XPT2046_TSLIB_SPI
|
||||
tristate "tslib mode"
|
||||
depends on TOUCHSCREEN_XPT2046_SPI
|
||||
|
||||
config TOUCHSCREEN_480X800
|
||||
tristate "480X800 resolution"
|
||||
depends on TOUCHSCREEN_XPT2046_TSLIB_SPI
|
||||
|
||||
config TOUCHSCREEN_800X480
|
||||
tristate "800X480 resolution"
|
||||
depends on TOUCHSCREEN_XPT2046_TSLIB_SPI
|
||||
|
||||
config TOUCHSCREEN_320X480
|
||||
tristate "320X480 resolution"
|
||||
depends on TOUCHSCREEN_XPT2046_TSLIB_SPI
|
||||
|
||||
config TOUCHSCREEN_XPT2046_CBN_SPI
|
||||
tristate "calibration mode"
|
||||
depends on TOUCHSCREEN_XPT2046_SPI
|
||||
|
||||
config TOUCHSCREEN_480X800
|
||||
tristate "480X800 resolution"
|
||||
depends on TOUCHSCREEN_XPT2046_CBN_SPI
|
||||
|
||||
config TOUCHSCREEN_800X480
|
||||
tristate "800X480 resolution"
|
||||
depends on TOUCHSCREEN_XPT2046_CBN_SPI
|
||||
|
||||
config TOUCHSCREEN_320X480
|
||||
tristate "320X480 resolution"
|
||||
depends on TOUCHSCREEN_XPT2046_CBN_SPI
|
||||
|
||||
config TOUCHSCREEN_88PM860X
|
||||
tristate "Marvell 88PM860x touchscreen"
|
||||
depends on MFD_88PM860X
|
||||
|
|
@ -55,6 +107,28 @@ config TOUCHSCREEN_AD7877
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called ad7877.
|
||||
|
||||
config TOUCHSCREEN_ILI2102_IIC
|
||||
tristate "ili2102 based touchscreens: IIC Interface"
|
||||
help
|
||||
Say Y here if you have a touchscreen interface using the
|
||||
hx8520 controller, and your board-specific initialization
|
||||
code includes that in its table of IIC devices.
|
||||
|
||||
If unsure, say N (but it's safe to say "Y").
|
||||
|
||||
config RK28_I2C_TS_NTP070
|
||||
tristate "NTP070 based touchscreens: NTP070 Interface"
|
||||
depends on I2C_RK2818
|
||||
|
||||
config TOUCHSCREEN_IT7250
|
||||
tristate "IT7250 based touchscreens: IT7250 Interface"
|
||||
help
|
||||
Say Y here if you have a touchscreen interface using the
|
||||
xpt2046 controller, and your board-specific initialization
|
||||
code includes that in its table of SPI devices.
|
||||
|
||||
If unsure, say N (but it's safe to say "Y").
|
||||
|
||||
config TOUCHSCREEN_AD7879
|
||||
tristate "Analog Devices AD7879-1/AD7889-1 touchscreen interface"
|
||||
help
|
||||
|
|
@ -732,4 +806,199 @@ config TOUCHSCREEN_TPS6507X
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called tps6507x_ts.
|
||||
|
||||
config HANNSTAR_P1003
|
||||
tristate "Hannstar P1003 touchscreen"
|
||||
depends on I2C2_RK29
|
||||
help
|
||||
RK29 hannstar touch
|
||||
|
||||
config HANNSTAR_MAX_X
|
||||
int "hannstar touch x max"
|
||||
depends on HANNSTAR_P1003
|
||||
default 1087
|
||||
help
|
||||
RK29 hannstar touch max X size
|
||||
|
||||
config HANNSTAR_MAX_Y
|
||||
int "hannstar touch Y max"
|
||||
depends on HANNSTAR_P1003
|
||||
default 800
|
||||
help
|
||||
RK29 hannstar touch max Y size
|
||||
|
||||
config HANNSTAR_DEBUG
|
||||
bool "hannstar debug"
|
||||
depends on HANNSTAR_P1003
|
||||
default n
|
||||
help
|
||||
RK29 hannstar touch debug
|
||||
|
||||
config ATMEL_MXT224
|
||||
tristate "Atmel mXT224 touchscreen"
|
||||
depends on I2C2_RK29
|
||||
help
|
||||
RK29 Atmel_mXT224 touch
|
||||
|
||||
config MXT224_MAX_X
|
||||
int "atmel_mxt224 touch X max"
|
||||
depends on ATMEL_MXT224
|
||||
default 4095
|
||||
help
|
||||
RK29 atmel_mxt224 touch max X size
|
||||
|
||||
config MXT224_MAX_Y
|
||||
int "atmel_mxt224 touch Y max"
|
||||
depends on ATMEL_MXT224
|
||||
default 4095
|
||||
help
|
||||
RK29 atmel_mxt224 touch max Y size
|
||||
|
||||
config SINTEK_3FA16
|
||||
tristate "Sintek 3FA16 touchscreen"
|
||||
depends on I2C2_RK29
|
||||
help
|
||||
RK29 Sintek touch
|
||||
|
||||
config HANNSTAR_MAX_X
|
||||
int "Sintek touch x max"
|
||||
depends on SINTEK_3FA16
|
||||
default 1024
|
||||
help
|
||||
RK29 hannstar touch max X size
|
||||
|
||||
config HANNSTAR_MAX_Y
|
||||
int "Sintek touch Y max"
|
||||
depends on SINTEK_3FA16
|
||||
default 600
|
||||
help
|
||||
RK29 hannstar touch max Y size
|
||||
|
||||
config HANNSTAR_DEBUG
|
||||
bool "Sintek debug"
|
||||
depends on SINTEK_3FA16
|
||||
default n
|
||||
help
|
||||
RK29 hannstar touch debug
|
||||
|
||||
config EETI_EGALAX
|
||||
tristate "EETI_EGALAX touchscreen panel support"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here to enable support for I2C connected EETI touch panels.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called eeti_egalax_ts.
|
||||
|
||||
config EETI_EGALAX_MAX_X
|
||||
int "EETI_EGALAX_MAX_X"
|
||||
depends on EETI_EGALAX
|
||||
default 2047
|
||||
help
|
||||
RK29 EETI_EGALAX touch max X size
|
||||
|
||||
config EETI_EGALAX_MAX_Y
|
||||
int "EETI_EGALAX_MAX_Y"
|
||||
depends on EETI_EGALAX
|
||||
default 2047
|
||||
help
|
||||
RK29 EETI_EGALAX touch max Y size
|
||||
|
||||
config EETI_EGALAX_DEBUG
|
||||
bool "EETI_EGALAX debug"
|
||||
depends on EETI_EGALAX
|
||||
default n
|
||||
help
|
||||
RK29 EETI_EGALAX touch debug
|
||||
|
||||
config TOUCHSCREEN_IT7260
|
||||
tristate "IT7260 based touchscreens: IT7260 Interface"
|
||||
depends on I2C2_RK29
|
||||
help
|
||||
Say Y here if you have a touchscreen interface using the
|
||||
it7260 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").
|
||||
|
||||
config TOUCHSCREEN_IT7260_I2C
|
||||
tristate "IT7260 based touchscreens: IT7260 I2C Interface"
|
||||
depends on I2C_RK29
|
||||
help
|
||||
Say Y here if you have a touchscreen interface using the
|
||||
IT7260 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").
|
||||
|
||||
config TOUCHSCREEN_NAS
|
||||
tristate "NAS based touchscreens: NAS Interface"
|
||||
depends on I2C2_RK29
|
||||
help
|
||||
Say Y here if you have a touchscreen interface using the
|
||||
nas 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").
|
||||
|
||||
config LAIBAO_TS
|
||||
tristate "LAIBAO touchscreen"
|
||||
depends on I2C2_RK29
|
||||
help
|
||||
RK29 LAIBAO touchscreen
|
||||
|
||||
config TOUCHSCREEN_GT801_IIC
|
||||
tristate "GT801_IIC based touchscreens"
|
||||
depends on I2C2_RK29
|
||||
|
||||
config TOUCHSCREEN_GT818_IIC
|
||||
tristate "GT818_IIC based touchscreens"
|
||||
depends on I2C2_RK29
|
||||
|
||||
config D70_L3188A
|
||||
tristate "D70-L3188A based touchscreens"
|
||||
depends on I2C2_RK29
|
||||
|
||||
config TOUCHSCREEN_GT819
|
||||
tristate "GT819 based touchscreens"
|
||||
depends on I2C2_RK29
|
||||
|
||||
config TOUCHSCREEN_FT5406
|
||||
tristate "FT5406 based touchscreens: FT5406 Interface"
|
||||
depends on I2C2_RK29
|
||||
help
|
||||
say Y here if you have a touchscreen interface using the FT5406
|
||||
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").
|
||||
|
||||
config ATMEL_MXT1386
|
||||
tristate "ATMEL_MXT1386 touchscreen panel support"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here to enable support for I2C connected ATMEL_MXT1386 touch panels.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called atmel_mxt1386_ts.
|
||||
|
||||
config ATMEL_MXT1386_MAX_X
|
||||
int "ATMEL_MXT1386_MAX_X"
|
||||
depends on ATMEL_MXT1386
|
||||
default 4095
|
||||
help
|
||||
RK29 ATMEL_MXT1386 touch max X size
|
||||
|
||||
config ATMEL_MXT1386_MAX_Y
|
||||
int "ATMEL_MXT1386_MAX_Y"
|
||||
depends on ATMEL_MXT1386
|
||||
default 4095
|
||||
help
|
||||
RK29 ATMEL_MXT1386 touch max Y size
|
||||
|
||||
config ATMEL_MXT1386_DEBUG
|
||||
bool "ATMEL_MXT1386 debug"
|
||||
depends on ATMEL_MXT1386
|
||||
default n
|
||||
help
|
||||
RK29 ATMEL_MXT1386 touch debug
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -74,9 +74,14 @@ obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/
|
|||
obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o
|
||||
obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
|
||||
obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o
|
||||
obj-$(CONFIG_SOC_CAMERA_MT9M112) += mt9m112.o
|
||||
obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o
|
||||
obj-$(CONFIG_SOC_CAMERA_MT9T111) += mt9t111.o
|
||||
obj-$(CONFIG_SOC_CAMERA_MT9T112) += mt9t112.o
|
||||
obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o
|
||||
obj-$(CONFIG_SOC_CAMERA_MT9P111) += mt9p111.o
|
||||
obj-$(CONFIG_SOC_CAMERA_MT9D112) += mt9d112.o
|
||||
obj-$(CONFIG_SOC_CAMERA_MT9D113) += mt9d113.o
|
||||
obj-$(CONFIG_SOC_CAMERA_OV2640) += ov2640.o
|
||||
obj-$(CONFIG_SOC_CAMERA_OV6650) += ov6650.o
|
||||
obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o
|
||||
|
|
@ -84,7 +89,25 @@ obj-$(CONFIG_SOC_CAMERA_OV9640) += ov9640.o
|
|||
obj-$(CONFIG_SOC_CAMERA_OV9740) += ov9740.o
|
||||
obj-$(CONFIG_SOC_CAMERA_RJ54N1) += rj54n1cb0c.o
|
||||
obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o
|
||||
|
||||
obj-$(CONFIG_SOC_CAMERA_OV7675) += ov7675.o
|
||||
obj-$(CONFIG_SOC_CAMERA_OV2655) += ov2655.o
|
||||
obj-$(CONFIG_SOC_CAMERA_OV2659) += ov2659.o
|
||||
obj-$(CONFIG_SOC_CAMERA_OV9650) += ov9650.o
|
||||
obj-$(CONFIG_SOC_CAMERA_OV2640) += ov2640.o
|
||||
obj-$(CONFIG_SOC_CAMERA_OV3640) += ov3640.o
|
||||
obj-$(CONFIG_SOC_CAMERA_OV5640) += ov5640.o
|
||||
obj-$(CONFIG_SOC_CAMERA_OV5642) += ov5642.o
|
||||
obj-$(CONFIG_SOC_CAMERA_S5K6AA) += s5k6aa.o
|
||||
obj-$(CONFIG_SOC_CAMERA_GT2005) += gt2005.o
|
||||
obj-$(CONFIG_SOC_CAMERA_GC0307) += gc0307.o
|
||||
obj-$(CONFIG_SOC_CAMERA_GC0308) += gc0308.o
|
||||
obj-$(CONFIG_SOC_CAMERA_GC0309) += gc0309.o
|
||||
obj-$(CONFIG_SOC_CAMERA_GC2015) += gc2015.o
|
||||
obj-$(CONFIG_SOC_CAMERA_SIV120B) += siv120b.o
|
||||
obj-$(CONFIG_SOC_CAMERA_SID130B) += sid130B.o
|
||||
obj-$(CONFIG_SOC_CAMERA_HI253) += hi253.o
|
||||
obj-$(CONFIG_SOC_CAMERA_HI704) += hi704.o
|
||||
obj-$(CONFIG_SOC_CAMERA_NT99250) += nt99250.o
|
||||
# And now the v4l2 drivers:
|
||||
|
||||
obj-$(CONFIG_VIDEO_BT848) += bt8xx/
|
||||
|
|
@ -163,6 +186,9 @@ obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o
|
|||
obj-$(CONFIG_VIDEO_MX2) += mx2_camera.o
|
||||
obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o
|
||||
obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o
|
||||
obj-$(CONFIG_VIDEO_RK29_WORK_ONEFRAME) += rk29_camera_oneframe.o
|
||||
obj-$(CONFIG_VIDEO_RK29_WORK_PINGPONG) += rk29_camera_pingpong.o
|
||||
obj-$(CONFIG_VIDEO_RK29XX_VOUT) += rk29xx/
|
||||
obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o
|
||||
obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o
|
||||
obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -484,6 +484,7 @@ static int soc_camera_open(struct file *file)
|
|||
icd->current_fmt->host_fmt->fourcc,
|
||||
},
|
||||
};
|
||||
<<<<<<< HEAD
|
||||
|
||||
ret = soc_camera_power_set(icd, icl, 1);
|
||||
if (ret < 0)
|
||||
|
|
@ -492,6 +493,20 @@ static int soc_camera_open(struct file *file)
|
|||
/* The camera could have been already on, try to reset */
|
||||
if (icl->reset)
|
||||
icl->reset(icd->pdev);
|
||||
=======
|
||||
/* ddl@rock-chips.com : accelerate device open */
|
||||
if ((file->f_flags & O_ACCMODE) == O_RDWR) {
|
||||
if (icl->power) {
|
||||
ret = icl->power(icd->pdev, 1);
|
||||
if (ret < 0)
|
||||
goto epower;
|
||||
}
|
||||
|
||||
/* The camera could have been already on, try to reset */
|
||||
if (icl->reset)
|
||||
icl->reset(icd->pdev);
|
||||
}
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
|
||||
ret = ici->ops->add(icd);
|
||||
if (ret < 0) {
|
||||
|
|
@ -504,6 +519,7 @@ static int soc_camera_open(struct file *file)
|
|||
if (ret < 0 && ret != -ENOSYS)
|
||||
goto eresume;
|
||||
|
||||
if ((file->f_flags & O_ACCMODE) == O_RDWR) {
|
||||
/*
|
||||
* Try to configure with default parameters. Notice: this is the
|
||||
* very first open, so, we cannot race against other calls,
|
||||
|
|
@ -513,6 +529,7 @@ static int soc_camera_open(struct file *file)
|
|||
ret = soc_camera_set_fmt(icd, &f);
|
||||
if (ret < 0)
|
||||
goto esfmt;
|
||||
<<<<<<< HEAD
|
||||
|
||||
if (ici->ops->init_videobuf) {
|
||||
ici->ops->init_videobuf(&icd->vb_vidq, icd);
|
||||
|
|
@ -521,6 +538,9 @@ static int soc_camera_open(struct file *file)
|
|||
if (ret < 0)
|
||||
goto einitvb;
|
||||
}
|
||||
=======
|
||||
}
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
}
|
||||
|
||||
file->private_data = icd;
|
||||
|
|
@ -562,7 +582,14 @@ static int soc_camera_close(struct file *file)
|
|||
if (ici->ops->init_videobuf2)
|
||||
vb2_queue_release(&icd->vb2_vidq);
|
||||
|
||||
<<<<<<< HEAD
|
||||
soc_camera_power_set(icd, icl, 0);
|
||||
=======
|
||||
if ((file->f_flags & O_ACCMODE) == O_RDWR) {
|
||||
if (icl->power)
|
||||
icl->power(icd->pdev, 0);
|
||||
}
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
}
|
||||
|
||||
if (icd->streamer == file)
|
||||
|
|
@ -653,8 +680,14 @@ static struct v4l2_file_operations soc_camera_fops = {
|
|||
static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
struct soc_camera_device *icd = file->private_data;
|
||||
int ret;
|
||||
=======
|
||||
struct soc_camera_file *icf = file->private_data;
|
||||
struct soc_camera_device *icd = icf->icd;
|
||||
int ret,i;
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
|
||||
WARN_ON(priv != file->private_data);
|
||||
|
||||
|
|
@ -666,10 +699,31 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
|
|||
if (icd->streamer && icd->streamer != file)
|
||||
return -EBUSY;
|
||||
|
||||
<<<<<<< HEAD
|
||||
if (is_streaming(to_soc_camera_host(icd->dev.parent), icd)) {
|
||||
=======
|
||||
#if 1
|
||||
if (icf->vb_vidq.bufs[0]) {
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
dev_err(&icd->dev, "S_FMT denied: queue initialised\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
#else
|
||||
|
||||
/* ddl@rock-chips.com :
|
||||
Judge queue initialised by Judge icf->vb_vidq.bufs[0] whether is NULL , it is error. */
|
||||
|
||||
i = 0;
|
||||
while (icf->vb_vidq.bufs[i] && (i<VIDEO_MAX_FRAME)) {
|
||||
if (icf->vb_vidq.bufs[i]->state != VIDEOBUF_NEEDS_INIT) {
|
||||
dev_err(&icd->dev, "S_FMT denied: queue initialised, icf->vb_vidq.bufs[%d]->state:0x%x\n",i,icf->vb_vidq.bufs[i]->state);
|
||||
ret = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
ret = soc_camera_set_fmt(icd, f);
|
||||
|
||||
|
|
@ -678,7 +732,27 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
|
|||
|
||||
return ret;
|
||||
}
|
||||
static int soc_camera_enum_frameintervals (struct file *file, void *priv,
|
||||
struct v4l2_frmivalenum *fival)
|
||||
{
|
||||
struct soc_camera_file *icf = file->private_data;
|
||||
struct soc_camera_device *icd = icf->icd;
|
||||
const struct soc_camera_data_format *format;
|
||||
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
|
||||
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
|
||||
int ret;
|
||||
|
||||
WARN_ON(priv != file->private_data);
|
||||
|
||||
ret = v4l2_subdev_call(sd, video, enum_frameintervals, fival);
|
||||
if (ret == -ENOIOCTLCMD)
|
||||
if (ici->ops->enum_frameinervals)
|
||||
ret = ici->ops->enum_frameinervals(icd, fival);
|
||||
else
|
||||
ret = -ENOIOCTLCMD;
|
||||
|
||||
return ret;
|
||||
}
|
||||
static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_fmtdesc *f)
|
||||
{
|
||||
|
|
@ -739,6 +813,8 @@ static int soc_camera_streamon(struct file *file, void *priv,
|
|||
struct soc_camera_device *icd = file->private_data;
|
||||
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
|
||||
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
|
||||
struct soc_camera_host *ici =
|
||||
to_soc_camera_host(icd->dev.parent);
|
||||
int ret;
|
||||
|
||||
WARN_ON(priv != file->private_data);
|
||||
|
|
@ -746,9 +822,17 @@ static int soc_camera_streamon(struct file *file, void *priv,
|
|||
if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
||||
return -EINVAL;
|
||||
|
||||
<<<<<<< HEAD
|
||||
if (icd->streamer != file)
|
||||
return -EBUSY;
|
||||
|
||||
=======
|
||||
mutex_lock(&icd->video_lock);
|
||||
|
||||
v4l2_subdev_call(sd, video, s_stream, 1);
|
||||
if (ici->ops->s_stream)
|
||||
ici->ops->s_stream(icd, 1); /* ddl@rock-chips.com : Add stream control for host */
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
/* This calls buf_queue from host driver's videobuf_queue_ops */
|
||||
if (ici->ops->init_videobuf)
|
||||
ret = videobuf_streamon(&icd->vb_vidq);
|
||||
|
|
@ -766,15 +850,25 @@ static int soc_camera_streamoff(struct file *file, void *priv,
|
|||
{
|
||||
struct soc_camera_device *icd = file->private_data;
|
||||
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
|
||||
<<<<<<< HEAD
|
||||
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
|
||||
=======
|
||||
struct soc_camera_host *ici =
|
||||
to_soc_camera_host(icd->dev.parent);
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
|
||||
WARN_ON(priv != file->private_data);
|
||||
|
||||
if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
||||
return -EINVAL;
|
||||
<<<<<<< HEAD
|
||||
|
||||
if (icd->streamer != file)
|
||||
return -EBUSY;
|
||||
=======
|
||||
|
||||
mutex_lock(&icd->video_lock);
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
|
||||
/*
|
||||
* This calls buf_release from host driver's videobuf_queue_ops for all
|
||||
|
|
@ -786,7 +880,15 @@ static int soc_camera_streamoff(struct file *file, void *priv,
|
|||
vb2_streamoff(&icd->vb2_vidq, i);
|
||||
|
||||
v4l2_subdev_call(sd, video, s_stream, 0);
|
||||
if (ici->ops->s_stream)
|
||||
ici->ops->s_stream(icd, 0); /* ddl@rock-chips.com : Add stream control for host */
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
videobuf_mmap_free(&icf->vb_vidq); /* ddl@rock-chips.com : free video buf */
|
||||
mutex_unlock(&icd->video_lock);
|
||||
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -821,6 +923,40 @@ static int soc_camera_queryctrl(struct file *file, void *priv,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* ddl@rock-chips.com : Add ioctrl -VIDIOC_QUERYMENU */
|
||||
static int soc_camera_querymenu(struct file *file, void *priv,
|
||||
struct v4l2_querymenu *qm)
|
||||
{
|
||||
struct soc_camera_file *icf = file->private_data;
|
||||
struct soc_camera_device *icd = icf->icd;
|
||||
struct v4l2_queryctrl qctrl;
|
||||
int i,j;
|
||||
|
||||
qctrl.id = qm->id;
|
||||
|
||||
if (soc_camera_queryctrl(file,priv, &qctrl) == 0) {
|
||||
for (i = 0; i < icd->ops->num_menus; i++) {
|
||||
if (qm->id == icd->ops->menus[i].id) {
|
||||
for (j=0; j<=(qctrl.maximum - qctrl.minimum); j++) {
|
||||
|
||||
if (qm->index == icd->ops->menus[i].index) {
|
||||
snprintf(qm->name, sizeof(qm->name), icd->ops->menus[i].name);
|
||||
qm->reserved = 0;
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
i++;
|
||||
if ( i >= icd->ops->num_menus)
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int soc_camera_g_ctrl(struct file *file, void *priv,
|
||||
struct v4l2_control *ctrl)
|
||||
{
|
||||
|
|
@ -859,6 +995,64 @@ static int soc_camera_s_ctrl(struct file *file, void *priv,
|
|||
return v4l2_subdev_call(sd, core, s_ctrl, ctrl);
|
||||
}
|
||||
|
||||
|
||||
/* ddl@rock-chips.com : Add ioctrl -VIDIOC_XXX_ext_ctrl for soc-camera */
|
||||
static int soc_camera_try_ext_ctrl(struct file *file, void *priv,
|
||||
struct v4l2_ext_controls *ctrl)
|
||||
{
|
||||
struct soc_camera_file *icf = file->private_data;
|
||||
struct soc_camera_device *icd = icf->icd;
|
||||
const struct v4l2_queryctrl *qctrl;
|
||||
int i;
|
||||
|
||||
WARN_ON(priv != file->private_data);
|
||||
|
||||
if (ctrl->ctrl_class != V4L2_CTRL_CLASS_CAMERA)
|
||||
return -EINVAL;
|
||||
|
||||
for (i=0; i<ctrl->count; i++) {
|
||||
qctrl = soc_camera_find_qctrl(icd->ops, ctrl->controls[i].id);
|
||||
if (!qctrl)
|
||||
return -EINVAL;
|
||||
|
||||
if ((ctrl->controls[i].value < qctrl->minimum) ||(ctrl->controls[i].value > qctrl->minimum))
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ddl@rock-chips.com : Add ioctrl -VIDIOC_XXX_ext_ctrl for soc-camera */
|
||||
static int soc_camera_g_ext_ctrl(struct file *file, void *priv,
|
||||
struct v4l2_ext_controls *ctrl)
|
||||
{
|
||||
struct soc_camera_file *icf = file->private_data;
|
||||
struct soc_camera_device *icd = icf->icd;
|
||||
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
|
||||
|
||||
WARN_ON(priv != file->private_data);
|
||||
|
||||
if (ctrl->ctrl_class != V4L2_CTRL_CLASS_CAMERA)
|
||||
return -EINVAL;
|
||||
|
||||
return v4l2_subdev_call(sd, core, g_ext_ctrls, ctrl);
|
||||
}
|
||||
/* ddl@rock-chips.com : Add ioctrl -VIDIOC_XXX_ext_ctrl for soc-camera */
|
||||
static int soc_camera_s_ext_ctrl(struct file *file, void *priv,
|
||||
struct v4l2_ext_controls *ctrl)
|
||||
{
|
||||
struct soc_camera_file *icf = file->private_data;
|
||||
struct soc_camera_device *icd = icf->icd;
|
||||
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
|
||||
|
||||
WARN_ON(priv != file->private_data);
|
||||
|
||||
if (ctrl->ctrl_class != V4L2_CTRL_CLASS_CAMERA)
|
||||
return -EINVAL;
|
||||
|
||||
return v4l2_subdev_call(sd, core, s_ext_ctrls, ctrl);
|
||||
}
|
||||
|
||||
|
||||
static int soc_camera_cropcap(struct file *file, void *fh,
|
||||
struct v4l2_cropcap *a)
|
||||
{
|
||||
|
|
@ -1471,8 +1665,13 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
|
|||
.vidioc_streamon = soc_camera_streamon,
|
||||
.vidioc_streamoff = soc_camera_streamoff,
|
||||
.vidioc_queryctrl = soc_camera_queryctrl,
|
||||
.vidioc_querymenu = soc_camera_querymenu, /* ddl@rock-chips.com: Add ioctrl - vidioc_querymenu for soc-camera */
|
||||
.vidioc_g_ctrl = soc_camera_g_ctrl,
|
||||
.vidioc_s_ctrl = soc_camera_s_ctrl,
|
||||
.vidioc_g_ext_ctrls = soc_camera_g_ext_ctrl, /* ddl@rock-chips.com: Add ioctrl - vidioc_g_ext_ctrls for soc-camera */
|
||||
.vidioc_s_ext_ctrls = soc_camera_s_ext_ctrl, /* ddl@rock-chips.com: Add ioctrl - vidioc_s_ext_ctrls for soc-camera */
|
||||
.vidioc_try_ext_ctrls = soc_camera_try_ext_ctrl,/* ddl@rock-chips.com: Add ioctrl - vidioc_try_ext_ctrls for soc-camera */
|
||||
.vidioc_enum_frameintervals = soc_camera_enum_frameintervals,/* ddl@rock-chips.com: Add ioctrl - VIDIOC_ENUM_FRAMEINTERVALS for soc-camera */
|
||||
.vidioc_cropcap = soc_camera_cropcap,
|
||||
.vidioc_g_crop = soc_camera_g_crop,
|
||||
.vidioc_s_crop = soc_camera_s_crop,
|
||||
|
|
|
|||
|
|
@ -295,8 +295,10 @@ static int uvc_v4l2_set_format(struct uvc_streaming *stream,
|
|||
struct uvc_frame *frame;
|
||||
int ret;
|
||||
|
||||
if (fmt->type != stream->type)
|
||||
if (fmt->type != stream->type) {
|
||||
printk("uvc_v4l2_set_format, fmt->type(%d) != stream->type(%d)\n",fmt->type,stream->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame);
|
||||
if (ret < 0)
|
||||
|
|
@ -305,6 +307,7 @@ static int uvc_v4l2_set_format(struct uvc_streaming *stream,
|
|||
mutex_lock(&stream->mutex);
|
||||
|
||||
if (uvc_queue_allocated(&stream->queue)) {
|
||||
printk("uvc_queue_allocated failed\n");
|
||||
ret = -EBUSY;
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -799,8 +802,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
|
|||
}
|
||||
|
||||
case VIDIOC_S_FMT:
|
||||
if ((ret = uvc_acquire_privileges(handle)) < 0)
|
||||
if ((ret = uvc_acquire_privileges(handle)) < 0) {
|
||||
printk("uvc_acquire_privileges error.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return uvc_v4l2_set_format(stream, arg);
|
||||
|
||||
|
|
@ -974,14 +979,18 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
|
|||
}
|
||||
|
||||
case VIDIOC_QBUF:
|
||||
if (!uvc_has_privileges(handle))
|
||||
if (!uvc_has_privileges(handle)) {
|
||||
printk("uvcvideo: VIDIOC_QBUF uvc_has_privileges failed\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return uvc_queue_buffer(&stream->queue, arg);
|
||||
|
||||
case VIDIOC_DQBUF:
|
||||
if (!uvc_has_privileges(handle))
|
||||
if (!uvc_has_privileges(handle)) {
|
||||
printk("uvcvideo: VIDIOC_DQBUF uvc_has_privileges failed\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return uvc_dequeue_buffer(&stream->queue, arg,
|
||||
file->f_flags & O_NONBLOCK);
|
||||
|
|
|
|||
|
|
@ -821,10 +821,10 @@ static long __video_do_ioctl(struct file *file,
|
|||
case VIDIOC_S_FMT:
|
||||
{
|
||||
struct v4l2_format *f = (struct v4l2_format *)arg;
|
||||
|
||||
|
||||
/* FIXME: Should be one dump per type */
|
||||
dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
|
||||
|
||||
|
||||
switch (f->type) {
|
||||
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
||||
CLEAR_AFTER_FIELD(f, fmt.pix);
|
||||
|
|
|
|||
|
|
@ -385,6 +385,17 @@ config MFD_WM831X_SPI
|
|||
for accessing the device, additional drivers must be enabled in
|
||||
order to use the functionality of the device.
|
||||
|
||||
config MFD_WM831X_SPI_A22
|
||||
bool "Support Wolfson Microelectronics WM831x/2x PMICs with SPI for A22"
|
||||
#select MFD_CORE
|
||||
#select MFD_WM831X
|
||||
depends on SPI_MASTER && GENERIC_HARDIRQS
|
||||
help
|
||||
Support for the Wolfson Microelecronics WM831x and WM832x PMICs
|
||||
when controlled using SPI. This driver provides common support
|
||||
for accessing the device, additional drivers must be enabled in
|
||||
order to use the functionality of the device.
|
||||
|
||||
config MFD_WM8350
|
||||
bool
|
||||
depends on GENERIC_HARDIRQS
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o
|
|||
obj-$(CONFIG_MFD_WM831X) += wm831x.o
|
||||
obj-$(CONFIG_MFD_WM831X_I2C) += wm831x-i2c.o
|
||||
obj-$(CONFIG_MFD_WM831X_SPI) += wm831x-spi.o
|
||||
obj-$(CONFIG_MFD_WM831X_SPI_A22) += wm831x-spi-a22.o
|
||||
wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
|
||||
wm8350-objs += wm8350-irq.o
|
||||
obj-$(CONFIG_MFD_WM8350) += wm8350.o
|
||||
|
|
|
|||
|
|
@ -1,801 +0,0 @@
|
|||
/*
|
||||
* tps65910-core.c -- Multifunction core driver for TPS65910x chips
|
||||
*
|
||||
* Copyright (C) 2010 Mistral solutions Pvt Ltd <www.mistralsolutions.com>
|
||||
*
|
||||
* Based on twl-core.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c/tps65910.h>
|
||||
#include <mach/board.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#if 0
|
||||
#define DBG(x...) printk(KERN_INFO x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
#define TPS65910_SPEED 400 * 1000
|
||||
|
||||
|
||||
#define DRIVER_NAME "tps659102"
|
||||
|
||||
#if defined(CONFIG_GPIO_TPS65910)
|
||||
#define tps65910_has_gpio() true
|
||||
#else
|
||||
#define tps65910_has_gpio() false
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_REGULATOR_TPS65910)
|
||||
#define tps65910_has_regulator() true
|
||||
#else
|
||||
#define tps65910_has_regulator() false
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_RTC_DRV_TPS65910)
|
||||
#define tps65910_has_rtc() true
|
||||
#else
|
||||
#define tps65910_has_rtc() false
|
||||
#endif
|
||||
|
||||
#define TPS65910_GENERAL 0
|
||||
#define TPS65910_SMARTREFLEX 1
|
||||
|
||||
|
||||
struct tps65910_platform_data *gtps65910_platform = NULL;
|
||||
|
||||
enum tps65910x_model {
|
||||
TPS65910, /* TI processors OMAP3 family */
|
||||
TPS659101, /* Samsung - S5PV210, S5PC1xx */
|
||||
TPS659102, /* Samsung - S3C64xx */
|
||||
TPS659103, /* Reserved */
|
||||
TPS659104, /* Reserved */
|
||||
TPS659105, /* TI processors - DM643x, DM644x */
|
||||
TPS659106, /* Reserved */
|
||||
TPS659107, /* Reserved */
|
||||
TPS659108, /* Reserved */
|
||||
TPS659109, /* Freescale - i.MX51 */
|
||||
|
||||
};
|
||||
|
||||
static bool inuse;
|
||||
static struct work_struct core_work;
|
||||
static struct mutex work_lock;
|
||||
|
||||
/* Structure for each TPS65910 Slave */
|
||||
struct tps65910_client {
|
||||
struct i2c_client *client;
|
||||
u8 address;
|
||||
/* max numb of i2c_msg required for read = 2 */
|
||||
struct i2c_msg xfer_msg[2];
|
||||
/* To lock access to xfer_msg */
|
||||
struct mutex xfer_lock;
|
||||
};
|
||||
static struct tps65910_client tps65910_modules[TPS65910_NUM_SLAVES];
|
||||
|
||||
/* bbch = Back-up battery charger control register */
|
||||
int tps65910_enable_bbch(u8 voltage)
|
||||
{
|
||||
u8 val = 0;
|
||||
int err;
|
||||
|
||||
if (voltage == TPS65910_BBSEL_3P0 || voltage == TPS65910_BBSEL_2P52 ||
|
||||
voltage == TPS65910_BBSEL_3P15 ||
|
||||
voltage == TPS65910_BBSEL_VBAT) {
|
||||
val = (voltage | TPS65910_BBCHEN);
|
||||
err = tps65910_i2c_write_u8(TPS65910_I2C_ID0, val,
|
||||
TPS65910_REG_BBCH);
|
||||
if (err) {
|
||||
printk(KERN_ERR "Unable write TPS65910_REG_BBCH reg\n");
|
||||
return -EIO;
|
||||
}
|
||||
} else {
|
||||
printk(KERN_ERR"Invalid argumnet for %s \n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(tps65910_enable_bbch);
|
||||
|
||||
int tps65910_disable_bbch(void)
|
||||
{
|
||||
u8 val = 0;
|
||||
int err;
|
||||
|
||||
err = tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_BBCH);
|
||||
|
||||
if (!err) {
|
||||
val &= ~TPS65910_BBCHEN;
|
||||
|
||||
err = tps65910_i2c_write_u8(TPS65910_I2C_ID0, val,
|
||||
TPS65910_REG_BBCH);
|
||||
if (err) {
|
||||
printk(KERN_ERR "Unable write TPS65910_REG_BBCH \
|
||||
reg\n");
|
||||
return -EIO;
|
||||
}
|
||||
} else {
|
||||
printk(KERN_ERR "Unable to read TPS65910_REG_BBCH reg\n");
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(tps65910_disable_bbch);
|
||||
|
||||
int tps65910_i2c_read_u8(u8 mod_no, u8 *value, u8 reg)
|
||||
{
|
||||
struct tps65910_client *tps65910;
|
||||
int ret;
|
||||
|
||||
switch (mod_no) {
|
||||
case TPS65910_I2C_ID0:
|
||||
tps65910 = &tps65910_modules[0];
|
||||
tps65910->address = TPS65910_I2C_ID0;
|
||||
break;
|
||||
case TPS65910_I2C_ID1:
|
||||
tps65910 = &tps65910_modules[1];
|
||||
tps65910->address = TPS65910_I2C_ID1;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "Invalid Slave address for TPS65910\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = i2c_master_reg8_recv(tps65910->client, reg, (char *)value, 1, TPS65910_SPEED);
|
||||
DBG("%s: ret=%d, slave_addr=0x%x, reg=0x%x, value=0x%x\n", __FUNCTION__, (ret > 0 ? 0: -EINVAL), mod_no, reg, *value);
|
||||
|
||||
return (ret > 0 ? 0: -EINVAL);
|
||||
}
|
||||
EXPORT_SYMBOL(tps65910_i2c_read_u8);
|
||||
|
||||
int tps65910_i2c_write_u8(u8 slave_addr, u8 value, u8 reg)
|
||||
{
|
||||
struct tps65910_client *tps65910;
|
||||
int ret;
|
||||
|
||||
switch (slave_addr) {
|
||||
case TPS65910_I2C_ID0:
|
||||
tps65910 = &tps65910_modules[0];
|
||||
tps65910->address = TPS65910_I2C_ID0;
|
||||
break;
|
||||
case TPS65910_I2C_ID1:
|
||||
tps65910 = &tps65910_modules[1];
|
||||
tps65910->address = TPS65910_I2C_ID1;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "Invalid Slave address for TPS65910\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = i2c_master_reg8_send(tps65910->client, reg, (char *)&value, 1, TPS65910_SPEED);
|
||||
DBG("%s: ret=%d, slave_addr=0x%x, reg=0x%x, value=0x%x\n", __FUNCTION__, ret, slave_addr, reg, value);
|
||||
|
||||
if (ret < 0)
|
||||
return -EIO;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(tps65910_i2c_write_u8);
|
||||
|
||||
|
||||
int tps65910_enable_irq(int irq)
|
||||
{
|
||||
u8 mask = 0x00;
|
||||
|
||||
if (irq > 7) {
|
||||
irq -= 8;
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0,
|
||||
&mask, TPS65910_REG_INT_MSK2);
|
||||
mask &= ~(1 << irq);
|
||||
return tps65910_i2c_write_u8(TPS65910_I2C_ID0,
|
||||
mask, TPS65910_REG_INT_MSK2);
|
||||
} else {
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0,
|
||||
&mask, TPS65910_REG_INT_MSK);
|
||||
mask &= ~(1 << irq);
|
||||
return tps65910_i2c_write_u8(TPS65910_I2C_ID0,
|
||||
mask, TPS65910_REG_INT_MSK);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(tps65910_enable_irq);
|
||||
|
||||
int tps65910_disable_irq(int irq)
|
||||
{
|
||||
u8 mask = 0x00;
|
||||
|
||||
if (irq > 7) {
|
||||
irq -= 8;
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0,
|
||||
&mask, TPS65910_REG_INT_MSK2);
|
||||
mask |= (1 << irq);
|
||||
return tps65910_i2c_write_u8(TPS65910_I2C_ID0,
|
||||
mask, TPS65910_REG_INT_MSK2);
|
||||
} else {
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0,
|
||||
&mask, TPS65910_REG_INT_MSK);
|
||||
mask = (1 << irq);
|
||||
return tps65910_i2c_write_u8(TPS65910_I2C_ID0,
|
||||
mask, TPS65910_REG_INT_MSK);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(tps65910_disable_irq);
|
||||
|
||||
int tps65910_add_irq_work(int irq,
|
||||
void (*handler)(void *data))
|
||||
{
|
||||
int ret = 0;
|
||||
gtps65910_platform->handlers[irq] = handler;
|
||||
ret = tps65910_enable_irq(irq);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(tps65910_add_irq_work);
|
||||
|
||||
int tps65910_remove_irq_work(int irq)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = tps65910_disable_irq(irq);
|
||||
gtps65910_platform->handlers[irq] = NULL;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(tps65910_remove_irq_work);
|
||||
|
||||
static void tps65910_core_work(struct work_struct *work)
|
||||
{
|
||||
/* Read the status register and take action */
|
||||
u8 status = 0x00;
|
||||
u8 status2 = 0x00;
|
||||
u8 mask = 0x00;
|
||||
u8 mask2 = 0x00;
|
||||
u16 isr = 0x00;
|
||||
u16 irq = 0;
|
||||
void (*handler)(void *data) = NULL;
|
||||
|
||||
DBG("Enter::%s %d\n",__FUNCTION__,__LINE__);
|
||||
mutex_lock(&work_lock);
|
||||
while (1) {
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &status2,
|
||||
TPS65910_REG_INT_STS2);
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &mask2,
|
||||
TPS65910_REG_INT_MSK2);
|
||||
status2 &= (~mask2);
|
||||
isr = (status2 << 8);
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &status,
|
||||
TPS65910_REG_INT_STS);
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &mask,
|
||||
TPS65910_REG_INT_MSK);
|
||||
status &= ~(mask);
|
||||
isr |= status;
|
||||
if (!isr)
|
||||
break;
|
||||
|
||||
while (isr) {
|
||||
irq = fls(isr) - 1;
|
||||
isr &= ~(1 << irq);
|
||||
handler = gtps65910_platform->handlers[irq];
|
||||
if (handler)
|
||||
handler(gtps65910_platform);
|
||||
}
|
||||
}
|
||||
enable_irq(gtps65910_platform->irq_num);
|
||||
mutex_unlock(&work_lock);
|
||||
}
|
||||
|
||||
|
||||
static irqreturn_t tps65910_isr(int irq, void *data)
|
||||
{
|
||||
disable_irq_nosync(irq);
|
||||
(void) schedule_work(&core_work);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
static struct device *add_numbered_child(unsigned chip, const char *name,
|
||||
int num, void *pdata, unsigned pdata_len, bool can_wakeup, int irq)
|
||||
{
|
||||
|
||||
struct platform_device *pdev;
|
||||
struct tps65910_client *tps65910 = &tps65910_modules[chip];
|
||||
int status;
|
||||
|
||||
pdev = platform_device_alloc(name, num);
|
||||
if (!pdev) {
|
||||
dev_dbg(&tps65910->client->dev, "can't alloc dev\n");
|
||||
status = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
device_init_wakeup(&pdev->dev, can_wakeup);
|
||||
pdev->dev.parent = &tps65910->client->dev;
|
||||
|
||||
if (pdata) {
|
||||
status = platform_device_add_data(pdev, pdata, pdata_len);
|
||||
if (status < 0) {
|
||||
dev_dbg(&pdev->dev, "can't add platform_data\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
status = platform_device_add(pdev);
|
||||
|
||||
err:
|
||||
if (status < 0) {
|
||||
platform_device_put(pdev);
|
||||
dev_err(&tps65910->client->dev, "can't add %s dev\n", name);
|
||||
return ERR_PTR(status);
|
||||
}
|
||||
return &pdev->dev;
|
||||
|
||||
}
|
||||
|
||||
static inline struct device *add_child(unsigned chip, const char *name,
|
||||
void *pdata, unsigned pdata_len,
|
||||
bool can_wakeup, int irq)
|
||||
{
|
||||
return add_numbered_child(chip, name, -1, pdata, pdata_len,
|
||||
can_wakeup, irq);
|
||||
}
|
||||
|
||||
static
|
||||
struct device *add_regulator_linked(int num, struct regulator_init_data *pdata,
|
||||
struct regulator_consumer_supply *consumers,
|
||||
unsigned num_consumers)
|
||||
{
|
||||
/* regulator framework demands init_data */
|
||||
if (!pdata)
|
||||
return NULL;
|
||||
|
||||
if (consumers) {
|
||||
pdata->consumer_supplies = consumers;
|
||||
pdata->num_consumer_supplies = num_consumers;
|
||||
}
|
||||
|
||||
return add_numbered_child(TPS65910_GENERAL, "tps65910_regulator", num,
|
||||
pdata, sizeof(*pdata), false, TPS65910_HOST_IRQ);
|
||||
}
|
||||
|
||||
static struct device *
|
||||
add_regulator(int num, struct regulator_init_data *pdata)
|
||||
{
|
||||
return add_regulator_linked(num, pdata, NULL, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
add_children(struct tps65910_platform_data *pdata, unsigned long features)
|
||||
{
|
||||
int status;
|
||||
struct device *child;
|
||||
|
||||
struct platform_device *pdev = NULL;
|
||||
|
||||
DBG("cwz add_children: tps65910 add children.\n");
|
||||
|
||||
if (tps65910_has_gpio() && (pdata->gpio != NULL)) {
|
||||
|
||||
pdev = platform_device_alloc("tps65910_gpio", -1);
|
||||
if (!pdev) {
|
||||
status = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
pdev->dev.parent = &tps65910_modules[0].client->dev;
|
||||
device_init_wakeup(&pdev->dev, 0);
|
||||
if (pdata) {
|
||||
status = platform_device_add_data(pdev, pdata,
|
||||
sizeof(*pdata));
|
||||
if (status < 0) {
|
||||
dev_dbg(&pdev->dev,
|
||||
"can't add platform_data\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tps65910_has_rtc()) {
|
||||
child = add_child(TPS65910_GENERAL, "tps65910_rtc",
|
||||
NULL, 0, true, pdata->irq_num);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
}
|
||||
|
||||
if (tps65910_has_regulator()) {
|
||||
child = add_regulator(TPS65910_VIO, pdata->vio);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TPS65910_VDD1, pdata->vdd1);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TPS65910_VDD2, pdata->vdd2);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TPS65910_VDD3, pdata->vdd3);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TPS65910_VDIG1, pdata->vdig1);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TPS65910_VDIG2, pdata->vdig2);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TPS65910_VAUX33, pdata->vaux33);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TPS65910_VMMC, pdata->vmmc);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TPS65910_VAUX1, pdata->vaux1);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TPS65910_VAUX2, pdata->vaux2);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TPS65910_VDAC, pdata->vdac);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TPS65910_VPLL, pdata->vpll);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int tps65910_remove(struct i2c_client *client)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < TPS65910_NUM_SLAVES; i++) {
|
||||
|
||||
struct tps65910_client *tps65910 = &tps65910_modules[i];
|
||||
|
||||
if (tps65910->client && tps65910->client != client)
|
||||
i2c_unregister_device(tps65910->client);
|
||||
|
||||
tps65910_modules[i].client = NULL;
|
||||
}
|
||||
inuse = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init
|
||||
tps65910_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
{
|
||||
int status;
|
||||
unsigned i;
|
||||
struct tps65910_platform_data *pdata;
|
||||
|
||||
pdata = client->dev.platform_data;
|
||||
gtps65910_platform = pdata;
|
||||
|
||||
DBG("cwz: tps65910_i2c_probe\n");
|
||||
|
||||
if (!pdata) {
|
||||
dev_dbg(&client->dev, "no platform data?\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,I2C_FUNC_I2C)) {
|
||||
dev_dbg(&client->dev, "can't talk I2C?\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (inuse) {
|
||||
dev_dbg(&client->dev, "driver is already in use\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
for (i = 0; i < TPS65910_NUM_SLAVES; i++) {
|
||||
|
||||
struct tps65910_client *tps65910 = &tps65910_modules[i];
|
||||
|
||||
tps65910->address = client->addr;
|
||||
|
||||
if (i == 0)
|
||||
tps65910->client = client;
|
||||
else {
|
||||
tps65910->client = i2c_new_dummy(client->adapter,
|
||||
tps65910->address);
|
||||
|
||||
if (!tps65910->client) {
|
||||
dev_err(&client->dev,
|
||||
"can't attach client %d\n", i);
|
||||
status = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
mutex_init(&tps65910->xfer_lock);
|
||||
}
|
||||
|
||||
inuse = true;
|
||||
|
||||
if (pdata->board_tps65910_config != NULL)
|
||||
pdata->board_tps65910_config(pdata);
|
||||
|
||||
if (pdata->irq_num) {
|
||||
/* TPS65910 power ON interrupt(s) would have already been
|
||||
* occurred, so immediately after request_irq the control will
|
||||
* be transferred to tps65910_isr, if we do core_work
|
||||
* initialization after requesting IRQ, the system crashes
|
||||
* and does not boot; to avoid this we do core_work
|
||||
* initialization before requesting IRQ
|
||||
*/
|
||||
mutex_init(&work_lock);
|
||||
|
||||
if(gpio_request(client->irq, "tps65910 irq"))
|
||||
{
|
||||
dev_err(&client->dev, "gpio request fail\n");
|
||||
gpio_free(client->irq);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pdata->irq_num = gpio_to_irq(client->irq);
|
||||
gpio_pull_updown(client->irq,GPIOPullUp);
|
||||
|
||||
status = request_irq(pdata->irq_num, tps65910_isr,
|
||||
IRQF_TRIGGER_FALLING, client->dev.driver->name, pdata);
|
||||
if (status < 0) {
|
||||
pr_err("tps65910: could not claim irq%d: %d\n",
|
||||
pdata->irq_num, status);
|
||||
goto fail;
|
||||
}
|
||||
enable_irq_wake(pdata->irq_num);
|
||||
INIT_WORK(&core_work, tps65910_core_work);
|
||||
}
|
||||
|
||||
status = add_children(pdata, 0x00);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (status < 0)
|
||||
tps65910_remove(client);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static int tps65910_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < TPS65910_NUM_SLAVES; i++) {
|
||||
|
||||
struct tps65910_client *tps65910 = &tps65910_modules[i];
|
||||
|
||||
if (tps65910->client && tps65910->client != client)
|
||||
i2c_unregister_device(tps65910->client);
|
||||
|
||||
tps65910_modules[i].client = NULL;
|
||||
}
|
||||
inuse = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* chip-specific feature flags, for i2c_device_id.driver_data */
|
||||
static const struct i2c_device_id tps65910_i2c_ids[] = {
|
||||
{ "tps65910", TPS65910 },
|
||||
{ "tps659101", TPS659101 },
|
||||
{ "tps659102", TPS659102 },
|
||||
{ "tps659103", TPS659103 },
|
||||
{ "tps659104", TPS659104 },
|
||||
{ "tps659105", TPS659105 },
|
||||
{ "tps659106", TPS659106 },
|
||||
{ "tps659107", TPS659107 },
|
||||
{ "tps659108", TPS659108 },
|
||||
{ "tps659109", TPS659109 },
|
||||
{/* end of list */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tps65910_i2c_ids);
|
||||
|
||||
/* One Client Driver ,3 Clients - Regulator, RTC , GPIO */
|
||||
static struct i2c_driver tps65910_i2c_driver = {
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.id_table = tps65910_i2c_ids,
|
||||
.probe = tps65910_i2c_probe,
|
||||
.remove = __devexit_p(tps65910_i2c_remove),
|
||||
};
|
||||
|
||||
static int __init tps65910_init(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = i2c_add_driver(&tps65910_i2c_driver);
|
||||
if (res < 0) {
|
||||
pr_err(DRIVER_NAME ": driver registration failed\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
subsys_initcall_sync(tps65910_init);
|
||||
|
||||
static void __exit tps65910_exit(void)
|
||||
{
|
||||
i2c_del_driver(&tps65910_i2c_driver);
|
||||
}
|
||||
module_exit(tps65910_exit);
|
||||
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
static int proc_tps65910_show(struct seq_file *s, void *v)
|
||||
{
|
||||
u8 val = 0;
|
||||
|
||||
seq_printf(s, "\n\nTPS65910 Registers is:\n");
|
||||
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_REF);
|
||||
seq_printf(s, "REF_REG=0x%x, Value=0x%x\n", TPS65910_REG_REF, val);
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VRTC);
|
||||
seq_printf(s, "VRTC_REG=0x%x, Value=0x%x\n", TPS65910_REG_VRTC, val);
|
||||
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VDD1);
|
||||
seq_printf(s, "VDD1_REG=0x%x, Value=0x%x\n", TPS65910_REG_VDD1, val);
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VDD1_OP);
|
||||
seq_printf(s, "VDD1_OP_REG=0x%x, Value=0x%x\n", TPS65910_REG_VDD1_OP, val);
|
||||
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VDD2);
|
||||
seq_printf(s, "VDD2_REG=0x%x, Value=0x%x\n", TPS65910_REG_VDD2, val);
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VDD2_OP);
|
||||
seq_printf(s, "VDD2_OP_REG=0x%x, Value=0x%x\n", TPS65910_REG_VDD2_OP, val);
|
||||
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VIO);
|
||||
seq_printf(s, "VIO_REG=0x%x, Value=0x%x\n", TPS65910_REG_VIO, val);
|
||||
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VDIG1);
|
||||
seq_printf(s, "VDIG1_REG=0x%x, Value=0x%x\n", TPS65910_REG_VDIG1, val);
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VDIG2);
|
||||
seq_printf(s, "VDIG2_REG=0x%x, Value=0x%x\n", TPS65910_REG_VDIG2, val);
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VAUX1);
|
||||
seq_printf(s, "VAUX1_REG=0x%x, Value=0x%x\n", TPS65910_REG_VAUX1, val);
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VAUX2);
|
||||
seq_printf(s, "VAUX2_REG=0x%x, Value=0x%x\n", TPS65910_REG_VAUX2, val);
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VAUX33);
|
||||
seq_printf(s, "VAUX33_REG=0x%x, Value=0x%x\n", TPS65910_REG_VAUX33, val);
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VMMC);
|
||||
seq_printf(s, "VMMC_REG=0x%x, Value=0x%x\n", TPS65910_REG_VMMC, val);
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VPLL);
|
||||
seq_printf(s, "VPLL_REG=0x%x, Value=0x%x\n", TPS65910_REG_VPLL, val);
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VDAC);
|
||||
seq_printf(s, "VDAC_REG=0x%x, Value=0x%x\n", TPS65910_REG_VDAC, val);
|
||||
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_DEVCTRL);
|
||||
seq_printf(s, "DEVCTRL_REG=0x%x, Value=0x%x\n", TPS65910_REG_DEVCTRL, val);
|
||||
tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_DEVCTRL2);
|
||||
seq_printf(s, "DEVCTRL2_REG=0x%x, Value=0x%x\n", TPS65910_REG_DEVCTRL2, val);
|
||||
|
||||
#if 0 // cwz 1 test vcore
|
||||
{
|
||||
struct regulator *vldo;
|
||||
|
||||
vldo = regulator_get(NULL, "vcore");
|
||||
if (!IS_ERR(vldo))
|
||||
{
|
||||
int uV = 0;
|
||||
#if 0
|
||||
seq_printf(s, "Set VCORE.\n");
|
||||
regulator_set_voltage(vldo,1350000,1350000);
|
||||
#endif
|
||||
uV = regulator_get_voltage(vldo);
|
||||
seq_printf(s, "Get VCORE=%d(uV).\n", uV);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
{
|
||||
struct regulator *vldo;
|
||||
|
||||
#if 1
|
||||
vldo = regulator_get(NULL, "vaux1");
|
||||
if (!IS_ERR(vldo))
|
||||
{
|
||||
seq_printf(s, "Disable VAUX1.\n");
|
||||
regulator_disable(vldo);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
vldo = regulator_get(NULL, "vdig1");
|
||||
if (!IS_ERR(vldo))
|
||||
{
|
||||
seq_printf(s, "Disable VDIG1.\n");
|
||||
regulator_disable(vldo);
|
||||
}
|
||||
|
||||
vldo = regulator_get(NULL, "vdig2");
|
||||
if (!IS_ERR(vldo))
|
||||
{
|
||||
seq_printf(s, "Disable VDIG2.\n");
|
||||
regulator_disable(vldo);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 // fih board is for hdmi
|
||||
vldo = regulator_get(NULL, "vdac");
|
||||
if (!IS_ERR(vldo))
|
||||
{
|
||||
seq_printf(s, "Disable VDAC.\n");
|
||||
regulator_disable(vldo);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
vldo = regulator_get(NULL, "vaux2");
|
||||
if (!IS_ERR(vldo))
|
||||
{
|
||||
seq_printf(s, "Disable VAUX2.\n");
|
||||
regulator_disable(vldo);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int proc_tps65910_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, proc_tps65910_show, NULL);
|
||||
}
|
||||
|
||||
static const struct file_operations proc_tps65910_fops = {
|
||||
.open = proc_tps65910_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int __init proc_tps65910_init(void)
|
||||
{
|
||||
proc_create("tps65910", 0, NULL, &proc_tps65910_fops);
|
||||
return 0;
|
||||
}
|
||||
late_initcall(proc_tps65910_init);
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
MODULE_AUTHOR("cwz <cwz@rock-chips.com>");
|
||||
MODULE_DESCRIPTION("I2C Core interface for TPS65910");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <linux/mfd/wm831x/core.h>
|
||||
#include <linux/mfd/wm831x/pdata.h>
|
||||
|
|
@ -25,10 +26,13 @@
|
|||
#include <linux/mfd/wm831x/auxadc.h>
|
||||
#include <linux/mfd/wm831x/otp.h>
|
||||
#include <linux/mfd/wm831x/regulator.h>
|
||||
#include <linux/mfd/wm831x/pmu.h>
|
||||
|
||||
|
||||
/* Current settings - values are 2*2^(reg_val/4) microamps. These are
|
||||
* exported since they are used by multiple drivers.
|
||||
*/
|
||||
extern int reboot_cmd_get(void);
|
||||
int wm831x_isinkv_values[WM831X_ISINK_MAX_ISEL + 1] = {
|
||||
2,
|
||||
2,
|
||||
|
|
@ -383,7 +387,7 @@ int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
|
|||
* the notification of the interrupt may be delayed by
|
||||
* threaded IRQ handling. */
|
||||
if (!wait_for_completion_timeout(&wm831x->auxadc_done,
|
||||
msecs_to_jiffies(500))) {
|
||||
msecs_to_jiffies(2000))) {
|
||||
dev_err(wm831x->dev, "Timed out waiting for AUXADC\n");
|
||||
ret = -EBUSY;
|
||||
goto disable;
|
||||
|
|
@ -997,6 +1001,20 @@ static struct mfd_cell wm8310_devs[] = {
|
|||
.num_resources = ARRAY_SIZE(wm831x_wdt_resources),
|
||||
.resources = wm831x_wdt_resources,
|
||||
},
|
||||
#if defined(CONFIG_KEYBOARD_WM831X_GPIO)
|
||||
{
|
||||
.name = "wm831x_gpio-keys",
|
||||
.num_resources = 0,
|
||||
},
|
||||
#endif
|
||||
#if defined(CONFIG_WM831X_CHARGER_DISPLAY)
|
||||
{
|
||||
.name = "wm831x_charger_display",
|
||||
.num_resources = 0,
|
||||
},
|
||||
#endif
|
||||
|
||||
|
||||
};
|
||||
|
||||
static struct mfd_cell wm8311_devs[] = {
|
||||
|
|
@ -1455,11 +1473,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
|
|||
dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
switch (ret) {
|
||||
case 0x6204:
|
||||
case 0x6246:
|
||||
break;
|
||||
default:
|
||||
if (ret != 0x6204) {
|
||||
dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
|
|
@ -1489,12 +1503,15 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
|
|||
switch (ret) {
|
||||
case WM8310:
|
||||
parent = WM8310;
|
||||
wm831x->num_gpio = 16;
|
||||
wm831x->num_gpio = 12;
|
||||
wm831x->charger_irq_wake = 1;
|
||||
if (rev > 0) {
|
||||
wm831x->has_gpio_ena = 1;
|
||||
wm831x->has_cs_sts = 1;
|
||||
}
|
||||
//ILIM = 900ma
|
||||
ret = wm831x_reg_read(wm831x, WM831X_POWER_STATE) & 0xffff;
|
||||
wm831x_reg_write(wm831x, WM831X_POWER_STATE, (ret&0xfff8) | 0x04);
|
||||
|
||||
dev_info(wm831x->dev, "WM8310 revision %c\n", 'A' + rev);
|
||||
break;
|
||||
|
|
@ -1541,12 +1558,15 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
|
|||
dev_info(wm831x->dev, "WM8325 revision %c\n", 'A' + rev);
|
||||
break;
|
||||
|
||||
<<<<<<< HEAD
|
||||
case WM8326:
|
||||
parent = WM8326;
|
||||
wm831x->num_gpio = 12;
|
||||
dev_info(wm831x->dev, "WM8326 revision %c\n", 'A' + rev);
|
||||
break;
|
||||
|
||||
=======
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
default:
|
||||
dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret);
|
||||
ret = -EINVAL;
|
||||
|
|
@ -1632,7 +1652,13 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
|
|||
case WM8326:
|
||||
ret = mfd_add_devices(wm831x->dev, -1,
|
||||
wm8320_devs, ARRAY_SIZE(wm8320_devs),
|
||||
NULL, wm831x->irq_base);
|
||||
NULL, 0);
|
||||
break;
|
||||
|
||||
case WM8325:
|
||||
ret = mfd_add_devices(wm831x->dev, -1,
|
||||
wm8320_devs, ARRAY_SIZE(wm8320_devs),
|
||||
NULL, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -1658,7 +1684,11 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
|
|||
wm831x_otp_init(wm831x);
|
||||
|
||||
if (pdata && pdata->post_init) {
|
||||
wm831x_reg_unlock(wm831x);
|
||||
wm831x_set_bits(wm831x, WM831X_RESET_CONTROL,0x0010,0x0000);
|
||||
wm831x_set_bits(wm831x, WM831X_LDO_ENABLE,0Xf800,0Xf800);
|
||||
ret = pdata->post_init(wm831x);
|
||||
wm831x_reg_lock(wm831x);
|
||||
if (ret != 0) {
|
||||
dev_err(wm831x->dev, "post_init() failed: %d\n", ret);
|
||||
goto err_irq;
|
||||
|
|
@ -1688,6 +1718,22 @@ void wm831x_device_exit(struct wm831x *wm831x)
|
|||
int wm831x_device_suspend(struct wm831x *wm831x)
|
||||
{
|
||||
int reg, mask;
|
||||
int i;
|
||||
|
||||
//mask some intterupt avoid wakeing up system while suspending
|
||||
for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) {
|
||||
/* If there's been a change in the mask write it back
|
||||
* to the hardware. */
|
||||
//printk("irq_masks_cur[%d]=0x%x\n",i,wm831x->irq_masks_cur[i]);
|
||||
|
||||
if (wm831x->irq_masks_cur[i] != wm831x->irq_masks_cache[i]) {
|
||||
wm831x->irq_masks_cache[i] = wm831x->irq_masks_cur[i];
|
||||
wm831x_reg_write(wm831x,
|
||||
WM831X_INTERRUPT_STATUS_1_MASK + i,
|
||||
wm831x->irq_masks_cur[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* If the charger IRQs are a wake source then make sure we ack
|
||||
* them even if they're not actively being used (eg, no power
|
||||
|
|
@ -1720,6 +1766,102 @@ int wm831x_device_suspend(struct wm831x *wm831x)
|
|||
|
||||
return 0;
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
void wm831x_enter_sleep(void){
|
||||
#if 1//def CONFIG_RK2818_SOC_PM
|
||||
struct regulator *dcdc;
|
||||
int i;
|
||||
dcdc=regulator_get(NULL, "dcdc1");
|
||||
struct wm831x_dcdc *dc = regulator_get_drvdata(dcdc);
|
||||
struct wm831x *wm831x = dc->wm831x;
|
||||
if(wm831x){
|
||||
wm831x_set_bits(wm831x, WM831X_POWER_STATE, 0x4000, 0x4000); // SYSTEM SLEEP MODE
|
||||
for (i=0; i<5; i++)
|
||||
wm831x_reg_write(wm831x,WM831X_INTERRUPT_STATUS_1+i, 0xffff); // INTRUPT FLAG CLEAR
|
||||
|
||||
printk("%s:complete! \n",__func__);
|
||||
|
||||
}else{
|
||||
printk("%s:error!",__func__);
|
||||
}
|
||||
regulator_put(dcdc);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm831x_enter_sleep);
|
||||
|
||||
void wm831x_exit_sleep(void){
|
||||
#if 1//def CONFIG_RK2818_SOC_PM
|
||||
struct regulator *dcdc;
|
||||
dcdc=regulator_get(NULL, "dcdc1");
|
||||
struct wm831x_dcdc *dc = regulator_get_drvdata(dcdc);
|
||||
struct wm831x *wm831x = dc->wm831x;
|
||||
if(wm831x){
|
||||
wm831x_set_bits(wm831x, WM831X_POWER_STATE, 0x4000, 0); // SYSTEM ON MODE
|
||||
printk("%s:complete! \n",__func__);
|
||||
|
||||
}else{
|
||||
printk("%s:error!",__func__);
|
||||
}
|
||||
regulator_put(dcdc);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wm831x_exit_sleep);
|
||||
|
||||
int wm831x_device_shutdown(struct wm831x *wm831x)
|
||||
{
|
||||
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
|
||||
int ret = 0;
|
||||
|
||||
printk("pre WM831X_POWER_STATE = 0x%x\n", wm831x_reg_read(wm831x, WM831X_POWER_STATE));
|
||||
|
||||
if (pdata && pdata->last_deinit) {
|
||||
ret = pdata->last_deinit(wm831x);
|
||||
if (ret != 0) {
|
||||
dev_info(wm831x->dev, "last_deinit() failed: %d\n", ret);
|
||||
//goto err_irq;
|
||||
}
|
||||
}
|
||||
|
||||
//if(0 == reboot_cmd_get())
|
||||
{
|
||||
if(wm831x_set_bits(wm831x, WM831X_POWER_STATE, WM831X_CHIP_ON_MASK, 0) < 0)
|
||||
printk("%s wm831x_set_bits err\n", __FUNCTION__);
|
||||
//printk("post WM831X_POWER_STATE = 0x%x\n", wm831x_reg_read(wm831x, WM831X_POWER_STATE));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(wm831x_device_shutdown);
|
||||
|
||||
|
||||
int wm831x_read_usb(struct wm831x *wm831x)
|
||||
{
|
||||
int ret, usb_chg = 0, wall_chg = 0;
|
||||
|
||||
ret = wm831x_reg_read(wm831x, WM831X_SYSTEM_STATUS);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret & WM831X_PWR_USB)
|
||||
usb_chg = 1;
|
||||
if (ret & WM831X_PWR_WALL)
|
||||
wall_chg = 1;
|
||||
|
||||
return ((usb_chg | wall_chg) ? 1 : 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
int wm831x_device_restart(struct wm831x *wm831x)
|
||||
{
|
||||
wm831x_reg_write(wm831x,WM831X_RESET_ID, 0xffff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
|
||||
MODULE_DESCRIPTION("Core support for the WM831X AudioPlus PMIC");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <linux/mfd/wm831x/core.h>
|
||||
#include <linux/mfd/wm831x/pdata.h>
|
||||
|
|
@ -51,6 +52,7 @@ static int wm831x_i2c_write_device(struct wm831x *wm831x, unsigned short reg,
|
|||
int bytes, void *src)
|
||||
{
|
||||
struct i2c_client *i2c = wm831x->control_data;
|
||||
<<<<<<< HEAD
|
||||
struct i2c_msg xfer[2];
|
||||
int ret;
|
||||
|
||||
|
|
@ -70,6 +72,19 @@ static int wm831x_i2c_write_device(struct wm831x *wm831x, unsigned short reg,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret != 2)
|
||||
=======
|
||||
unsigned char msg[bytes + 2];
|
||||
int ret;
|
||||
|
||||
reg = cpu_to_be16(reg);
|
||||
memcpy(&msg[0], ®, 2);
|
||||
memcpy(&msg[2], src, bytes);
|
||||
|
||||
ret = i2c_master_send(i2c, msg, bytes + 2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret < bytes + 2)
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
|
|
@ -79,18 +94,44 @@ static int wm831x_i2c_probe(struct i2c_client *i2c,
|
|||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct wm831x *wm831x;
|
||||
<<<<<<< HEAD
|
||||
|
||||
=======
|
||||
int ret,gpio,irq;
|
||||
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
|
||||
if (wm831x == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(i2c, wm831x);
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
|
||||
gpio = i2c->irq;
|
||||
ret = gpio_request(gpio, "wm831x");
|
||||
if (ret) {
|
||||
printk( "failed to request rk gpio irq for wm831x \n");
|
||||
return ret;
|
||||
}
|
||||
gpio_pull_updown(gpio, GPIOPullUp);
|
||||
if (ret) {
|
||||
printk("failed to pull up gpio irq for wm831x \n");
|
||||
return ret;
|
||||
}
|
||||
irq = gpio_to_irq(gpio);
|
||||
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
wm831x->dev = &i2c->dev;
|
||||
wm831x->control_data = i2c;
|
||||
wm831x->read_dev = wm831x_i2c_read_device;
|
||||
wm831x->write_dev = wm831x_i2c_write_device;
|
||||
|
||||
<<<<<<< HEAD
|
||||
return wm831x_device_init(wm831x, id->driver_data, i2c->irq);
|
||||
=======
|
||||
return wm831x_device_init(wm831x, id->driver_data, irq);
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
}
|
||||
|
||||
static int wm831x_i2c_remove(struct i2c_client *i2c)
|
||||
|
|
@ -109,6 +150,33 @@ static int wm831x_i2c_suspend(struct device *dev)
|
|||
return wm831x_device_suspend(wm831x);
|
||||
}
|
||||
|
||||
static int wm831x_i2c_resume(struct device *dev)
|
||||
{
|
||||
struct wm831x *wm831x = dev_get_drvdata(dev);
|
||||
int i;
|
||||
//set some intterupt again while resume
|
||||
for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) {
|
||||
//printk("irq_masks_cur[%d]=0x%x\n",i,wm831x->irq_masks_cur[i]);
|
||||
|
||||
if (wm831x->irq_masks_cur[i] != wm831x->irq_masks_cache[i]) {
|
||||
wm831x->irq_masks_cache[i] = wm831x->irq_masks_cur[i];
|
||||
wm831x_reg_write(wm831x,
|
||||
WM831X_INTERRUPT_STATUS_1_MASK + i,
|
||||
wm831x->irq_masks_cur[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wm831x_i2c_shutdown(struct i2c_client *i2c)
|
||||
{
|
||||
struct wm831x *wm831x = i2c_get_clientdata(i2c);
|
||||
printk("%s\n", __FUNCTION__);
|
||||
wm831x_device_shutdown(wm831x);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id wm831x_i2c_id[] = {
|
||||
{ "wm8310", WM8310 },
|
||||
{ "wm8311", WM8311 },
|
||||
|
|
@ -123,6 +191,7 @@ MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
|
|||
|
||||
static const struct dev_pm_ops wm831x_pm_ops = {
|
||||
.suspend = wm831x_i2c_suspend,
|
||||
.resume = wm831x_i2c_resume,
|
||||
};
|
||||
|
||||
static struct i2c_driver wm831x_i2c_driver = {
|
||||
|
|
@ -133,6 +202,7 @@ static struct i2c_driver wm831x_i2c_driver = {
|
|||
},
|
||||
.probe = wm831x_i2c_probe,
|
||||
.remove = wm831x_i2c_remove,
|
||||
.shutdown = wm831x_i2c_shutdown,
|
||||
.id_table = wm831x_i2c_id,
|
||||
};
|
||||
|
||||
|
|
@ -140,6 +210,7 @@ static int __init wm831x_i2c_init(void)
|
|||
{
|
||||
int ret;
|
||||
|
||||
printk("%s \n", __FUNCTION__);
|
||||
ret = i2c_add_driver(&wm831x_i2c_driver);
|
||||
if (ret != 0)
|
||||
pr_err("Failed to register wm831x I2C driver: %d\n", ret);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,19 @@
|
|||
#include <linux/mfd/wm831x/irq.h>
|
||||
|
||||
#include <linux/delay.h>
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
#include <linux/wakelock.h>
|
||||
/*
|
||||
* Since generic IRQs don't currently support interrupt controllers on
|
||||
* interrupt driven buses we don't use genirq but instead provide an
|
||||
* interface that looks very much like the standard ones. This leads
|
||||
* to some bodges, including storing interrupt handler information in
|
||||
* the static irq_data table we use to look up the data for individual
|
||||
* interrupts, but hopefully won't last too long.
|
||||
*/
|
||||
#define WM831X_IRQ_TYPE IRQF_TRIGGER_LOW
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
|
||||
struct wm831x_irq_data {
|
||||
int primary;
|
||||
|
|
@ -32,6 +45,12 @@ struct wm831x_irq_data {
|
|||
int mask;
|
||||
};
|
||||
|
||||
struct wm831x_handle_irq
|
||||
{
|
||||
int irq;
|
||||
struct list_head queue;
|
||||
};
|
||||
|
||||
static struct wm831x_irq_data wm831x_irqs[] = {
|
||||
[WM831X_IRQ_TEMP_THW] = {
|
||||
.primary = WM831X_TEMP_INT,
|
||||
|
|
@ -373,6 +392,7 @@ static void wm831x_irq_enable(struct irq_data *data)
|
|||
data->irq);
|
||||
|
||||
wm831x->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
|
||||
//printk("%s:irq=%d\n",__FUNCTION__,irq);
|
||||
}
|
||||
|
||||
static void wm831x_irq_disable(struct irq_data *data)
|
||||
|
|
@ -382,6 +402,16 @@ static void wm831x_irq_disable(struct irq_data *data)
|
|||
data->irq);
|
||||
|
||||
wm831x->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
|
||||
//printk("%s:irq=%d\n",__FUNCTION__,irq);
|
||||
}
|
||||
|
||||
static void wm831x_irq_disable(unsigned int irq)
|
||||
{
|
||||
struct wm831x *wm831x = get_irq_chip_data(irq);
|
||||
struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, irq);
|
||||
|
||||
wm831x->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
|
||||
//printk("%s:irq=%d\n",__FUNCTION__,irq);
|
||||
}
|
||||
|
||||
static int wm831x_irq_set_type(struct irq_data *data, unsigned int type)
|
||||
|
|
@ -389,16 +419,21 @@ static int wm831x_irq_set_type(struct irq_data *data, unsigned int type)
|
|||
struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
|
||||
int val, irq;
|
||||
|
||||
<<<<<<< HEAD
|
||||
irq = data->irq - wm831x->irq_base;
|
||||
|
||||
if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11) {
|
||||
=======
|
||||
irq = irq - wm831x->irq_base;
|
||||
if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_12) {
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
/* Ignore internal-only IRQs */
|
||||
if (irq >= 0 && irq < WM831X_NUM_IRQS)
|
||||
return 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
//printk("wm831x_irq_set_type:type=%x,irq=%d\n",type,irq);
|
||||
switch (type) {
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
val = WM831X_GPN_INT_MODE;
|
||||
|
|
@ -413,29 +448,106 @@ static int wm831x_irq_set_type(struct irq_data *data, unsigned int type)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + irq,
|
||||
return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + irq - 1,
|
||||
WM831X_GPN_INT_MODE | WM831X_GPN_POL, val);
|
||||
}
|
||||
|
||||
static int wm831x_irq_set_wake(unsigned irq, unsigned state)
|
||||
{
|
||||
struct wm831x *wm831x = get_irq_chip_data(irq);
|
||||
|
||||
//only wm831x irq
|
||||
if ((irq > wm831x->irq_base + WM831X_IRQ_TEMP_THW) &&( irq < wm831x->irq_base + WM831X_NUM_IRQS))
|
||||
{
|
||||
if(state)
|
||||
wm831x_irq_unmask(irq);
|
||||
else
|
||||
wm831x_irq_mask(irq);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
printk("%s:irq number err!irq=%d\n",__FUNCTION__,irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static struct irq_chip wm831x_irq_chip = {
|
||||
<<<<<<< HEAD
|
||||
.name = "wm831x",
|
||||
.irq_bus_lock = wm831x_irq_lock,
|
||||
.irq_bus_sync_unlock = wm831x_irq_sync_unlock,
|
||||
.irq_disable = wm831x_irq_disable,
|
||||
.irq_enable = wm831x_irq_enable,
|
||||
.irq_set_type = wm831x_irq_set_type,
|
||||
=======
|
||||
.name = "wm831x",
|
||||
.bus_lock = wm831x_irq_lock,
|
||||
.bus_sync_unlock = wm831x_irq_sync_unlock,
|
||||
.disable = wm831x_irq_disable,
|
||||
.mask = wm831x_irq_mask,
|
||||
.unmask = wm831x_irq_unmask,
|
||||
.set_type = wm831x_irq_set_type,
|
||||
.set_wake = wm831x_irq_set_wake,
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
};
|
||||
|
||||
/* The processing of the primary interrupt occurs in a thread so that
|
||||
* we can interact with the device over I2C or SPI. */
|
||||
static irqreturn_t wm831x_irq_thread(int irq, void *data)
|
||||
#if WM831X_IRQ_LIST
|
||||
static void wm831x_handle_worker(struct work_struct *work)
|
||||
{
|
||||
struct wm831x *wm831x = data;
|
||||
struct wm831x *wm831x = container_of(work, struct wm831x, handle_work);
|
||||
int irq;
|
||||
|
||||
while (1) {
|
||||
unsigned long flags;
|
||||
struct wm831x_handle_irq *hd = NULL;
|
||||
|
||||
spin_lock_irqsave(&wm831x->work_lock, flags);
|
||||
if (!list_empty(&wm831x->handle_queue)) {
|
||||
hd = list_first_entry(&wm831x->handle_queue, struct wm831x_handle_irq, queue);
|
||||
list_del(&hd->queue);
|
||||
}
|
||||
spin_unlock_irqrestore(&wm831x->work_lock, flags);
|
||||
|
||||
if (!hd) // trans_queue empty
|
||||
break;
|
||||
|
||||
irq = hd->irq; //get wm831x intterupt status
|
||||
//printk("%s:irq=%d\n",__FUNCTION__,irq);
|
||||
|
||||
/*start to handle wm831x intterupt*/
|
||||
handle_nested_irq(wm831x->irq_base + irq);
|
||||
|
||||
kfree(hd);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Main interrupt handling occurs in a workqueue since we need
|
||||
* interrupts enabled to interact with the chip. */
|
||||
static void wm831x_irq_worker(struct work_struct *work)
|
||||
{
|
||||
struct wm831x *wm831x = container_of(work, struct wm831x, irq_work);
|
||||
unsigned int i;
|
||||
int primary;
|
||||
int status_regs[WM831X_NUM_IRQ_REGS] = { 0 };
|
||||
int read[WM831X_NUM_IRQ_REGS] = { 0 };
|
||||
int *status;
|
||||
unsigned long flags;
|
||||
struct wm831x_handle_irq *hd;
|
||||
int ret;
|
||||
|
||||
#if (WM831X_IRQ_TYPE != IRQF_TRIGGER_LOW)
|
||||
/*mask wm831x irq at first*/
|
||||
ret = wm831x_set_bits(wm831x, WM831X_IRQ_CONFIG,
|
||||
WM831X_IRQ_IM_MASK, WM831X_IRQ_IM_EANBLE);
|
||||
if (ret < 0) {
|
||||
dev_err(wm831x->dev, "Failed to mask irq: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
primary = wm831x_reg_read(wm831x, WM831X_SYSTEM_INTERRUPTS);
|
||||
if (primary < 0) {
|
||||
|
|
@ -443,6 +555,8 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
|
|||
primary);
|
||||
goto out;
|
||||
}
|
||||
|
||||
mutex_lock(&wm831x->irq_lock);
|
||||
|
||||
/* The touch interrupts are visible in the primary register as
|
||||
* an optimisation; open code this to avoid complicating the
|
||||
|
|
@ -458,10 +572,10 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) {
|
||||
int offset = wm831x_irqs[i].reg - 1;
|
||||
|
||||
|
||||
if (!(primary & wm831x_irqs[i].primary))
|
||||
continue;
|
||||
|
||||
|
||||
status = &status_regs[offset];
|
||||
|
||||
/* Hopefully there should only be one register to read
|
||||
|
|
@ -473,7 +587,7 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
|
|||
dev_err(wm831x->dev,
|
||||
"Failed to read IRQ status: %d\n",
|
||||
*status);
|
||||
goto out;
|
||||
goto out_lock;
|
||||
}
|
||||
|
||||
read[offset] = 1;
|
||||
|
|
@ -482,11 +596,39 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
|
|||
/* Report it if it isn't masked, or forget the status. */
|
||||
if ((*status & ~wm831x->irq_masks_cur[offset])
|
||||
& wm831x_irqs[i].mask)
|
||||
{
|
||||
#if WM831X_IRQ_LIST
|
||||
/*add intterupt handle on list*/
|
||||
hd = kzalloc(sizeof(struct wm831x_handle_irq), GFP_KERNEL);
|
||||
if (!hd)
|
||||
{
|
||||
printk("err:%s:ENOMEM\n",__FUNCTION__);
|
||||
return ;
|
||||
}
|
||||
|
||||
if(i == WM831X_IRQ_ON)
|
||||
wake_lock(&wm831x->handle_wake); //keep wake while handle WM831X_IRQ_ON
|
||||
hd->irq = i;
|
||||
spin_lock_irqsave(&wm831x->work_lock, flags);
|
||||
list_add_tail(&hd->queue, &wm831x->handle_queue);
|
||||
spin_unlock_irqrestore(&wm831x->work_lock, flags);
|
||||
queue_work(wm831x->handle_wq, &wm831x->handle_work);
|
||||
|
||||
#else
|
||||
if(i == WM831X_IRQ_ON)
|
||||
wake_lock(&wm831x->handle_wake); //keep wake while handle WM831X_IRQ_ON
|
||||
handle_nested_irq(wm831x->irq_base + i);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
else
|
||||
*status &= ~wm831x_irqs[i].mask;
|
||||
}
|
||||
|
||||
|
||||
out_lock:
|
||||
mutex_unlock(&wm831x->irq_lock);
|
||||
|
||||
out:
|
||||
/* Touchscreen interrupts are handled specially in the driver */
|
||||
status_regs[0] &= ~(WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT);
|
||||
|
|
@ -496,7 +638,45 @@ out:
|
|||
wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1 + i,
|
||||
status_regs[i]);
|
||||
}
|
||||
|
||||
#if (WM831X_IRQ_TYPE != IRQF_TRIGGER_LOW)
|
||||
ret = wm831x_set_bits(wm831x, WM831X_IRQ_CONFIG,
|
||||
WM831X_IRQ_IM_MASK, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(wm831x->dev, "Failed to open irq: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
#if (WM831X_IRQ_TYPE == IRQF_TRIGGER_LOW)
|
||||
enable_irq(wm831x->irq);
|
||||
#endif
|
||||
wake_unlock(&wm831x->irq_wake);
|
||||
|
||||
}
|
||||
/* The processing of the primary interrupt occurs in a thread so that
|
||||
* we can interact with the device over I2C or SPI. */
|
||||
static irqreturn_t wm831x_irq_thread(int irq, void *data)
|
||||
{
|
||||
struct wm831x *wm831x = data;
|
||||
int msdelay = 0;
|
||||
/* Shut the interrupt to the CPU up and schedule the actual
|
||||
* handler; we can't check that the IRQ is asserted. */
|
||||
#if (WM831X_IRQ_TYPE == IRQF_TRIGGER_LOW)
|
||||
disable_irq_nosync(irq);
|
||||
#endif
|
||||
wake_lock(&wm831x->irq_wake);
|
||||
if(wm831x->flag_suspend)
|
||||
{
|
||||
spin_lock(&wm831x->flag_lock);
|
||||
wm831x->flag_suspend = 0;
|
||||
spin_unlock(&wm831x->flag_lock);
|
||||
msdelay = 50; //wait for spi/i2c resume
|
||||
printk("%s:msdelay=%d\n",__FUNCTION__,msdelay);
|
||||
}
|
||||
else
|
||||
msdelay = 0;
|
||||
|
||||
queue_delayed_work(wm831x->irq_wq, &wm831x->irq_work, msecs_to_jiffies(msdelay));
|
||||
//printk("%s\n",__FUNCTION__);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
|
@ -504,7 +684,7 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
|
|||
{
|
||||
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
|
||||
int i, cur_irq, ret;
|
||||
|
||||
printk( "wm831x_irq_init:irq=%d,%d\n",irq,pdata->irq_base);
|
||||
mutex_init(&wm831x->irq_lock);
|
||||
|
||||
/* Mask the individual interrupt sources */
|
||||
|
|
@ -521,6 +701,7 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
|
|||
return 0;
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
if (pdata->irq_cmos)
|
||||
i = 0;
|
||||
else
|
||||
|
|
@ -540,9 +721,32 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
|
|||
ret);
|
||||
}
|
||||
|
||||
wm831x->irq = irq;
|
||||
wm831x->irq_base = pdata->irq_base;
|
||||
=======
|
||||
wm831x->irq_wq = create_singlethread_workqueue("wm831x-irq");
|
||||
if (!wm831x->irq_wq) {
|
||||
dev_err(wm831x->dev, "Failed to allocate IRQ worker\n");
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
wm831x->irq = irq;
|
||||
wm831x->flag_suspend = 0;
|
||||
wm831x->irq_base = pdata->irq_base;
|
||||
INIT_DELAYED_WORK(&wm831x->irq_work, wm831x_irq_worker);
|
||||
wake_lock_init(&wm831x->irq_wake, WAKE_LOCK_SUSPEND, "wm831x_irq_wake");
|
||||
wake_lock_init(&wm831x->handle_wake, WAKE_LOCK_SUSPEND, "wm831x_handle_wake");
|
||||
#if WM831X_IRQ_LIST
|
||||
wm831x->handle_wq = create_rt_workqueue("wm831x_handle_wq");
|
||||
if (!wm831x->handle_wq) {
|
||||
printk("cannot create workqueue\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
INIT_WORK(&wm831x->handle_work, wm831x_handle_worker);
|
||||
INIT_LIST_HEAD(&wm831x->handle_queue);
|
||||
|
||||
#endif
|
||||
|
||||
/* Register them with genirq */
|
||||
for (cur_irq = wm831x->irq_base;
|
||||
cur_irq < ARRAY_SIZE(wm831x_irqs) + wm831x->irq_base;
|
||||
|
|
@ -560,6 +764,7 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
|
|||
irq_set_noprobe(cur_irq);
|
||||
#endif
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
|
||||
if (irq) {
|
||||
ret = request_threaded_irq(irq, NULL, wm831x_irq_thread,
|
||||
|
|
@ -577,6 +782,24 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
|
|||
|
||||
|
||||
|
||||
=======
|
||||
#if (WM831X_IRQ_TYPE == IRQF_TRIGGER_LOW)
|
||||
ret = request_threaded_irq(wm831x->irq, wm831x_irq_thread, NULL,
|
||||
IRQF_TRIGGER_LOW| IRQF_ONESHOT,//IRQF_TRIGGER_FALLING, //
|
||||
"wm831x", wm831x);
|
||||
#else
|
||||
ret = request_threaded_irq(wm831x->irq, wm831x_irq_thread, NULL,
|
||||
IRQF_TRIGGER_FALLING, //IRQF_TRIGGER_LOW| IRQF_ONESHOT,//
|
||||
"wm831x", wm831x);
|
||||
#endif
|
||||
if (ret != 0) {
|
||||
dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n",
|
||||
wm831x->irq, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
enable_irq_wake(wm831x->irq); // so wm831x irq can wake up system
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
/* Enable top level interrupts, we mask at secondary level */
|
||||
wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <linux/mfd/wm831x/core.h>
|
||||
|
||||
|
|
@ -28,14 +29,24 @@ static int wm831x_spi_read_device(struct wm831x *wm831x, unsigned short reg,
|
|||
|
||||
/* Go register at a time */
|
||||
for (r = reg; r < reg + (bytes / 2); r++) {
|
||||
<<<<<<< HEAD
|
||||
tx_val = r | 0x8000;
|
||||
|
||||
=======
|
||||
tx_val = cpu_to_be16(r | 0x8000);
|
||||
//printk("read:reg=0x%x,",reg);
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
ret = spi_write_then_read(wm831x->control_data,
|
||||
(u8 *)&tx_val, 2, (u8 *)d, 2);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
<<<<<<< HEAD
|
||||
|
||||
*d = be16_to_cpu(*d);
|
||||
=======
|
||||
//printk("rec=0x%x\n",be16_to_cpu(*d));
|
||||
//*d = be16_to_cpu(*d);
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
|
||||
d++;
|
||||
}
|
||||
|
|
@ -53,9 +64,15 @@ static int wm831x_spi_write_device(struct wm831x *wm831x, unsigned short reg,
|
|||
|
||||
/* Go register at a time */
|
||||
for (r = reg; r < reg + (bytes / 2); r++) {
|
||||
<<<<<<< HEAD
|
||||
data[0] = r;
|
||||
data[1] = *s++;
|
||||
|
||||
=======
|
||||
data[0] = cpu_to_be16(r);
|
||||
data[1] = *s++;
|
||||
//printk("write:reg=0x%x,send=0x%x\n",reg, data[0]);
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
ret = spi_write(spi, (char *)&data, sizeof(data));
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
|
@ -68,7 +85,12 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi)
|
|||
{
|
||||
struct wm831x *wm831x;
|
||||
enum wm831x_parent type;
|
||||
<<<<<<< HEAD
|
||||
|
||||
=======
|
||||
int ret,gpio,irq;
|
||||
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
/* Currently SPI support for ID tables is unmerged, we're faking it */
|
||||
if (strcmp(spi->modalias, "wm8310") == 0)
|
||||
type = WM8310;
|
||||
|
|
@ -96,13 +118,33 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi)
|
|||
spi->bits_per_word = 16;
|
||||
spi->mode = SPI_MODE_0;
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
gpio = spi->irq;
|
||||
ret = gpio_request(gpio, "wm831x");
|
||||
if (ret) {
|
||||
printk( "failed to request rk gpio irq for wm831x \n");
|
||||
return ret;
|
||||
}
|
||||
gpio_pull_updown(gpio, GPIOPullUp);
|
||||
if (ret) {
|
||||
printk("failed to pull up gpio irq for wm831x \n");
|
||||
return ret;
|
||||
}
|
||||
irq = gpio_to_irq(gpio);
|
||||
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
dev_set_drvdata(&spi->dev, wm831x);
|
||||
wm831x->dev = &spi->dev;
|
||||
wm831x->control_data = spi;
|
||||
wm831x->read_dev = wm831x_spi_read_device;
|
||||
wm831x->write_dev = wm831x_spi_write_device;
|
||||
|
||||
<<<<<<< HEAD
|
||||
return wm831x_device_init(wm831x, type, spi->irq);
|
||||
=======
|
||||
return wm831x_device_init(wm831x, type, irq);
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
}
|
||||
|
||||
static int __devexit wm831x_spi_remove(struct spi_device *spi)
|
||||
|
|
@ -118,6 +160,10 @@ static int wm831x_spi_suspend(struct device *dev)
|
|||
{
|
||||
struct wm831x *wm831x = dev_get_drvdata(dev);
|
||||
|
||||
spin_lock(&wm831x->flag_lock);
|
||||
wm831x->flag_suspend = 1;
|
||||
spin_unlock(&wm831x->flag_lock);
|
||||
|
||||
return wm831x_device_suspend(wm831x);
|
||||
}
|
||||
|
||||
|
|
|
|||
0
drivers/mfd/wm8994-core.c
Executable file → Normal file
0
drivers/mfd/wm8994-core.c
Executable file → Normal file
21
drivers/misc/Kconfig
Executable file → Normal file
21
drivers/misc/Kconfig
Executable file → Normal file
|
|
@ -535,9 +535,30 @@ config APANIC_PLABEL
|
|||
If your platform uses a different flash partition label for storing
|
||||
crashdumps, enter it here.
|
||||
|
||||
config STE
|
||||
bool "STE modem control driver"
|
||||
|
||||
config MTK23D
|
||||
bool "MTK6223D modem control driver"
|
||||
|
||||
config FM580X
|
||||
bool "FM rda580x driver"
|
||||
|
||||
config MU509
|
||||
bool "MU509 modem control driver"
|
||||
|
||||
config MW100
|
||||
bool "MW100 modem control driver"
|
||||
|
||||
config RK29_NEWTON
|
||||
bool "RK29_NEWTON misc driver"
|
||||
|
||||
source "drivers/misc/c2port/Kconfig"
|
||||
source "drivers/misc/eeprom/Kconfig"
|
||||
source "drivers/misc/cb710/Kconfig"
|
||||
source "drivers/misc/rk29_modem/Kconfig"
|
||||
source "drivers/misc/gps/Kconfig"
|
||||
source "drivers/misc/mpu3050/Kconfig"
|
||||
source "drivers/misc/iwmc3200top/Kconfig"
|
||||
source "drivers/misc/ti-st/Kconfig"
|
||||
source "drivers/misc/lis3lv02d/Kconfig"
|
||||
|
|
|
|||
9
drivers/misc/Makefile
Executable file → Normal file
9
drivers/misc/Makefile
Executable file → Normal file
|
|
@ -52,3 +52,12 @@ obj-y += carma/
|
|||
obj-$(CONFIG_WL127X_RFKILL) += wl127x-rfkill.o
|
||||
obj-$(CONFIG_APANIC) += apanic.o
|
||||
obj-$(CONFIG_SENSORS_AK8975) += akm8975.o
|
||||
obj-$(CONFIG_MTK23D) += mtk23d.o
|
||||
obj-$(CONFIG_FM580X) += fm580x.o
|
||||
obj-$(CONFIG_MU509) += mu509.o
|
||||
obj-$(CONFIG_MW100) += MW100.o
|
||||
obj-$(CONFIG_STE) += ste.o
|
||||
obj-$(CONFIG_RK29_SUPPORT_MODEM) += rk29_modem/
|
||||
obj-$(CONFIG_GPS_GNS7560) += gps/
|
||||
obj-y += mpu3050/
|
||||
obj-$(CONFIG_RK29_NEWTON) += newton.o
|
||||
|
|
|
|||
|
|
@ -193,8 +193,13 @@ static int apanic_proc_read(char *buffer, char **start, off_t offset,
|
|||
ctx->mtd->writesize,
|
||||
&len, ctx->bounce);
|
||||
|
||||
#ifdef CONFIG_MTD_RKNAND
|
||||
if (count > (ctx->mtd->writesize - page_offset))
|
||||
count = ctx->mtd->writesize - page_offset;
|
||||
#else
|
||||
if (page_offset)
|
||||
count -= page_offset;
|
||||
#endif
|
||||
memcpy(buffer, ctx->bounce + page_offset, count);
|
||||
|
||||
*start = count;
|
||||
|
|
@ -209,6 +214,11 @@ static int apanic_proc_read(char *buffer, char **start, off_t offset,
|
|||
static void mtd_panic_erase(void)
|
||||
{
|
||||
struct apanic_data *ctx = &drv_ctx;
|
||||
#ifdef CONFIG_MTD_RKNAND
|
||||
size_t wlen;
|
||||
memset(ctx->bounce, 0, ctx->mtd->writesize);
|
||||
ctx->mtd->write(ctx->mtd, 0, ctx->mtd->writesize, &wlen, ctx->bounce);
|
||||
#else
|
||||
struct erase_info erase;
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
wait_queue_head_t wait_q;
|
||||
|
|
@ -260,6 +270,7 @@ static void mtd_panic_erase(void)
|
|||
schedule();
|
||||
remove_wait_queue(&wait_q, &wait);
|
||||
}
|
||||
#endif
|
||||
printk(KERN_DEBUG "apanic: %s partition erased\n",
|
||||
CONFIG_APANIC_PLABEL);
|
||||
out:
|
||||
|
|
@ -331,14 +342,18 @@ static void mtd_panic_notify_add(struct mtd_info *mtd)
|
|||
|
||||
if (hdr->magic != PANIC_MAGIC) {
|
||||
printk(KERN_INFO "apanic: No panic data available\n");
|
||||
#ifndef CONFIG_MTD_RKNAND
|
||||
mtd_panic_erase();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (hdr->version != PHDR_VERSION) {
|
||||
printk(KERN_INFO "apanic: Version mismatch (%d != %d)\n",
|
||||
hdr->version, PHDR_VERSION);
|
||||
#ifndef CONFIG_MTD_RKNAND
|
||||
mtd_panic_erase();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -378,8 +393,10 @@ static void mtd_panic_notify_add(struct mtd_info *mtd)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_MTD_RKNAND
|
||||
if (!proc_entry_created)
|
||||
mtd_panic_erase();
|
||||
#endif
|
||||
|
||||
return;
|
||||
out_err:
|
||||
|
|
@ -511,7 +528,7 @@ static int apanic(struct notifier_block *this, unsigned long event,
|
|||
printk(KERN_EMERG "Crash partition in use!\n");
|
||||
goto out;
|
||||
}
|
||||
console_offset = ctx->mtd->writesize;
|
||||
console_offset = ctx->mtd->erasesize;
|
||||
|
||||
/*
|
||||
* Write out the console
|
||||
|
|
|
|||
|
|
@ -1087,8 +1087,8 @@ static long pmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
region.offset = pmem_start_addr(id, data);
|
||||
region.len = pmem_len(id, data);
|
||||
}
|
||||
printk(KERN_INFO "pmem: request for physical address of pmem region "
|
||||
"from process %d.\n", current->pid);
|
||||
//printk(KERN_INFO "pmem: request for physical address of pmem region "
|
||||
// "from process %d.\n", current->pid);
|
||||
if (copy_to_user((void __user *)arg, ®ion,
|
||||
sizeof(struct pmem_region)))
|
||||
return -EFAULT;
|
||||
|
|
|
|||
|
|
@ -521,6 +521,13 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
|
|||
return result;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) //Deleted by xbw@2011-03-21
|
||||
//static u32 get_card_status(struct mmc_card *card, struct request *req)
|
||||
//{
|
||||
// return 0;
|
||||
//}
|
||||
|
||||
#else
|
||||
static u32 get_card_status(struct mmc_card *card, struct request *req)
|
||||
{
|
||||
struct mmc_command cmd = {0};
|
||||
|
|
@ -532,10 +539,11 @@ static u32 get_card_status(struct mmc_card *card, struct request *req)
|
|||
cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
|
||||
err = mmc_wait_for_cmd(card->host, &cmd, 0);
|
||||
if (err)
|
||||
printk(KERN_ERR "%s: error %d sending status command",
|
||||
printk(KERN_DEBUG "%s: error %d sending status command",
|
||||
req->rq_disk->disk_name, err);
|
||||
return cmd.resp[0];
|
||||
}
|
||||
#endif
|
||||
|
||||
static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
|
||||
{
|
||||
|
|
@ -689,6 +697,10 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
|
|||
brq.mrq.cmd = &brq.cmd;
|
||||
brq.mrq.data = &brq.data;
|
||||
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
brq.cmd.retries = 2; //suppot retry read-write; added by xbw@2011-03-21
|
||||
#endif
|
||||
|
||||
brq.cmd.arg = blk_rq_pos(req);
|
||||
if (!mmc_card_blockaddr(card))
|
||||
brq.cmd.arg <<= 9;
|
||||
|
|
@ -799,6 +811,11 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
|
|||
|
||||
mmc_queue_bounce_post(mq);
|
||||
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
//not turn CMD18 to CMD17. deleted by xbw at 2011-04-21
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Check for errors here, but don't jump to cmd_err
|
||||
* until later as we need to wait for the card to leave
|
||||
|
|
@ -808,7 +825,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
|
|||
brq.data.error || brq.stop.error) {
|
||||
if (brq.data.blocks > 1 && rq_data_dir(req) == READ) {
|
||||
/* Redo read one sector at a time */
|
||||
printk(KERN_WARNING "%s: retrying using single "
|
||||
printk(KERN_DEBUG "%s: retrying using single "
|
||||
"block read\n", req->rq_disk->disk_name);
|
||||
disable_multi = 1;
|
||||
continue;
|
||||
|
|
@ -817,6 +834,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
|
|||
} else if (disable_multi == 1) {
|
||||
disable_multi = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (brq.sbc.error) {
|
||||
printk(KERN_ERR "%s: error %d sending SET_BLOCK_COUNT "
|
||||
|
|
@ -826,7 +844,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
|
|||
}
|
||||
|
||||
if (brq.cmd.error) {
|
||||
printk(KERN_ERR "%s: error %d sending read/write "
|
||||
printk(KERN_DEBUG "%s: error %d sending read/write "
|
||||
"command, response %#x, card status %#x\n",
|
||||
req->rq_disk->disk_name, brq.cmd.error,
|
||||
brq.cmd.resp[0], status);
|
||||
|
|
@ -836,7 +854,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
|
|||
if (brq.data.error == -ETIMEDOUT && brq.mrq.stop)
|
||||
/* 'Stop' response contains card status */
|
||||
status = brq.mrq.stop->resp[0];
|
||||
printk(KERN_ERR "%s: error %d transferring data,"
|
||||
printk(KERN_DEBUG "%s: error %d transferring data,"
|
||||
" sector %u, nr %u, card status %#x\n",
|
||||
req->rq_disk->disk_name, brq.data.error,
|
||||
(unsigned)blk_rq_pos(req),
|
||||
|
|
@ -844,12 +862,16 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
|
|||
}
|
||||
|
||||
if (brq.stop.error) {
|
||||
printk(KERN_ERR "%s: error %d sending stop command, "
|
||||
printk(KERN_DEBUG "%s: error %d sending stop command, "
|
||||
"response %#x, card status %#x\n",
|
||||
req->rq_disk->disk_name, brq.stop.error,
|
||||
brq.stop.resp[0], status);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
//Deleted by xbw@2011-03-21
|
||||
|
||||
#else
|
||||
if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
|
||||
do {
|
||||
int err;
|
||||
|
|
@ -859,7 +881,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
|
|||
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
|
||||
err = mmc_wait_for_cmd(card->host, &cmd, 5);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: error %d requesting status\n",
|
||||
printk(KERN_DEBUG "%s: error %d requesting status\n",
|
||||
req->rq_disk->disk_name, err);
|
||||
goto cmd_err;
|
||||
}
|
||||
|
|
@ -879,6 +901,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
|
|||
goto cmd_err;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (brq.cmd.error || brq.stop.error || brq.data.error) {
|
||||
if (rq_data_dir(req) == READ) {
|
||||
|
|
@ -1063,6 +1086,11 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
|
|||
snprintf(md->disk->disk_name, sizeof(md->disk->disk_name),
|
||||
"mmcblk%d%s", md->name_idx, subname ? subname : "");
|
||||
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
printk("%s..%d **** devidx=%d, dev_use[0]=%lu, disk_name=%s *** ==xbw[%s]==\n",\
|
||||
__FUNCTION__,__LINE__, devidx, dev_use[0], md->disk->disk_name,mmc_hostname(card->host));
|
||||
#endif
|
||||
|
||||
blk_queue_logical_block_size(md->queue.queue, 512);
|
||||
set_capacity(md->disk, size);
|
||||
|
||||
|
|
|
|||
|
|
@ -215,6 +215,9 @@ static void mmc_wait_done(struct mmc_request *mrq)
|
|||
*/
|
||||
void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
|
||||
{
|
||||
unsigned long datasize, waittime = 0xFFFF;
|
||||
u32 multi, unit;
|
||||
|
||||
DECLARE_COMPLETION_ONSTACK(complete);
|
||||
|
||||
mrq->done_data = &complete;
|
||||
|
|
@ -222,7 +225,47 @@ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
|
|||
|
||||
mmc_start_request(host, mrq);
|
||||
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
if( strncmp( mmc_hostname(host) ,"mmc0" , strlen("mmc0")) )
|
||||
{
|
||||
multi = (mrq->cmd->retries>0)?mrq->cmd->retries:1;
|
||||
waittime = wait_for_completion_timeout(&complete,HZ*7*multi); //sdio; for cmd dead. Modifyed by xbw at 2011-06-02
|
||||
}
|
||||
else
|
||||
{
|
||||
//calculate the timeout value for SDMMC; added by xbw at 2011-09-27
|
||||
if(mrq->data)
|
||||
{
|
||||
unit = 3*(1<<20);// unit=3MB
|
||||
datasize = mrq->data->blksz*mrq->data->blocks;
|
||||
multi = datasize/unit;
|
||||
multi += (datasize%unit)?1:0;
|
||||
multi = (multi>0) ? multi : 1;
|
||||
multi += (mrq->cmd->retries>0)?1:0;
|
||||
waittime = wait_for_completion_timeout(&complete,HZ*7*multi); //It should be longer than bottom driver's time,due to the sum of two cmd time.
|
||||
//modifyed by xbw at 2011-10-08
|
||||
//
|
||||
//example:
|
||||
//rk29_sdmmc_request_end..2336... CMD12 wait busy timeout!!!!! ====xbw=[sd_mmc]====
|
||||
//mmc_wait_for_req..236.. !!!!! wait for CMD25 timeout ===xbw[mmc0]===
|
||||
}
|
||||
else
|
||||
{
|
||||
multi = (mrq->cmd->retries>0)?mrq->cmd->retries:1;
|
||||
waittime = wait_for_completion_timeout(&complete,HZ*7*multi);
|
||||
}
|
||||
}
|
||||
|
||||
if(waittime <= 1)
|
||||
{
|
||||
host->doneflag = 0;
|
||||
mrq->cmd->error = -EIO;
|
||||
printk("%s..%d.. !!!!! wait for CMD%d timeout ===xbw[%s]===\n",\
|
||||
__FUNCTION__, __LINE__, mrq->cmd->opcode, mmc_hostname(host));
|
||||
}
|
||||
#else
|
||||
wait_for_completion(&complete);
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(mmc_wait_for_req);
|
||||
|
|
@ -1869,6 +1912,11 @@ int mmc_resume_host(struct mmc_host *host)
|
|||
}
|
||||
}
|
||||
BUG_ON(!host->bus_ops->resume);
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
//panic if the card is being removed during the resume, deleted by xbw at 2011-06-20
|
||||
host->bus_ops->resume(host);
|
||||
|
||||
#else
|
||||
err = host->bus_ops->resume(host);
|
||||
if (err) {
|
||||
printk(KERN_WARNING "%s: error %d during resume "
|
||||
|
|
@ -1876,6 +1924,7 @@ int mmc_resume_host(struct mmc_host *host)
|
|||
mmc_hostname(host), err);
|
||||
err = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
host->pm_flags &= ~MMC_PM_KEEP_POWER;
|
||||
mmc_bus_put(host);
|
||||
|
|
|
|||
|
|
@ -559,7 +559,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
|||
/* The extra bit indicates that we support high capacity */
|
||||
err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr);
|
||||
if (err)
|
||||
{
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
printk("%s..%d.. ====*Identify the card as MMC , but OCR error, so fail to initialize.===xbw[%s]===\n",\
|
||||
__FUNCTION__, __LINE__, mmc_hostname(host));
|
||||
#endif
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* For SPI, enable CRC as appropriate.
|
||||
|
|
@ -734,6 +740,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
|||
if (max_dtr > card->ext_csd.hs_max_dtr)
|
||||
max_dtr = card->ext_csd.hs_max_dtr;
|
||||
} else if (max_dtr > card->csd.max_dtr) {
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
//in order to expand the compatibility of card. Added by xbw@2011-03-21
|
||||
card->csd.max_dtr = (card->csd.max_dtr > MMC_FPP_FREQ) ? MMC_FPP_FREQ : (card->csd.max_dtr);
|
||||
#endif
|
||||
max_dtr = card->csd.max_dtr;
|
||||
}
|
||||
|
||||
|
|
@ -1012,6 +1022,9 @@ int mmc_attach_mmc(struct mmc_host *host)
|
|||
{
|
||||
int err;
|
||||
u32 ocr;
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
int retry_times = 3;
|
||||
#endif
|
||||
|
||||
BUG_ON(!host);
|
||||
WARN_ON(!host->claimed);
|
||||
|
|
@ -1062,10 +1075,34 @@ int mmc_attach_mmc(struct mmc_host *host)
|
|||
goto err;
|
||||
|
||||
mmc_release_host(host);
|
||||
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
//modifyed by xbw at 2011--04-11
|
||||
Retry_add:
|
||||
err = mmc_add_card(host->card);
|
||||
mmc_claim_host(host);
|
||||
if (err)
|
||||
{
|
||||
//retry add the card; Added by xbw
|
||||
if((--retry_times >= 0))
|
||||
{
|
||||
printk("\n%s..%s..%d ****error in add partition, so retry. ===xbw[%s]===\n",__FUNCTION__,__FILE__,__LINE__, mmc_hostname(host));
|
||||
/* sleep some time */
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(HZ/2);
|
||||
|
||||
goto Retry_add;
|
||||
}
|
||||
|
||||
goto remove_card;
|
||||
|
||||
}
|
||||
#else
|
||||
err = mmc_add_card(host->card);
|
||||
mmc_claim_host(host);
|
||||
if (err)
|
||||
goto remove_card;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -718,8 +718,13 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
|
|||
|
||||
try_again:
|
||||
err = mmc_send_app_op_cond(host, ocr, rocr);
|
||||
if (err)
|
||||
if (err) {
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
printk("%s..%d.. ====*Identify the card as SD , but OCR error, so fail to initialize.===xbw[%s]===\n", \
|
||||
__FUNCTION__, __LINE__, mmc_hostname(host));
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* In case CCS and S18A in the response is set, start Signal Voltage
|
||||
|
|
@ -807,6 +812,13 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
|
|||
printk(KERN_WARNING
|
||||
"%s: read switch failed (attempt %d)\n",
|
||||
mmc_hostname(host), retries);
|
||||
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
if(0 == host->re_initialized_flags)
|
||||
{
|
||||
break; //Added by xbw at 2011-06-21
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
|
@ -859,6 +871,11 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
|
|||
if (max_dtr > card->sw_caps.hs_max_dtr)
|
||||
max_dtr = card->sw_caps.hs_max_dtr;
|
||||
} else if (max_dtr > card->csd.max_dtr) {
|
||||
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
//in order to expand the compatibility of card. Added by xbw@2011-03-21
|
||||
card->csd.max_dtr = (card->csd.max_dtr > SD_FPP_FREQ) ? SD_FPP_FREQ : (card->csd.max_dtr);
|
||||
#endif
|
||||
max_dtr = card->csd.max_dtr;
|
||||
}
|
||||
|
||||
|
|
@ -1029,6 +1046,15 @@ static void mmc_sd_detect(struct mmc_host *host)
|
|||
err = mmc_send_status(host->card, NULL);
|
||||
if (err) {
|
||||
retries--;
|
||||
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
if(0 == host->re_initialized_flags)
|
||||
{
|
||||
retries = 0;
|
||||
break; //Added by xbw at 2011-06-21
|
||||
}
|
||||
#endif
|
||||
|
||||
udelay(5);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1096,6 +1122,13 @@ static int mmc_sd_resume(struct mmc_host *host)
|
|||
mmc_hostname(host), err, retries);
|
||||
mdelay(5);
|
||||
retries--;
|
||||
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
if(0 == host->re_initialized_flags)
|
||||
{
|
||||
break; //Added by xbw at 2011-06-21
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1154,6 +1187,10 @@ int mmc_attach_sd(struct mmc_host *host)
|
|||
{
|
||||
int err;
|
||||
u32 ocr;
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
int retry_times = 3;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MMC_PARANOID_SD_INIT
|
||||
int retries;
|
||||
#endif
|
||||
|
|
@ -1227,6 +1264,14 @@ int mmc_attach_sd(struct mmc_host *host)
|
|||
err = mmc_sd_init_card(host, host->ocr, NULL);
|
||||
if (err) {
|
||||
retries--;
|
||||
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
if(0 == host->re_initialized_flags)
|
||||
{
|
||||
retries = 0;
|
||||
break; //Added by xbw at 2011-06-21
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1244,10 +1289,34 @@ int mmc_attach_sd(struct mmc_host *host)
|
|||
#endif
|
||||
|
||||
mmc_release_host(host);
|
||||
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
//modifyed by xbw at 2011--04-11
|
||||
Retry_add:
|
||||
err = mmc_add_card(host->card);
|
||||
mmc_claim_host(host);
|
||||
if (err)
|
||||
{
|
||||
//retry add the card; Added by xbw
|
||||
if((--retry_times >= 0))
|
||||
{
|
||||
printk("\n%s..%s..%d ****error in add partition, so retry. ===xbw[%s]===\n",__FUNCTION__,__FILE__,__LINE__, mmc_hostname(host));
|
||||
/* sleep some time */
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(HZ/2);
|
||||
|
||||
goto Retry_add;
|
||||
}
|
||||
|
||||
goto remove_card;
|
||||
|
||||
}
|
||||
#else
|
||||
err = mmc_add_card(host->card);
|
||||
mmc_claim_host(host);
|
||||
if (err)
|
||||
goto remove_card;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -351,8 +351,13 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
|
|||
*/
|
||||
if (!powered_resume) {
|
||||
err = mmc_send_io_op_cond(host, host->ocr, &ocr);
|
||||
if (err)
|
||||
if (err) {
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
printk("%s..%d.. ====*Identify the card as SDIO , but OCR error, so fail to initialize.===xbw[%s]===\n", \
|
||||
__FUNCTION__, __LINE__, mmc_hostname(host));
|
||||
#endif
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -405,6 +410,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
|
|||
if (err)
|
||||
goto remove;
|
||||
|
||||
#if !defined(CONFIG_SDMMC_RK29) || defined(CONFIG_SDMMC_RK29_OLD)
|
||||
/*
|
||||
* Update oldcard with the new RCA received from the SDIO
|
||||
* device -- we're doing this so that it's updated in the
|
||||
|
|
@ -412,6 +418,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
|
|||
*/
|
||||
if (oldcard)
|
||||
oldcard->rca = card->rca;
|
||||
#endif
|
||||
|
||||
mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
|
||||
}
|
||||
|
|
@ -932,6 +939,10 @@ int sdio_reset_comm(struct mmc_card *card)
|
|||
printk("%s():\n", __func__);
|
||||
mmc_claim_host(host);
|
||||
|
||||
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
|
||||
host->sdmmc_host_hw_init(mmc_priv(host)); //added by xbw , at 2011-10-18
|
||||
#endif
|
||||
|
||||
mmc_go_idle(host);
|
||||
|
||||
mmc_set_clock(host, host->f_min);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,12 @@
|
|||
# Makefile for MMC/SD host controller drivers
|
||||
#
|
||||
|
||||
ifeq ($(CONFIG_SDMMC_RK29_OLD),y)
|
||||
obj-$(CONFIG_SDMMC_RK29) += rk29_sdmmc_old.o
|
||||
else
|
||||
obj-$(CONFIG_SDMMC_RK29) += rk29_sdmmc.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_MMC_ARMMMCI) += mmci.o
|
||||
obj-$(CONFIG_MMC_PXA) += pxamci.o
|
||||
obj-$(CONFIG_MMC_IMX) += imxmmc.o
|
||||
|
|
|
|||
|
|
@ -3177,8 +3177,12 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
|
|||
/*
|
||||
* We can do SGIO
|
||||
*/
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
|
||||
mmc->max_segs = 64;
|
||||
#else
|
||||
mmc->max_phys_segs = 64;
|
||||
mmc->max_hw_segs = 64;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Block size can be up to 2048 bytes, but must be a power of two.
|
||||
|
|
|
|||
|
|
@ -1404,8 +1404,12 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
|
|||
mmc->f_max = host->bus_hz;
|
||||
mmc->ocr_avail = pdata->host_ocr_avail;
|
||||
mmc->caps = pdata->host_caps;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
|
||||
mmc->max_segs = 64;
|
||||
#else
|
||||
mmc->max_phys_segs = 64;
|
||||
mmc->max_hw_segs = 64;
|
||||
#endif
|
||||
mmc->max_blk_size = 4096;
|
||||
mmc->max_blk_count = 65535;
|
||||
mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
|
||||
|
|
|
|||
|
|
@ -310,7 +310,11 @@ static int rk29xxnand_add_partitions(struct rknand_info *nand_info)
|
|||
rknand_parts[num_partitions - 1].size = rknand_mtd.size - rknand_parts[num_partitions - 1].offset;
|
||||
|
||||
g_num_partitions = num_partitions;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
|
||||
return mtd_device_register(&rknand_mtd, rknand_parts, num_partitions);
|
||||
#else
|
||||
return add_mtd_partitions(&(rknand_mtd), rknand_parts, num_partitions);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -17,280 +17,53 @@ menuconfig WLAN
|
|||
|
||||
if WLAN
|
||||
|
||||
config PCMCIA_RAYCS
|
||||
tristate "Aviator/Raytheon 2.4GHz wireless support"
|
||||
depends on PCMCIA
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
config WLAN_80211
|
||||
bool "Wireless LAN (IEEE 802.11)"
|
||||
depends on NETDEVICES
|
||||
---help---
|
||||
Say Y here if you intend to attach an Aviator/Raytheon PCMCIA
|
||||
(PC-card) wireless Ethernet networking card to your computer.
|
||||
Please read the file <file:Documentation/networking/ray_cs.txt> for
|
||||
details.
|
||||
Say Y if you have any 802.11 wireless LAN hardware.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called ray_cs. If unsure, say N.
|
||||
This option does not affect the kernel build, it only
|
||||
lets you choose drivers.
|
||||
|
||||
config LIBERTAS_THINFIRM
|
||||
tristate "Marvell 8xxx Libertas WLAN driver support with thin firmware"
|
||||
depends on MAC80211
|
||||
select FW_LOADER
|
||||
---help---
|
||||
A library for Marvell Libertas 8xxx devices using thinfirm.
|
||||
choice
|
||||
prompt "WiFi device driver support"
|
||||
default WIFI_NONE
|
||||
|
||||
config LIBERTAS_THINFIRM_DEBUG
|
||||
bool "Enable full debugging output in the Libertas thin firmware module."
|
||||
depends on LIBERTAS_THINFIRM
|
||||
---help---
|
||||
Debugging support.
|
||||
config WIFI_NONE
|
||||
bool "No WiFi"
|
||||
|
||||
config LIBERTAS_THINFIRM_USB
|
||||
tristate "Marvell Libertas 8388 USB 802.11b/g cards with thin firmware"
|
||||
depends on LIBERTAS_THINFIRM && USB
|
||||
---help---
|
||||
A driver for Marvell Libertas 8388 USB devices using thinfirm.
|
||||
config BCM4329
|
||||
depends on WLAN_80211 && MMC
|
||||
select WIRELESS_EXT
|
||||
select WEXT_PRIV
|
||||
select IEEE80211
|
||||
select FW_LOADER
|
||||
bool "Broadcom BCM4329 WiFi/BT Combo SDIO"
|
||||
---help---
|
||||
A library for Broadcom BCM4329 SDIO WLAN/BT combo devices.
|
||||
So far, the following modules have been verified:
|
||||
(1) Samsung SWL-B23
|
||||
|
||||
config AIRO
|
||||
tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
|
||||
depends on ISA_DMA_API && (PCI || BROKEN)
|
||||
select WIRELESS_EXT
|
||||
select CRYPTO
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
---help---
|
||||
This is the standard Linux driver to support Cisco/Aironet ISA and
|
||||
PCI 802.11 wireless cards.
|
||||
It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X
|
||||
- with or without encryption) as well as card before the Cisco
|
||||
acquisition (Aironet 4500, Aironet 4800, Aironet 4800B).
|
||||
config MV8686
|
||||
depends on WLAN_80211 && MMC
|
||||
select WIRELESS_EXT
|
||||
select IEEE80211
|
||||
select FW_LOADER
|
||||
bool "Marvell MV8686 SDIO"
|
||||
---help---
|
||||
A library for Marvell 8686 SDIO WLAN devices.
|
||||
So far, the following modules have been verified:
|
||||
(1) Samsung SWL-2480
|
||||
(2) Azurewave AW-GH321
|
||||
(3) USI WM-G-MR-09
|
||||
(4) Murata SP-8HEP-P
|
||||
|
||||
This driver support both the standard Linux Wireless Extensions
|
||||
and Cisco proprietary API, so both the Linux Wireless Tools and the
|
||||
Cisco Linux utilities can be used to configure the card.
|
||||
source "drivers/net/wireless/bcm4319/Kconfig"
|
||||
source "drivers/net/wireless/rtl8192c/Kconfig"
|
||||
endchoice
|
||||
|
||||
The driver can be compiled as a module and will be named "airo".
|
||||
#source "drivers/net/wireless/bcm4329/Kconfig"
|
||||
|
||||
config ATMEL
|
||||
tristate "Atmel at76c50x chipset 802.11b support"
|
||||
depends on (PCI || PCMCIA)
|
||||
select WIRELESS_EXT
|
||||
select WEXT_PRIV
|
||||
select FW_LOADER
|
||||
select CRC32
|
||||
---help---
|
||||
A driver 802.11b wireless cards based on the Atmel fast-vnet
|
||||
chips. This driver supports standard Linux wireless extensions.
|
||||
endif
|
||||
|
||||
Many cards based on this chipset do not have flash memory
|
||||
and need their firmware loaded at start-up. If yours is
|
||||
one of these, you will need to provide a firmware image
|
||||
to be loaded into the card by the driver. The Atmel
|
||||
firmware package can be downloaded from
|
||||
<http://www.thekelleys.org.uk/atmel>
|
||||
|
||||
config PCI_ATMEL
|
||||
tristate "Atmel at76c506 PCI cards"
|
||||
depends on ATMEL && PCI
|
||||
---help---
|
||||
Enable support for PCI and mini-PCI cards containing the
|
||||
Atmel at76c506 chip.
|
||||
|
||||
config PCMCIA_ATMEL
|
||||
tristate "Atmel at76c502/at76c504 PCMCIA cards"
|
||||
depends on ATMEL && PCMCIA
|
||||
select WIRELESS_EXT
|
||||
select FW_LOADER
|
||||
select CRC32
|
||||
---help---
|
||||
Enable support for PCMCIA cards containing the
|
||||
Atmel at76c502 and at76c504 chips.
|
||||
|
||||
config AT76C50X_USB
|
||||
tristate "Atmel at76c503/at76c505/at76c505a USB cards"
|
||||
depends on MAC80211 && USB
|
||||
select FW_LOADER
|
||||
---help---
|
||||
Enable support for USB Wireless devices using Atmel at76c503,
|
||||
at76c505 or at76c505a chips.
|
||||
|
||||
config AIRO_CS
|
||||
tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards"
|
||||
depends on PCMCIA && (BROKEN || !M32R)
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
select CRYPTO
|
||||
select CRYPTO_AES
|
||||
---help---
|
||||
This is the standard Linux driver to support Cisco/Aironet PCMCIA
|
||||
802.11 wireless cards. This driver is the same as the Aironet
|
||||
driver part of the Linux Pcmcia package.
|
||||
It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X
|
||||
- with or without encryption) as well as card before the Cisco
|
||||
acquisition (Aironet 4500, Aironet 4800, Aironet 4800B). It also
|
||||
supports OEM of Cisco such as the DELL TrueMobile 4800 and Xircom
|
||||
802.11b cards.
|
||||
|
||||
This driver support both the standard Linux Wireless Extensions
|
||||
and Cisco proprietary API, so both the Linux Wireless Tools and the
|
||||
Cisco Linux utilities can be used to configure the card.
|
||||
|
||||
config PCMCIA_WL3501
|
||||
tristate "Planet WL3501 PCMCIA cards"
|
||||
depends on EXPERIMENTAL && PCMCIA
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
help
|
||||
A driver for WL3501 PCMCIA 802.11 wireless cards made by Planet.
|
||||
It has basic support for Linux wireless extensions and initial
|
||||
micro support for ethtool.
|
||||
|
||||
config PRISM54
|
||||
tristate 'Intersil Prism GT/Duette/Indigo PCI/Cardbus (DEPRECATED)'
|
||||
depends on PCI && EXPERIMENTAL
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
select FW_LOADER
|
||||
---help---
|
||||
This enables support for FullMAC PCI/Cardbus prism54 devices. This
|
||||
driver is now deprecated in favor for the SoftMAC driver, p54pci.
|
||||
p54pci supports FullMAC PCI/Cardbus devices as well. For details on
|
||||
the scheduled removal of this driver on the kernel see the feature
|
||||
removal schedule:
|
||||
|
||||
Documentation/feature-removal-schedule.txt
|
||||
|
||||
For more information refer to the p54 wiki:
|
||||
|
||||
http://wireless.kernel.org/en/users/Drivers/p54
|
||||
|
||||
Note: You need a motherboard with DMA support to use any of these cards
|
||||
|
||||
When built as module you get the module prism54
|
||||
|
||||
config USB_ZD1201
|
||||
tristate "USB ZD1201 based Wireless device support"
|
||||
depends on USB
|
||||
select WIRELESS_EXT
|
||||
select WEXT_PRIV
|
||||
select FW_LOADER
|
||||
---help---
|
||||
Say Y if you want to use wireless LAN adapters based on the ZyDAS
|
||||
ZD1201 chip.
|
||||
|
||||
This driver makes the adapter appear as a normal Ethernet interface,
|
||||
typically on wlan0.
|
||||
|
||||
The zd1201 device requires external firmware to be loaded.
|
||||
This can be found at http://linux-lc100020.sourceforge.net/
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called zd1201.
|
||||
|
||||
config USB_NET_RNDIS_WLAN
|
||||
tristate "Wireless RNDIS USB support"
|
||||
depends on USB && EXPERIMENTAL
|
||||
depends on CFG80211
|
||||
select USB_USBNET
|
||||
select USB_NET_CDCETHER
|
||||
select USB_NET_RNDIS_HOST
|
||||
---help---
|
||||
This is a driver for wireless RNDIS devices.
|
||||
These are USB based adapters found in devices such as:
|
||||
|
||||
Buffalo WLI-U2-KG125S
|
||||
U.S. Robotics USR5421
|
||||
Belkin F5D7051
|
||||
Linksys WUSB54GSv2
|
||||
Linksys WUSB54GSC
|
||||
Asus WL169gE
|
||||
Eminent EM4045
|
||||
BT Voyager 1055
|
||||
Linksys WUSB54GSv1
|
||||
U.S. Robotics USR5420
|
||||
BUFFALO WLI-USB-G54
|
||||
|
||||
All of these devices are based on Broadcom 4320 chip which is the
|
||||
only wireless RNDIS chip known to date.
|
||||
|
||||
If you choose to build a module, it'll be called rndis_wlan.
|
||||
|
||||
source "drivers/net/wireless/rtl818x/Kconfig"
|
||||
|
||||
config ADM8211
|
||||
tristate "ADMtek ADM8211 support"
|
||||
depends on MAC80211 && PCI && EXPERIMENTAL
|
||||
select CRC32
|
||||
select EEPROM_93CX6
|
||||
---help---
|
||||
This driver is for ADM8211A, ADM8211B, and ADM8211C based cards.
|
||||
These are PCI/mini-PCI/Cardbus 802.11b chips found in cards such as:
|
||||
|
||||
Xterasys Cardbus XN-2411b
|
||||
Blitz NetWave Point PC
|
||||
TrendNet 221pc
|
||||
Belkin F5D6001
|
||||
SMC 2635W
|
||||
Linksys WPC11 v1
|
||||
Fiberline FL-WL-200X
|
||||
3com Office Connect (3CRSHPW796)
|
||||
Corega WLPCIB-11
|
||||
SMC 2602W V2 EU
|
||||
D-Link DWL-520 Revision C
|
||||
|
||||
However, some of these cards have been replaced with other chips
|
||||
like the RTL8180L (Xterasys Cardbus XN-2411b, Belkin F5D6001) or
|
||||
the Ralink RT2400 (SMC2635W) without a model number change.
|
||||
|
||||
Thanks to Infineon-ADMtek for their support of this driver.
|
||||
|
||||
config MAC80211_HWSIM
|
||||
tristate "Simulated radio testing tool for mac80211"
|
||||
depends on MAC80211
|
||||
---help---
|
||||
This driver is a developer testing tool that can be used to test
|
||||
IEEE 802.11 networking stack (mac80211) functionality. This is not
|
||||
needed for normal wireless LAN usage and is only for testing. See
|
||||
Documentation/networking/mac80211_hwsim for more information on how
|
||||
to use this tool.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called mac80211_hwsim. If unsure, say N.
|
||||
|
||||
config MWL8K
|
||||
tristate "Marvell 88W8xxx PCI/PCIe Wireless support"
|
||||
depends on MAC80211 && PCI && EXPERIMENTAL
|
||||
---help---
|
||||
This driver supports Marvell TOPDOG 802.11 wireless cards.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called mwl8k. If unsure, say N.
|
||||
|
||||
config WIFI_CONTROL_FUNC
|
||||
bool "Enable WiFi control function abstraction"
|
||||
help
|
||||
Enables Power/Reset/Carddetect function abstraction
|
||||
|
||||
source "drivers/net/wireless/ath/Kconfig"
|
||||
source "drivers/net/wireless/b43/Kconfig"
|
||||
source "drivers/net/wireless/b43legacy/Kconfig"
|
||||
source "drivers/net/wireless/bcm4329/Kconfig"
|
||||
source "drivers/net/wireless/bcmdhd/Kconfig"
|
||||
source "drivers/net/wireless/hostap/Kconfig"
|
||||
source "drivers/net/wireless/ipw2x00/Kconfig"
|
||||
source "drivers/net/wireless/iwlwifi/Kconfig"
|
||||
source "drivers/net/wireless/iwlegacy/Kconfig"
|
||||
source "drivers/net/wireless/iwmc3200wifi/Kconfig"
|
||||
source "drivers/net/wireless/libertas/Kconfig"
|
||||
source "drivers/net/wireless/orinoco/Kconfig"
|
||||
source "drivers/net/wireless/p54/Kconfig"
|
||||
source "drivers/net/wireless/rt2x00/Kconfig"
|
||||
source "drivers/net/wireless/rtlwifi/Kconfig"
|
||||
source "drivers/net/wireless/wl1251/Kconfig"
|
||||
source "drivers/net/wireless/wl12xx/Kconfig"
|
||||
source "drivers/net/wireless/zd1211rw/Kconfig"
|
||||
source "drivers/net/wireless/mwifiex/Kconfig"
|
||||
|
||||
endif # WLAN
|
||||
|
|
|
|||
|
|
@ -1,63 +1,9 @@
|
|||
#
|
||||
# Makefile for the Linux Wireless network device drivers.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_IPW2100) += ipw2x00/
|
||||
obj-$(CONFIG_IPW2200) += ipw2x00/
|
||||
|
||||
obj-$(CONFIG_HERMES) += orinoco/
|
||||
|
||||
obj-$(CONFIG_AIRO) += airo.o
|
||||
obj-$(CONFIG_AIRO_CS) += airo_cs.o airo.o
|
||||
|
||||
obj-$(CONFIG_ATMEL) += atmel.o
|
||||
obj-$(CONFIG_PCI_ATMEL) += atmel_pci.o
|
||||
obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o
|
||||
|
||||
obj-$(CONFIG_AT76C50X_USB) += at76c50x-usb.o
|
||||
|
||||
obj-$(CONFIG_PRISM54) += prism54/
|
||||
|
||||
obj-$(CONFIG_HOSTAP) += hostap/
|
||||
obj-$(CONFIG_B43) += b43/
|
||||
obj-$(CONFIG_B43LEGACY) += b43legacy/
|
||||
obj-$(CONFIG_ZD1211RW) += zd1211rw/
|
||||
obj-$(CONFIG_RTL8180) += rtl818x/
|
||||
obj-$(CONFIG_RTL8187) += rtl818x/
|
||||
obj-$(CONFIG_RTLWIFI) += rtlwifi/
|
||||
|
||||
# 16-bit wireless PCMCIA client drivers
|
||||
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
|
||||
obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
|
||||
|
||||
obj-$(CONFIG_USB_NET_RNDIS_WLAN) += rndis_wlan.o
|
||||
|
||||
obj-$(CONFIG_USB_ZD1201) += zd1201.o
|
||||
obj-$(CONFIG_LIBERTAS) += libertas/
|
||||
|
||||
obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf/
|
||||
|
||||
obj-$(CONFIG_ADM8211) += adm8211.o
|
||||
|
||||
obj-$(CONFIG_MWL8K) += mwl8k.o
|
||||
|
||||
obj-$(CONFIG_IWLAGN) += iwlwifi/
|
||||
obj-$(CONFIG_IWLWIFI_LEGACY) += iwlegacy/
|
||||
obj-$(CONFIG_RT2X00) += rt2x00/
|
||||
|
||||
obj-$(CONFIG_P54_COMMON) += p54/
|
||||
|
||||
obj-$(CONFIG_ATH_COMMON) += ath/
|
||||
|
||||
obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
|
||||
|
||||
obj-$(CONFIG_WL1251) += wl1251/
|
||||
obj-$(CONFIG_WL12XX) += wl12xx/
|
||||
obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx/
|
||||
|
||||
obj-$(CONFIG_IWM) += iwmc3200wifi/
|
||||
|
||||
obj-$(CONFIG_MWIFIEX) += mwifiex/
|
||||
|
||||
obj-$(CONFIG_BCM4329) += bcm4329/
|
||||
obj-$(CONFIG_BCMDHD) += bcmdhd/
|
||||
obj-y += wifi_sys/rkwifi_sys_iface.o
|
||||
obj-$(CONFIG_BCM4329) += bcm4329/
|
||||
obj-$(CONFIG_MV8686) += mv8686/
|
||||
obj-$(CONFIG_BCM4319) += bcm4319/
|
||||
obj-$(CONFIG_RTL8192CU) += rtl8192c/
|
||||
#obj-m += wlan/
|
||||
|
|
|
|||
|
|
@ -22,6 +22,6 @@ config BCM4329_FW_PATH
|
|||
config BCM4329_NVRAM_PATH
|
||||
depends on BCM4329
|
||||
string "NVRAM path"
|
||||
default "/proc/calibration"
|
||||
default "/system/etc/firmware/nvram_B23.txt"
|
||||
---help---
|
||||
Path to the calibration file.
|
||||
|
|
|
|||
11
drivers/net/wireless/bcm4329/Makefile
Normal file → Executable file
11
drivers/net/wireless/bcm4329/Makefile
Normal file → Executable file
|
|
@ -3,13 +3,16 @@ DHDCFLAGS = -DLINUX -DBCMDRIVER -DBCMDONGLEHOST -DDHDTHREAD -DBCMWPA2 \
|
|||
-DUNRELEASEDCHIP -Dlinux -DDHD_SDALIGN=64 -DMAX_HDR_READ=64 \
|
||||
-DDHD_FIRSTREAD=64 -DDHD_GPL -DDHD_SCHED -DBDC -DTOE -DDHD_BCMEVENTS \
|
||||
-DSHOW_EVENTS -DBCMSDIO -DDHD_GPL -DBCMLXSDMMC -DBCMPLATFORM_BUS \
|
||||
-Wall -Wstrict-prototypes -Werror -DOOB_INTR_ONLY -DCUSTOMER_HW2 \
|
||||
-DDHD_USE_STATIC_BUF -DMMC_SDIO_ABORT -DDHD_DEBUG_TRAP -DSOFTAP \
|
||||
-Wall -Wstrict-prototypes -Werror -DCUSTOMER_HW2 \
|
||||
-DDHD_USE_STATIC_BUF -DDHD_DEBUG_TRAP -DSOFTAP -DSDIO_ISR_THREAD \
|
||||
-DEMBEDDED_PLATFORM -DARP_OFFLOAD_SUPPORT -DPKT_FILTER_SUPPORT \
|
||||
-DGET_CUSTOM_MAC_ENABLE -DSET_RANDOM_MAC_SOFTAP -DCSCAN -DHW_OOB \
|
||||
-DKEEP_ALIVE -DPNO_SUPPORT \
|
||||
-DGET_CUSTOM_MAC_ENABLE -DSET_RANDOM_MAC_SOFTAP -DCSCAN \
|
||||
-DKEEP_ALIVE -DCONFIG_US_NON_DFS_CHANNELS_ONLY \
|
||||
-Idrivers/net/wireless/bcm4329 -Idrivers/net/wireless/bcm4329/include
|
||||
|
||||
#options defines dependent on platform board and applicantion requirements:
|
||||
#-DOOB_INTR_ONLY -DMMC_SDIO_ABORT -DHW_OOB
|
||||
|
||||
DHDOFILES = dhd_linux.o linux_osl.o bcmutils.o dhd_common.o dhd_custom_gpio.o \
|
||||
wl_iw.o siutils.o sbutils.o aiutils.o hndpmu.o bcmwifi.o dhd_sdio.o \
|
||||
dhd_linux_sched.o dhd_cdc.o bcmsdh_sdmmc.o bcmsdh.o bcmsdh_linux.o \
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ int bcmsdh_remove(struct device *dev)
|
|||
MFREE(osh, sdhc, sizeof(bcmsdh_hc_t));
|
||||
osl_detach(osh);
|
||||
|
||||
#if !defined(BCMLXSDMMC) || defined(OOB_INTR_ONLY)
|
||||
#if !defined(BCMLXSDMMC)
|
||||
dev_set_drvdata(dev, NULL);
|
||||
#endif /* !defined(BCMLXSDMMC) */
|
||||
|
||||
|
|
@ -636,7 +636,7 @@ int bcmsdh_register_oob_intr(void * dhdp)
|
|||
if (error)
|
||||
return -ENODEV;
|
||||
|
||||
enable_irq_wake(sdhcinfo->oob_irq);
|
||||
set_irq_wake(sdhcinfo->oob_irq, 1);
|
||||
sdhcinfo->oob_irq_registered = TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -661,12 +661,10 @@ void bcmsdh_unregister_oob_intr(void)
|
|||
{
|
||||
SDLX_MSG(("%s: Enter\n", __FUNCTION__));
|
||||
|
||||
if (sdhcinfo->oob_irq_registered) {
|
||||
disable_irq_wake(sdhcinfo->oob_irq);
|
||||
disable_irq(sdhcinfo->oob_irq); /* just in case.. */
|
||||
free_irq(sdhcinfo->oob_irq, NULL);
|
||||
sdhcinfo->oob_irq_registered = FALSE;
|
||||
}
|
||||
set_irq_wake(sdhcinfo->oob_irq, 0);
|
||||
disable_irq(sdhcinfo->oob_irq); /* just in case.. */
|
||||
free_irq(sdhcinfo->oob_irq, NULL);
|
||||
sdhcinfo->oob_irq_registered = FALSE;
|
||||
}
|
||||
#endif /* defined(OOB_INTR_ONLY) */
|
||||
/* Module parameters specific to each host-controller driver */
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ PBCMSDH_SDMMC_INSTANCE gInstance;
|
|||
|
||||
extern int bcmsdh_probe(struct device *dev);
|
||||
extern int bcmsdh_remove(struct device *dev);
|
||||
struct device sdmmc_dev;
|
||||
|
||||
static int bcmsdh_sdmmc_probe(struct sdio_func *func,
|
||||
const struct sdio_device_id *id)
|
||||
|
|
@ -101,7 +102,7 @@ static int bcmsdh_sdmmc_probe(struct sdio_func *func,
|
|||
if(func->device == 0x4) { /* 4318 */
|
||||
gInstance->func[2] = NULL;
|
||||
sd_trace(("NIC found, calling bcmsdh_probe...\n"));
|
||||
ret = bcmsdh_probe(&func->dev);
|
||||
ret = bcmsdh_probe(&sdmmc_dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -109,7 +110,7 @@ static int bcmsdh_sdmmc_probe(struct sdio_func *func,
|
|||
|
||||
if (func->num == 2) {
|
||||
sd_trace(("F2 found, calling bcmsdh_probe...\n"));
|
||||
ret = bcmsdh_probe(&func->dev);
|
||||
ret = bcmsdh_probe(&sdmmc_dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -125,7 +126,7 @@ static void bcmsdh_sdmmc_remove(struct sdio_func *func)
|
|||
|
||||
if (func->num == 2) {
|
||||
sd_trace(("F2 found, calling bcmsdh_remove...\n"));
|
||||
bcmsdh_remove(&func->dev);
|
||||
bcmsdh_remove(&sdmmc_dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -249,8 +250,10 @@ int sdio_function_init(void)
|
|||
if (!gInstance)
|
||||
return -ENOMEM;
|
||||
|
||||
bzero(&sdmmc_dev, sizeof(sdmmc_dev));
|
||||
error = sdio_register_driver(&bcmsdh_sdmmc_driver);
|
||||
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
@ -262,6 +265,7 @@ void sdio_function_cleanup(void)
|
|||
{
|
||||
sd_trace(("%s Enter\n", __FUNCTION__));
|
||||
|
||||
|
||||
sdio_unregister_driver(&bcmsdh_sdmmc_driver);
|
||||
|
||||
if (gInstance)
|
||||
|
|
|
|||
1726
drivers/net/wireless/bcm4329/bcmspibrcm.c
Normal file
1726
drivers/net/wireless/bcm4329/bcmspibrcm.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -24,7 +24,7 @@
|
|||
* software in any way with any other Broadcom software provided under a license
|
||||
* other than the GPL, without Broadcom's express prior written consent.
|
||||
*
|
||||
* $Id: dhd.h,v 1.32.4.7.2.4.14.49.4.9 2011/01/14 22:40:45 Exp $
|
||||
* $Id: dhd.h,v 1.32.4.7.2.4.14.49.4.7 2010/11/12 22:48:36 Exp $
|
||||
*/
|
||||
|
||||
/****************
|
||||
|
|
@ -165,7 +165,7 @@ typedef struct dhd_pub {
|
|||
char * pktfilter[100];
|
||||
int pktfilter_count;
|
||||
|
||||
wl_country_t dhd_cspec; /* Current Locale info */
|
||||
uint8 country_code[WLC_CNTRY_BUF_SZ];
|
||||
char eventmask[WL_EVENTING_MASK_LEN];
|
||||
|
||||
} dhd_pub_t;
|
||||
|
|
@ -180,7 +180,7 @@ typedef struct dhd_pub {
|
|||
wait_event_interruptible_timeout(a, FALSE, HZ/100); \
|
||||
} \
|
||||
} while (0)
|
||||
#define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 200)
|
||||
#define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 30)
|
||||
#define DHD_PM_RESUME_WAIT_FOREVER(a) _DHD_PM_RESUME_WAIT(a, ~0)
|
||||
#define DHD_PM_RESUME_RETURN_ERROR(a) do { if (dhd_mmc_suspend) return a; } while (0)
|
||||
#define DHD_PM_RESUME_RETURN do { if (dhd_mmc_suspend) return; } while (0)
|
||||
|
|
@ -215,20 +215,6 @@ typedef struct dhd_pub {
|
|||
|
||||
#define DHD_IF_VIF 0x01 /* Virtual IF (Hidden from user) */
|
||||
|
||||
inline static void NETIF_ADDR_LOCK(struct net_device *dev)
|
||||
{
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
|
||||
netif_addr_lock_bh(dev);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline static void NETIF_ADDR_UNLOCK(struct net_device *dev)
|
||||
{
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
|
||||
netif_addr_unlock_bh(dev);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Wakelock Functions */
|
||||
extern int dhd_os_wake_lock(dhd_pub_t *pub);
|
||||
extern int dhd_os_wake_unlock(dhd_pub_t *pub);
|
||||
|
|
@ -449,16 +435,4 @@ extern char nv_path[MOD_PARAM_PATHLEN];
|
|||
extern void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar);
|
||||
extern void dhd_wait_event_wakeup(dhd_pub_t*dhd);
|
||||
|
||||
/* dhd_commn arp offload wrapers */
|
||||
extern void dhd_arp_cleanup(dhd_pub_t *dhd);
|
||||
int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen);
|
||||
void dhd_arp_offload_add_ip(dhd_pub_t *dhd, u32 ipaddr);
|
||||
|
||||
#define DHD_UNICAST_FILTER_NUM 0
|
||||
#define DHD_BROADCAST_FILTER_NUM 1
|
||||
#define DHD_MULTICAST4_FILTER_NUM 2
|
||||
#define DHD_MULTICAST6_FILTER_NUM 3
|
||||
extern int net_os_set_packet_filter(struct net_device *dev, int val);
|
||||
extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num);
|
||||
|
||||
#endif /* _dhd_h_ */
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@
|
|||
#include <dhd_bus.h>
|
||||
#include <dhd_dbg.h>
|
||||
|
||||
uint8 wlan_mac_addr[ETHER_ADDR_LEN];
|
||||
|
||||
extern int dhd_preinit_ioctls(dhd_pub_t *dhd);
|
||||
|
||||
/* Packet alignment for most efficient SDIO (can change based on platform) */
|
||||
|
|
@ -502,6 +504,7 @@ dhd_prot_init(dhd_pub_t *dhd)
|
|||
return ret;
|
||||
}
|
||||
memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN);
|
||||
memcpy(wlan_mac_addr, buf, ETHER_ADDR_LEN);
|
||||
|
||||
dhd_os_proto_unblock(dhd);
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
* software in any way with any other Broadcom software provided under a license
|
||||
* other than the GPL, without Broadcom's express prior written consent.
|
||||
*
|
||||
* $Id: dhd_common.c,v 1.5.6.8.2.6.6.69.4.25 2011-02-11 21:16:02 Exp $
|
||||
* $Id: dhd_common.c,v 1.5.6.8.2.6.6.69.4.20 2010/12/20 23:37:28 Exp $
|
||||
*/
|
||||
#include <typedefs.h>
|
||||
#include <osl.h>
|
||||
|
|
@ -39,6 +39,9 @@
|
|||
|
||||
#include <wlioctl.h>
|
||||
|
||||
#define CONFIG_BCM4329_FW_PATH "/system/etc/firmware/fw_bcm4329.bin"
|
||||
#define CONFIG_BCM4329_NVRAM_PATH "/system/etc/firmware/nvram_B23.txt"
|
||||
|
||||
#ifdef SET_RANDOM_MAC_SOFTAP
|
||||
#include <linux/random.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
|
@ -992,9 +995,6 @@ dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_
|
|||
wl_pkt_filter_enable_t enable_parm;
|
||||
wl_pkt_filter_enable_t * pkt_filterp;
|
||||
|
||||
if (!arg)
|
||||
return;
|
||||
|
||||
if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) {
|
||||
DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
|
||||
goto fail;
|
||||
|
|
@ -1068,9 +1068,6 @@ dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg)
|
|||
char *arg_save = 0, *arg_org = 0;
|
||||
#define BUF_SIZE 2048
|
||||
|
||||
if (!arg)
|
||||
return;
|
||||
|
||||
if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) {
|
||||
DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
|
||||
goto fail;
|
||||
|
|
@ -1226,82 +1223,6 @@ dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable)
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
void dhd_arp_cleanup(dhd_pub_t *dhd)
|
||||
{
|
||||
#ifdef ARP_OFFLOAD_SUPPORT
|
||||
int ret = 0;
|
||||
int iov_len = 0;
|
||||
char iovbuf[128];
|
||||
|
||||
if (dhd == NULL) return;
|
||||
|
||||
dhd_os_proto_block(dhd);
|
||||
|
||||
iov_len = bcm_mkiovar("arp_hostip_clear", 0, 0, iovbuf, sizeof(iovbuf));
|
||||
if ((ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, iov_len)) < 0)
|
||||
DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
|
||||
|
||||
iov_len = bcm_mkiovar("arp_table_clear", 0, 0, iovbuf, sizeof(iovbuf));
|
||||
if ((ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, iov_len)) < 0)
|
||||
DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
|
||||
|
||||
dhd_os_proto_unblock(dhd);
|
||||
|
||||
#endif /* ARP_OFFLOAD_SUPPORT */
|
||||
}
|
||||
|
||||
void dhd_arp_offload_add_ip(dhd_pub_t *dhd, u32 ipaddr)
|
||||
{
|
||||
#ifdef ARP_OFFLOAD_SUPPORT
|
||||
int iov_len = 0;
|
||||
char iovbuf[32];
|
||||
int retcode;
|
||||
|
||||
dhd_os_proto_block(dhd);
|
||||
|
||||
iov_len = bcm_mkiovar("arp_hostip", (char *)&ipaddr, 4, iovbuf, sizeof(iovbuf));
|
||||
retcode = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, iov_len);
|
||||
|
||||
dhd_os_proto_unblock(dhd);
|
||||
|
||||
if (retcode)
|
||||
DHD_TRACE(("%s: ARP ip addr add failed, retcode = %d\n",
|
||||
__FUNCTION__, retcode));
|
||||
else
|
||||
DHD_TRACE(("%s: ARP ipaddr entry added\n",
|
||||
__FUNCTION__));
|
||||
#endif /* ARP_OFFLOAD_SUPPORT */
|
||||
}
|
||||
|
||||
|
||||
int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen)
|
||||
{
|
||||
#ifdef ARP_OFFLOAD_SUPPORT
|
||||
int retcode;
|
||||
int iov_len = 0;
|
||||
|
||||
if (!buf)
|
||||
return -1;
|
||||
|
||||
dhd_os_proto_block(dhd);
|
||||
|
||||
iov_len = bcm_mkiovar("arp_hostip", 0, 0, buf, buflen);
|
||||
retcode = dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, buflen);
|
||||
|
||||
dhd_os_proto_unblock(dhd);
|
||||
|
||||
if (retcode) {
|
||||
DHD_TRACE(("%s: ioctl WLC_GET_VAR error %d\n",
|
||||
__FUNCTION__, retcode));
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif /* ARP_OFFLOAD_SUPPORT */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
dhd_preinit_ioctls(dhd_pub_t *dhd)
|
||||
{
|
||||
|
|
@ -1368,11 +1289,15 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
|
|||
}
|
||||
#endif /* SET_RANDOM_MAC_SOFTAP */
|
||||
|
||||
/* Set Country code */
|
||||
if (dhd->dhd_cspec.ccode[0] != 0) {
|
||||
bcm_mkiovar("country", (char *)&dhd->dhd_cspec, \
|
||||
sizeof(wl_country_t), iovbuf, sizeof(iovbuf));
|
||||
if ((ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf))) < 0) {
|
||||
/* Set Country code
|
||||
* "US" ---> 11 channels, this is default setting.
|
||||
* "EU" ---> 13 channels
|
||||
* "JP" ---> 14 channels
|
||||
*/
|
||||
strcpy(dhd->country_code, "EU");
|
||||
if (dhd->country_code[0] != 0) {
|
||||
if (dhdcdc_set_ioctl(dhd, 0, WLC_SET_COUNTRY,
|
||||
dhd->country_code, sizeof(dhd->country_code)) < 0) {
|
||||
DHD_ERROR(("%s: country code setting failed\n", __FUNCTION__));
|
||||
}
|
||||
}
|
||||
|
|
@ -1979,7 +1904,6 @@ int dhd_pno_clean(dhd_pub_t *dhd)
|
|||
int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
|
||||
{
|
||||
char iovbuf[128];
|
||||
uint8 bssid[6];
|
||||
int ret = -1;
|
||||
|
||||
if ((!dhd) && ((pfn_enabled != 0) || (pfn_enabled != 1))) {
|
||||
|
|
@ -1987,20 +1911,6 @@ int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
|
|||
return ret;
|
||||
}
|
||||
|
||||
memset(iovbuf, 0, sizeof(iovbuf));
|
||||
|
||||
/* Check if disassoc to enable pno */
|
||||
if ((pfn_enabled) && \
|
||||
((ret = dhdcdc_set_ioctl(dhd, 0, WLC_GET_BSSID, \
|
||||
(char *)&bssid, ETHER_ADDR_LEN)) == BCME_NOTASSOCIATED)) {
|
||||
DHD_TRACE(("%s pno enable called in disassoc mode\n", __FUNCTION__));
|
||||
}
|
||||
else if (pfn_enabled) {
|
||||
DHD_ERROR(("%s pno enable called in assoc mode ret=%d\n", \
|
||||
__FUNCTION__, ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enable/disable PNO */
|
||||
if ((ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf))) > 0) {
|
||||
if ((ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf))) < 0) {
|
||||
|
|
@ -2019,8 +1929,7 @@ int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
|
|||
|
||||
/* Function to execute combined scan */
|
||||
int
|
||||
dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, \
|
||||
int pno_repeat, int pno_freq_expo_max)
|
||||
dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr)
|
||||
{
|
||||
int err = -1;
|
||||
char iovbuf[128];
|
||||
|
|
@ -2065,23 +1974,12 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr,
|
|||
pfn_param.version = htod32(PFN_VERSION);
|
||||
pfn_param.flags = htod16((PFN_LIST_ORDER << SORT_CRITERIA_BIT));
|
||||
|
||||
/* check and set extra pno params */
|
||||
if ((pno_repeat != 0) || (pno_freq_expo_max != 0)) {
|
||||
pfn_param.flags |= htod16(ENABLE << ENABLE_ADAPTSCAN_BIT);
|
||||
pfn_param.repeat_scan = htod32(pno_repeat);
|
||||
pfn_param.max_freq_adjust = htod32(pno_freq_expo_max);
|
||||
}
|
||||
|
||||
/* set up pno scan fr */
|
||||
if (scan_fr != 0)
|
||||
pfn_param.scan_freq = htod32(scan_fr);
|
||||
|
||||
if (pfn_param.scan_freq > PNO_SCAN_MAX_FW_SEC) {
|
||||
DHD_ERROR(("%s pno freq above %d sec\n", __FUNCTION__, PNO_SCAN_MAX_FW_SEC));
|
||||
return err;
|
||||
}
|
||||
if (pfn_param.scan_freq < PNO_SCAN_MIN_FW_SEC) {
|
||||
DHD_ERROR(("%s pno freq less %d sec\n", __FUNCTION__, PNO_SCAN_MIN_FW_SEC));
|
||||
if (pfn_param.scan_freq > PNO_SCAN_MAX_FW) {
|
||||
DHD_ERROR(("%s pno freq above %d sec\n", __FUNCTION__, PNO_SCAN_MAX_FW));
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -2093,6 +1991,8 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr,
|
|||
|
||||
pfn_element.bss_type = htod32(DOT11_BSSTYPE_INFRASTRUCTURE);
|
||||
pfn_element.auth = (DOT11_OPEN_SYSTEM);
|
||||
pfn_element.wpa_auth = htod32(WPA_AUTH_PFN_ANY);
|
||||
pfn_element.wsec = htod32(0);
|
||||
pfn_element.infra = htod32(1);
|
||||
|
||||
memcpy((char *)pfn_element.ssid.SSID, ssids_local[i].SSID, ssids_local[i].SSID_len);
|
||||
|
|
@ -2108,9 +2008,8 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr,
|
|||
return err;
|
||||
}
|
||||
else
|
||||
DHD_ERROR(("%s set OK with PNO time=%d repeat=%d max_adjust=%d\n", \
|
||||
__FUNCTION__, pfn_param.scan_freq, \
|
||||
pfn_param.repeat_scan, pfn_param.max_freq_adjust));
|
||||
DHD_ERROR(("%s set OK with PNO time=%d\n", __FUNCTION__, \
|
||||
pfn_param.scan_freq));
|
||||
}
|
||||
else DHD_ERROR(("%s failed err=%d\n", __FUNCTION__, err));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
* software in any way with any other Broadcom software provided under a license
|
||||
* other than the GPL, without Broadcom's express prior written consent.
|
||||
*
|
||||
* $Id: dhd_custom_gpio.c,v 1.1.4.8.4.4 2011/01/20 20:23:09 Exp $
|
||||
* $Id: dhd_custom_gpio.c,v 1.1.4.8.4.1 2010/09/02 23:13:16 Exp $
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -47,7 +47,6 @@ int wifi_set_carddetect(int on);
|
|||
int wifi_set_power(int on, unsigned long msec);
|
||||
int wifi_get_irq_number(unsigned long *irq_flags_ptr);
|
||||
int wifi_get_mac_addr(unsigned char *buf);
|
||||
void *wifi_get_country_code(char *ccode);
|
||||
#endif
|
||||
|
||||
#if defined(OOB_INTR_ONLY)
|
||||
|
|
@ -178,95 +177,3 @@ dhd_custom_get_mac_address(unsigned char *buf)
|
|||
return ret;
|
||||
}
|
||||
#endif /* GET_CUSTOM_MAC_ENABLE */
|
||||
|
||||
/* Customized Locale table : OPTIONAL feature */
|
||||
const struct cntry_locales_custom translate_custom_table[] = {
|
||||
/* Table should be filled out based on custom platform regulatory requirement */
|
||||
#ifdef EXAMPLE_TABLE
|
||||
{"", "XY", 4}, /* universal */
|
||||
{"US", "US", 69}, /* input ISO "US" to : US regrev 69 */
|
||||
{"CA", "US", 69}, /* input ISO "CA" to : US regrev 69 */
|
||||
{"EU", "EU", 5}, /* European union countries */
|
||||
{"AT", "EU", 5},
|
||||
{"BE", "EU", 5},
|
||||
{"BG", "EU", 5},
|
||||
{"CY", "EU", 5},
|
||||
{"CZ", "EU", 5},
|
||||
{"DK", "EU", 5},
|
||||
{"EE", "EU", 5},
|
||||
{"FI", "EU", 5},
|
||||
{"FR", "EU", 5},
|
||||
{"DE", "EU", 5},
|
||||
{"GR", "EU", 5},
|
||||
{"HU", "EU", 5},
|
||||
{"IE", "EU", 5},
|
||||
{"IT", "EU", 5},
|
||||
{"LV", "EU", 5},
|
||||
{"LI", "EU", 5},
|
||||
{"LT", "EU", 5},
|
||||
{"LU", "EU", 5},
|
||||
{"MT", "EU", 5},
|
||||
{"NL", "EU", 5},
|
||||
{"PL", "EU", 5},
|
||||
{"PT", "EU", 5},
|
||||
{"RO", "EU", 5},
|
||||
{"SK", "EU", 5},
|
||||
{"SI", "EU", 5},
|
||||
{"ES", "EU", 5},
|
||||
{"SE", "EU", 5},
|
||||
{"GB", "EU", 5}, /* input ISO "GB" to : EU regrev 05 */
|
||||
{"IL", "IL", 0},
|
||||
{"CH", "CH", 0},
|
||||
{"TR", "TR", 0},
|
||||
{"NO", "NO", 0},
|
||||
{"KR", "XY", 3},
|
||||
{"AU", "XY", 3},
|
||||
{"CN", "XY", 3}, /* input ISO "CN" to : XY regrev 03 */
|
||||
{"TW", "XY", 3},
|
||||
{"AR", "XY", 3},
|
||||
{"MX", "XY", 3}
|
||||
#endif /* EXAMPLE_TABLE */
|
||||
};
|
||||
|
||||
|
||||
/* Customized Locale convertor
|
||||
* input : ISO 3166-1 country abbreviation
|
||||
* output: customized cspec
|
||||
*/
|
||||
void get_customized_country_code(char *country_iso_code, wl_country_t *cspec)
|
||||
{
|
||||
#ifdef CUSTOMER_HW2
|
||||
struct cntry_locales_custom *cloc_ptr;
|
||||
|
||||
if (!cspec)
|
||||
return;
|
||||
|
||||
cloc_ptr = wifi_get_country_code(country_iso_code);
|
||||
if (cloc_ptr) {
|
||||
strlcpy(cspec->ccode, cloc_ptr->custom_locale, WLC_CNTRY_BUF_SZ);
|
||||
cspec->rev = cloc_ptr->custom_locale_rev;
|
||||
}
|
||||
return;
|
||||
#else
|
||||
int size, i;
|
||||
|
||||
size = ARRAYSIZE(translate_custom_table);
|
||||
|
||||
if (cspec == 0)
|
||||
return;
|
||||
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (strcmp(country_iso_code, translate_custom_table[i].iso_abbrev) == 0) {
|
||||
memcpy(cspec->ccode, translate_custom_table[i].custom_locale, WLC_CNTRY_BUF_SZ);
|
||||
cspec->rev = translate_custom_table[i].custom_locale_rev;
|
||||
return;
|
||||
}
|
||||
}
|
||||
memcpy(cspec->ccode, translate_custom_table[0].custom_locale, WLC_CNTRY_BUF_SZ);
|
||||
cspec->rev = translate_custom_table[0].custom_locale_rev;
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,9 +22,12 @@
|
|||
* software in any way with any other Broadcom software provided under a license
|
||||
* other than the GPL, without Broadcom's express prior written consent.
|
||||
*
|
||||
* $Id: dhd_linux.c,v 1.65.4.9.2.12.2.104.4.40 2011/02/03 19:55:18 Exp $
|
||||
* $Id: dhd_linux.c,v 1.65.4.9.2.12.2.104.4.35 2010/11/17 03:13:21 Exp $
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_WIFI_CONTROL_FUNC
|
||||
#include <linux/platform_device.h>
|
||||
#endif
|
||||
#include <typedefs.h>
|
||||
#include <linuxver.h>
|
||||
#include <osl.h>
|
||||
|
|
@ -40,12 +43,11 @@
|
|||
#include <linux/ethtool.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/inetdevice.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <wifi_version.h>
|
||||
#include <epivers.h>
|
||||
#include <bcmutils.h>
|
||||
#include <bcmendian.h>
|
||||
|
|
@ -60,14 +62,18 @@
|
|||
#ifdef CONFIG_HAS_WAKELOCK
|
||||
#include <linux/wakelock.h>
|
||||
#endif
|
||||
#ifdef CUSTOMER_HW2
|
||||
#include <linux/platform_device.h>
|
||||
#ifdef CONFIG_WIFI_CONTROL_FUNC
|
||||
#include <linux/wlan_plat.h>
|
||||
static struct wifi_platform_data *wifi_control_data = NULL;
|
||||
#endif
|
||||
#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
|
||||
//#include <linux/wlan_plat.h>
|
||||
#include <mach/board.h>
|
||||
|
||||
struct semaphore wifi_control_sem;
|
||||
|
||||
struct dhd_bus *g_bus;
|
||||
|
||||
extern void bcm4329_power_save_exit(void);
|
||||
extern void bcm4329_power_save_init(void);
|
||||
|
||||
static struct wifi_platform_data *wifi_control_data = NULL;
|
||||
static struct resource *wifi_irqres = NULL;
|
||||
|
||||
int wifi_get_irq_number(unsigned long *irq_flags_ptr)
|
||||
|
|
@ -86,22 +92,18 @@ int wifi_get_irq_number(unsigned long *irq_flags_ptr)
|
|||
int wifi_set_carddetect(int on)
|
||||
{
|
||||
printk("%s = %d\n", __FUNCTION__, on);
|
||||
#ifdef CONFIG_WIFI_CONTROL_FUNC
|
||||
if (wifi_control_data && wifi_control_data->set_carddetect) {
|
||||
wifi_control_data->set_carddetect(on);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wifi_set_power(int on, unsigned long msec)
|
||||
{
|
||||
printk("%s = %d\n", __FUNCTION__, on);
|
||||
#ifdef CONFIG_WIFI_CONTROL_FUNC
|
||||
if (wifi_control_data && wifi_control_data->set_power) {
|
||||
wifi_control_data->set_power(on);
|
||||
}
|
||||
#endif
|
||||
if (msec)
|
||||
mdelay(msec);
|
||||
return 0;
|
||||
|
|
@ -110,11 +112,9 @@ int wifi_set_power(int on, unsigned long msec)
|
|||
int wifi_set_reset(int on, unsigned long msec)
|
||||
{
|
||||
DHD_TRACE(("%s = %d\n", __FUNCTION__, on));
|
||||
#ifdef CONFIG_WIFI_CONTROL_FUNC
|
||||
if (wifi_control_data && wifi_control_data->set_reset) {
|
||||
wifi_control_data->set_reset(on);
|
||||
}
|
||||
#endif
|
||||
if (msec)
|
||||
mdelay(msec);
|
||||
return 0;
|
||||
|
|
@ -125,38 +125,20 @@ int wifi_get_mac_addr(unsigned char *buf)
|
|||
DHD_TRACE(("%s\n", __FUNCTION__));
|
||||
if (!buf)
|
||||
return -EINVAL;
|
||||
#ifdef CONFIG_WIFI_CONTROL_FUNC
|
||||
if (wifi_control_data && wifi_control_data->get_mac_addr) {
|
||||
return wifi_control_data->get_mac_addr(buf);
|
||||
}
|
||||
#endif
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
void *wifi_get_country_code(char *ccode)
|
||||
{
|
||||
DHD_TRACE(("%s\n", __FUNCTION__));
|
||||
#ifdef CONFIG_WIFI_CONTROL_FUNC
|
||||
if (!ccode)
|
||||
return NULL;
|
||||
if (wifi_control_data && wifi_control_data->get_country_code) {
|
||||
return wifi_control_data->get_country_code(ccode);
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int wifi_probe(struct platform_device *pdev)
|
||||
{
|
||||
#ifdef CONFIG_WIFI_CONTROL_FUNC
|
||||
struct wifi_platform_data *wifi_ctrl =
|
||||
(struct wifi_platform_data *)(pdev->dev.platform_data);
|
||||
|
||||
wifi_control_data = wifi_ctrl;
|
||||
#endif
|
||||
|
||||
DHD_TRACE(("## %s\n", __FUNCTION__));
|
||||
wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcm4329_wlan_irq");
|
||||
wifi_control_data = wifi_ctrl;
|
||||
|
||||
wifi_set_power(1, 0); /* Power On */
|
||||
wifi_set_carddetect(1); /* CardDetect (0->1) */
|
||||
|
|
@ -167,34 +149,26 @@ static int wifi_probe(struct platform_device *pdev)
|
|||
|
||||
static int wifi_remove(struct platform_device *pdev)
|
||||
{
|
||||
#ifdef CONFIG_WIFI_CONTROL_FUNC
|
||||
struct wifi_platform_data *wifi_ctrl =
|
||||
(struct wifi_platform_data *)(pdev->dev.platform_data);
|
||||
|
||||
wifi_control_data = wifi_ctrl;
|
||||
#endif
|
||||
DHD_TRACE(("## %s\n", __FUNCTION__));
|
||||
wifi_control_data = wifi_ctrl;
|
||||
|
||||
wifi_set_power(0, 0); /* Power Off */
|
||||
wifi_set_carddetect(0); /* CardDetect (1->0) */
|
||||
|
||||
up(&wifi_control_sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
DHD_TRACE(("##> %s\n", __FUNCTION__));
|
||||
#if defined(OOB_INTR_ONLY)
|
||||
bcmsdh_oob_intr_set(0);
|
||||
#endif /* (OOB_INTR_ONLY) */
|
||||
return 0;
|
||||
}
|
||||
static int wifi_resume(struct platform_device *pdev)
|
||||
{
|
||||
DHD_TRACE(("##> %s\n", __FUNCTION__));
|
||||
#if defined(OOB_INTR_ONLY)
|
||||
bcmsdh_oob_intr_set(1);
|
||||
#endif /* (OOB_INTR_ONLY) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -219,14 +193,8 @@ void wifi_del_dev(void)
|
|||
DHD_TRACE(("## Unregister platform_driver_register\n"));
|
||||
platform_driver_unregister(&wifi_device);
|
||||
}
|
||||
#endif /* defined(CUSTOMER_HW2) */
|
||||
#endif /* defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */
|
||||
|
||||
static int dhd_device_event(struct notifier_block *this, unsigned long event,
|
||||
void *ptr);
|
||||
|
||||
static struct notifier_block dhd_notifier = {
|
||||
.notifier_call = dhd_device_event
|
||||
};
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
|
||||
#include <linux/suspend.h>
|
||||
|
|
@ -412,7 +380,7 @@ uint dhd_roam = 1;
|
|||
uint dhd_radio_up = 1;
|
||||
|
||||
/* Network inteface name */
|
||||
char iface_name[IFNAMSIZ];
|
||||
char iface_name[IFNAMSIZ] = "wlan0";
|
||||
module_param_string(iface_name, iface_name, IFNAMSIZ, 0);
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
|
||||
|
|
@ -800,13 +768,13 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
|
|||
ASSERT(dhd && dhd->iflist[ifidx]);
|
||||
dev = dhd->iflist[ifidx]->net;
|
||||
|
||||
NETIF_ADDR_LOCK(dev);
|
||||
netif_addr_lock_bh(dev);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
|
||||
cnt = netdev_mc_count(dev);
|
||||
#else
|
||||
cnt = dev->mc_count;
|
||||
#endif
|
||||
NETIF_ADDR_UNLOCK(dev);
|
||||
netif_addr_unlock_bh(dev);
|
||||
|
||||
/* Determine initial value of allmulti flag */
|
||||
allmulti = (dev->flags & IFF_ALLMULTI) ? TRUE : FALSE;
|
||||
|
|
@ -826,7 +794,7 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
|
|||
memcpy(bufp, &cnt, sizeof(cnt));
|
||||
bufp += sizeof(cnt);
|
||||
|
||||
NETIF_ADDR_LOCK(dev);
|
||||
netif_addr_lock_bh(dev);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
|
||||
netdev_for_each_mc_addr(ha, dev) {
|
||||
if (!cnt)
|
||||
|
|
@ -836,12 +804,12 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
|
|||
cnt--;
|
||||
}
|
||||
#else
|
||||
for (mclist = dev->mc_list; (mclist && (cnt > 0)); cnt--, mclist = mclist->next) {
|
||||
for (mclist = dev->mc_list;(mclist && (cnt > 0)); cnt--, mclist = mclist->next) {
|
||||
memcpy(bufp, (void *)mclist->dmi_addr, ETHER_ADDR_LEN);
|
||||
bufp += ETHER_ADDR_LEN;
|
||||
}
|
||||
#endif
|
||||
NETIF_ADDR_UNLOCK(dev);
|
||||
netif_addr_unlock_bh(dev);
|
||||
|
||||
memset(&ioc, 0, sizeof(ioc));
|
||||
ioc.cmd = WLC_SET_VAR;
|
||||
|
|
@ -1939,11 +1907,10 @@ dhd_open(struct net_device *net)
|
|||
wl_control_wl_start(net);
|
||||
|
||||
ifidx = dhd_net2idx(dhd, net);
|
||||
if (ifidx == DHD_BAD_IF)
|
||||
return -1;
|
||||
DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx));
|
||||
|
||||
if (ifidx == DHD_BAD_IF)
|
||||
return -1;
|
||||
|
||||
if ((dhd->iflist[ifidx]) && (dhd->iflist[ifidx]->state == WLC_E_IF_DEL)) {
|
||||
DHD_ERROR(("%s: Error: called when IF already deleted\n", __FUNCTION__));
|
||||
return -1;
|
||||
|
|
@ -2044,7 +2011,6 @@ dhd_del_if(dhd_info_t *dhd, int ifidx)
|
|||
up(&dhd->sysioc_sem);
|
||||
}
|
||||
|
||||
|
||||
dhd_pub_t *
|
||||
dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
|
||||
{
|
||||
|
|
@ -2187,6 +2153,9 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
|
|||
*/
|
||||
memcpy(netdev_priv(net), &dhd, sizeof(dhd));
|
||||
|
||||
#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
|
||||
g_bus = bus;
|
||||
#endif
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
|
||||
register_pm_notifier(&dhd_sleep_pm_notifier);
|
||||
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
|
||||
|
|
@ -2198,8 +2167,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
|
|||
register_early_suspend(&dhd->early_suspend);
|
||||
#endif
|
||||
|
||||
register_inetaddr_notifier(&dhd_notifier);
|
||||
|
||||
return &dhd->pub;
|
||||
|
||||
fail:
|
||||
|
|
@ -2225,15 +2192,12 @@ dhd_bus_start(dhd_pub_t *dhdp)
|
|||
|
||||
DHD_TRACE(("%s: \n", __FUNCTION__));
|
||||
|
||||
dhd_os_sdlock(dhdp);
|
||||
|
||||
/* try to download image and nvram to the dongle */
|
||||
if (dhd->pub.busstate == DHD_BUS_DOWN) {
|
||||
if (!(dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh,
|
||||
fw_path, nv_path))) {
|
||||
DHD_ERROR(("%s: dhdsdio_probe_download failed. firmware = %s nvram = %s\n",
|
||||
__FUNCTION__, fw_path, nv_path));
|
||||
dhd_os_sdunlock(dhdp);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -2243,9 +2207,8 @@ dhd_bus_start(dhd_pub_t *dhdp)
|
|||
dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms);
|
||||
|
||||
/* Bring up the bus */
|
||||
if ((ret = dhd_bus_init(&dhd->pub, FALSE)) != 0) {
|
||||
if ((ret = dhd_bus_init(&dhd->pub, TRUE)) != 0) {
|
||||
DHD_ERROR(("%s, dhd_bus_init failed %d\n", __FUNCTION__, ret));
|
||||
dhd_os_sdunlock(dhdp);
|
||||
return ret;
|
||||
}
|
||||
#if defined(OOB_INTR_ONLY)
|
||||
|
|
@ -2254,7 +2217,6 @@ dhd_bus_start(dhd_pub_t *dhdp)
|
|||
dhd->wd_timer_valid = FALSE;
|
||||
del_timer_sync(&dhd->timer);
|
||||
DHD_ERROR(("%s Host failed to resgister for OOB\n", __FUNCTION__));
|
||||
dhd_os_sdunlock(dhdp);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
|
@ -2267,12 +2229,9 @@ dhd_bus_start(dhd_pub_t *dhdp)
|
|||
dhd->wd_timer_valid = FALSE;
|
||||
del_timer_sync(&dhd->timer);
|
||||
DHD_ERROR(("%s failed bus is not ready\n", __FUNCTION__));
|
||||
dhd_os_sdunlock(dhdp);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dhd_os_sdunlock(dhdp);
|
||||
|
||||
#ifdef EMBEDDED_PLATFORM
|
||||
bcm_mkiovar("event_msgs", dhdp->eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
|
||||
dhdcdc_query_ioctl(dhdp, 0, WLC_GET_VAR, iovbuf, sizeof(iovbuf));
|
||||
|
|
@ -2304,12 +2263,9 @@ dhd_bus_start(dhd_pub_t *dhdp)
|
|||
/* enable dongle roaming event */
|
||||
setbit(dhdp->eventmask, WLC_E_ROAM);
|
||||
|
||||
dhdp->pktfilter_count = 4;
|
||||
dhdp->pktfilter_count = 1;
|
||||
/* Setup filter to allow only unicast */
|
||||
dhdp->pktfilter[0] = "100 0 0 0 0x01 0x00";
|
||||
dhdp->pktfilter[1] = NULL;
|
||||
dhdp->pktfilter[2] = NULL;
|
||||
dhdp->pktfilter[3] = NULL;
|
||||
#endif /* EMBEDDED_PLATFORM */
|
||||
|
||||
/* Bus is ready, do any protocol initialization */
|
||||
|
|
@ -2363,48 +2319,6 @@ static struct net_device_ops dhd_ops_virt = {
|
|||
};
|
||||
#endif
|
||||
|
||||
static int dhd_device_event(struct notifier_block *this, unsigned long event,
|
||||
void *ptr)
|
||||
{
|
||||
struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
|
||||
dhd_info_t *dhd;
|
||||
dhd_pub_t *dhd_pub;
|
||||
|
||||
if (!ifa)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
dhd = *(dhd_info_t **)netdev_priv(ifa->ifa_dev->dev);
|
||||
dhd_pub = &dhd->pub;
|
||||
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 31))
|
||||
if (ifa->ifa_dev->dev->netdev_ops == &dhd_ops_pri) {
|
||||
#else
|
||||
if (ifa->ifa_dev->dev->open == &dhd_open) {
|
||||
#endif
|
||||
switch (event) {
|
||||
case NETDEV_UP:
|
||||
DHD_TRACE(("%s: [%s] Up IP: 0x%x\n",
|
||||
__FUNCTION__, ifa->ifa_label, ifa->ifa_address));
|
||||
|
||||
dhd_arp_cleanup(dhd_pub);
|
||||
break;
|
||||
|
||||
case NETDEV_DOWN:
|
||||
DHD_TRACE(("%s: [%s] Down IP: 0x%x\n",
|
||||
__FUNCTION__, ifa->ifa_label, ifa->ifa_address));
|
||||
|
||||
dhd_arp_cleanup(dhd_pub);
|
||||
break;
|
||||
|
||||
default:
|
||||
DHD_TRACE(("%s: [%s] Event: %lu\n",
|
||||
__FUNCTION__, ifa->ifa_label, event));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
int
|
||||
dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
|
||||
{
|
||||
|
|
@ -2478,7 +2392,6 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
|
|||
dhd->pub.mac.octet[0], dhd->pub.mac.octet[1], dhd->pub.mac.octet[2],
|
||||
dhd->pub.mac.octet[3], dhd->pub.mac.octet[4], dhd->pub.mac.octet[5]);
|
||||
|
||||
|
||||
#if defined(CONFIG_WIRELESS_EXT)
|
||||
#if defined(CONFIG_FIRST_SCAN)
|
||||
#ifdef SOFTAP
|
||||
|
|
@ -2544,8 +2457,6 @@ dhd_detach(dhd_pub_t *dhdp)
|
|||
dhd_if_t *ifp;
|
||||
int i;
|
||||
|
||||
unregister_inetaddr_notifier(&dhd_notifier);
|
||||
|
||||
#if defined(CONFIG_HAS_EARLYSUSPEND)
|
||||
if (dhd->early_suspend.suspend)
|
||||
unregister_early_suspend(&dhd->early_suspend);
|
||||
|
|
@ -2610,8 +2521,8 @@ dhd_detach(dhd_pub_t *dhdp)
|
|||
}
|
||||
}
|
||||
|
||||
static void __exit
|
||||
dhd_module_cleanup(void)
|
||||
void
|
||||
rockchip_wifi_exit_module(void)
|
||||
{
|
||||
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
|
||||
|
||||
|
|
@ -2621,15 +2532,17 @@ dhd_module_cleanup(void)
|
|||
#endif
|
||||
/* Call customer gpio to turn off power with WL_REG_ON signal */
|
||||
dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
|
||||
bcm4329_power_save_exit();
|
||||
}
|
||||
|
||||
static int __init
|
||||
dhd_module_init(void)
|
||||
int
|
||||
rockchip_wifi_init_module(void)
|
||||
{
|
||||
int error;
|
||||
|
||||
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
|
||||
|
||||
printk("BCM4329 Wi-Fi driver (Powered by Rockchip,Ver %s) init.\n", BCM4329_DRV_VERSION);
|
||||
/* Sanity check on the module parameters */
|
||||
do {
|
||||
/* Both watchdog and DPC as tasklets are ok */
|
||||
|
|
@ -2688,6 +2601,8 @@ dhd_module_init(void)
|
|||
goto fail_2;
|
||||
}
|
||||
#endif
|
||||
bcm4329_power_save_init();
|
||||
|
||||
return error;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
|
||||
fail_2:
|
||||
|
|
@ -2705,8 +2620,23 @@ fail_0:
|
|||
return error;
|
||||
}
|
||||
|
||||
module_init(dhd_module_init);
|
||||
module_exit(dhd_module_cleanup);
|
||||
//module_init(dhd_module_init);
|
||||
//module_exit(dhd_module_cleanup);
|
||||
int mv88w8686_if_sdio_init_module(void)
|
||||
{
|
||||
return rockchip_wifi_init_module();
|
||||
}
|
||||
|
||||
void mv88w8686_if_sdio_exit_module(void)
|
||||
{
|
||||
rockchip_wifi_exit_module();
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(rockchip_wifi_init_module);
|
||||
EXPORT_SYMBOL(rockchip_wifi_exit_module);
|
||||
EXPORT_SYMBOL(mv88w8686_if_sdio_init_module);
|
||||
EXPORT_SYMBOL(mv88w8686_if_sdio_exit_module);
|
||||
|
||||
|
||||
/*
|
||||
* OS specific functions required to implement DHD driver in OS independent way
|
||||
|
|
@ -3080,35 +3010,6 @@ int net_os_set_dtim_skip(struct net_device *dev, int val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num)
|
||||
{
|
||||
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
|
||||
char *filterp = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!dhd || (num == DHD_UNICAST_FILTER_NUM))
|
||||
return ret;
|
||||
if (num >= dhd->pub.pktfilter_count)
|
||||
return -EINVAL;
|
||||
if (add_remove) {
|
||||
switch (num) {
|
||||
case DHD_BROADCAST_FILTER_NUM:
|
||||
filterp = "101 0 0 0 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF";
|
||||
break;
|
||||
case DHD_MULTICAST4_FILTER_NUM:
|
||||
filterp = "102 0 0 0 0xFFFFFF 0x01005E";
|
||||
break;
|
||||
case DHD_MULTICAST6_FILTER_NUM:
|
||||
filterp = "103 0 0 0 0xFFFF 0x3333";
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
dhd->pub.pktfilter[num] = filterp;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int net_os_set_packet_filter(struct net_device *dev, int val)
|
||||
{
|
||||
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
|
||||
|
|
@ -3162,12 +3063,11 @@ dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled)
|
|||
|
||||
/* Linux wrapper to call common dhd_pno_set */
|
||||
int
|
||||
dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid,
|
||||
ushort scan_fr, int pno_repeat, int pno_freq_expo_max)
|
||||
dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr)
|
||||
{
|
||||
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
|
||||
|
||||
return (dhd_pno_set(&dhd->pub, ssids_local, nssid, scan_fr, pno_repeat, pno_freq_expo_max));
|
||||
return (dhd_pno_set(&dhd->pub, ssids_local, nssid, scan_fr));
|
||||
}
|
||||
|
||||
/* Linux wrapper to get pno status */
|
||||
|
|
@ -3195,20 +3095,20 @@ int net_os_send_hang_message(struct net_device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec)
|
||||
void dhd_bus_country_set(struct net_device *dev, char *country_code)
|
||||
{
|
||||
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
|
||||
|
||||
if (dhd && dhd->pub.up)
|
||||
memcpy(&dhd->pub.dhd_cspec, cspec, sizeof(wl_country_t));
|
||||
strncpy(dhd->pub.country_code, country_code, WLC_CNTRY_BUF_SZ);
|
||||
}
|
||||
|
||||
char *dhd_bus_country_get(struct net_device *dev)
|
||||
{
|
||||
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
|
||||
|
||||
if (dhd && (dhd->pub.dhd_cspec.ccode[0] != 0))
|
||||
return dhd->pub.dhd_cspec.ccode;
|
||||
if (dhd && (dhd->pub.country_code[0] != 0))
|
||||
return dhd->pub.country_code;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -428,6 +428,7 @@ static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start);
|
|||
|
||||
#ifdef DHD_DEBUG_TRAP
|
||||
static int dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size);
|
||||
static int dhdsdio_mem_dump(dhd_bus_t *bus);
|
||||
#endif /* DHD_DEBUG_TRAP */
|
||||
static int dhdsdio_download_state(dhd_bus_t *bus, bool enter);
|
||||
|
||||
|
|
@ -1844,6 +1845,11 @@ dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size)
|
|||
DHD_ERROR(("%s: %s\n", __FUNCTION__, strbuf.origbuf));
|
||||
}
|
||||
|
||||
if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
|
||||
/* Mem dump to a file on device */
|
||||
dhdsdio_mem_dump(bus);
|
||||
}
|
||||
|
||||
done:
|
||||
if (mbuffer)
|
||||
MFREE(bus->dhd->osh, mbuffer, msize);
|
||||
|
|
@ -1852,6 +1858,60 @@ done:
|
|||
|
||||
return bcmerror;
|
||||
}
|
||||
|
||||
static int
|
||||
dhdsdio_mem_dump(dhd_bus_t *bus)
|
||||
{
|
||||
int ret = 0;
|
||||
int size; /* Full mem size */
|
||||
int start = 0; /* Start address */
|
||||
int read_size = 0; /* Read size of each iteration */
|
||||
uint8 *buf = NULL, *databuf = NULL;
|
||||
|
||||
/* Get full mem size */
|
||||
size = bus->ramsize;
|
||||
buf = MALLOC(bus->dhd->osh, size);
|
||||
if (!buf) {
|
||||
printf("%s: Out of memory (%d bytes)\n", __FUNCTION__, size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read mem content */
|
||||
printf("Dump dongle memory");
|
||||
databuf = buf;
|
||||
while (size)
|
||||
{
|
||||
read_size = MIN(MEMBLOCK, size);
|
||||
if ((ret = dhdsdio_membytes(bus, FALSE, start, databuf, read_size)))
|
||||
{
|
||||
printf("%s: Error membytes %d\n", __FUNCTION__, ret);
|
||||
if (buf) {
|
||||
MFREE(bus->dhd->osh, buf, size);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
printf(".");
|
||||
|
||||
/* Decrement size and increment start address */
|
||||
size -= read_size;
|
||||
start += read_size;
|
||||
databuf += read_size;
|
||||
}
|
||||
printf("Done\n");
|
||||
|
||||
#ifdef DHD_DEBUG
|
||||
/* free buf before return !!! */
|
||||
if (write_to_file(bus->dhd, buf, bus->ramsize))
|
||||
{
|
||||
printf("%s: Error writing to files\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
/* buf free handled in write_to_file, not here */
|
||||
#else
|
||||
MFREE(bus->dhd->osh, buf, size);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif /* DHD_DEBUG_TRAP */
|
||||
|
||||
#ifdef DHD_DEBUG
|
||||
|
|
|
|||
|
|
@ -33,16 +33,16 @@
|
|||
|
||||
#define EPI_RC_NUMBER 248
|
||||
|
||||
#define EPI_INCREMENTAL_NUMBER 23
|
||||
#define EPI_INCREMENTAL_NUMBER 18
|
||||
|
||||
#define EPI_BUILD_NUMBER 0
|
||||
|
||||
#define EPI_VERSION 4, 218, 248, 23
|
||||
#define EPI_VERSION 4, 218, 248, 18
|
||||
|
||||
#define EPI_VERSION_NUM 0x04daf817
|
||||
#define EPI_VERSION_NUM 0x04daf812
|
||||
|
||||
|
||||
#define EPI_VERSION_STR "4.218.248.23"
|
||||
#define EPI_ROUTER_VERSION_STR "4.219.248.23"
|
||||
#define EPI_VERSION_STR "4.218.248.18"
|
||||
#define EPI_ROUTER_VERSION_STR "4.219.248.18"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
* software in any way with any other Broadcom software provided under a license
|
||||
* other than the GPL, without Broadcom's express prior written consent.
|
||||
*
|
||||
* $Id: wlioctl.h,v 1.601.4.15.2.14.2.62.4.3 2011/02/09 23:31:02 Exp $
|
||||
* $Id: wlioctl.h,v 1.601.4.15.2.14.2.62.4.1 2010/11/17 03:09:28 Exp $
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -254,11 +254,6 @@ typedef struct wl_join_params {
|
|||
|
||||
#define WLC_CNTRY_BUF_SZ 4
|
||||
|
||||
typedef struct wl_country {
|
||||
char country_abbrev[WLC_CNTRY_BUF_SZ];
|
||||
int32 rev;
|
||||
char ccode[WLC_CNTRY_BUF_SZ];
|
||||
} wl_country_t;
|
||||
|
||||
typedef enum sup_auth_status {
|
||||
|
||||
|
|
@ -862,7 +857,7 @@ typedef struct wl_ioctl {
|
|||
#define PM_MAX 1
|
||||
#define PM_FAST 2
|
||||
|
||||
#define LISTEN_INTERVAL 10
|
||||
#define LISTEN_INTERVAL 20
|
||||
|
||||
#define INTERFERE_NONE 0
|
||||
#define NON_WLAN 1
|
||||
|
|
@ -1314,16 +1309,12 @@ enum {
|
|||
#define ENABLE_BKGRD_SCAN_BIT 2
|
||||
#define IMMEDIATE_SCAN_BIT 3
|
||||
#define AUTO_CONNECT_BIT 4
|
||||
#define ENABLE_BD_SCAN_BIT 5
|
||||
#define ENABLE_ADAPTSCAN_BIT 6
|
||||
|
||||
#define SORT_CRITERIA_MASK 0x01
|
||||
#define AUTO_NET_SWITCH_MASK 0x02
|
||||
#define ENABLE_BKGRD_SCAN_MASK 0x04
|
||||
#define IMMEDIATE_SCAN_MASK 0x08
|
||||
#define AUTO_CONNECT_MASK 0x10
|
||||
#define ENABLE_BD_SCAN_MASK 0x20
|
||||
#define ENABLE_ADAPTSCAN_MASK 0x40
|
||||
|
||||
#define PFN_VERSION 1
|
||||
|
||||
|
|
@ -1336,8 +1327,6 @@ typedef struct wl_pfn_param {
|
|||
int32 lost_network_timeout;
|
||||
int16 flags;
|
||||
int16 rssi_margin;
|
||||
int32 repeat_scan;
|
||||
int32 max_freq_adjust;
|
||||
} wl_pfn_param_t;
|
||||
|
||||
typedef struct wl_pfn {
|
||||
|
|
@ -1347,12 +1336,14 @@ typedef struct wl_pfn {
|
|||
int32 auth;
|
||||
uint32 wpa_auth;
|
||||
int32 wsec;
|
||||
#ifdef WLPFN_AUTO_CONNECT
|
||||
union {
|
||||
wl_wsec_key_t sec_key;
|
||||
wsec_pmk_t wpa_sec_key;
|
||||
} pfn_security;
|
||||
#endif
|
||||
} wl_pfn_t;
|
||||
|
||||
#define PNO_SCAN_MAX_FW 508*1000
|
||||
#define PNO_SCAN_MAX_FW_SEC PNO_SCAN_MAX_FW/1000
|
||||
#define PNO_SCAN_MIN_FW_SEC 10
|
||||
|
||||
|
||||
#define TOE_TX_CSUM_OL 0x00000001
|
||||
#define TOE_RX_CSUM_OL 0x00000002
|
||||
|
|
|
|||
|
|
@ -247,10 +247,8 @@ void*
|
|||
osl_pktget(osl_t *osh, uint len)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
gfp_t flags;
|
||||
|
||||
flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
|
||||
if ((skb = __dev_alloc_skb(len, flags))) {
|
||||
if ((skb = dev_alloc_skb(len))) {
|
||||
skb_put(skb, len);
|
||||
skb->priority = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
* software in any way with any other Broadcom software provided under a license
|
||||
* other than the GPL, without Broadcom's express prior written consent.
|
||||
*
|
||||
* $Id: wl_iw.c,v 1.51.4.9.2.6.4.142.4.78 2011/02/11 21:27:52 Exp $
|
||||
* $Id: wl_iw.c,v 1.51.4.9.2.6.4.142.4.69 2010/12/21 03:00:08 Exp $
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -54,11 +54,10 @@ typedef const struct si_pub si_t;
|
|||
#define WL_INFORM(x)
|
||||
#define WL_WSEC(x)
|
||||
#define WL_SCAN(x)
|
||||
#define WL_PNO(x)
|
||||
#define WL_TRACE_COEX(x)
|
||||
|
||||
#include <wl_iw.h>
|
||||
|
||||
#include <linux/wakelock.h>
|
||||
|
||||
|
||||
#ifndef IW_ENCODE_ALG_SM4
|
||||
|
|
@ -116,6 +115,10 @@ static int g_onoff = G_WLAN_SET_ON;
|
|||
wl_iw_extra_params_t g_wl_iw_params;
|
||||
static struct mutex wl_cache_lock;
|
||||
|
||||
#ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY
|
||||
static bool use_non_dfs_channels = true;
|
||||
#endif
|
||||
|
||||
extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status,
|
||||
uint32 reason, char* stringBuf, uint buflen);
|
||||
#include <bcmsdbus.h>
|
||||
|
|
@ -158,13 +161,12 @@ extern int dhd_wait_pend8021x(struct net_device *dev);
|
|||
#endif
|
||||
|
||||
static void *g_scan = NULL;
|
||||
static volatile uint g_scan_specified_ssid;
|
||||
static wlc_ssid_t g_specific_ssid;
|
||||
static volatile uint g_scan_specified_ssid;
|
||||
static wlc_ssid_t g_specific_ssid;
|
||||
|
||||
static wlc_ssid_t g_ssid;
|
||||
|
||||
bool btcoex_is_sco_active(struct net_device *dev);
|
||||
static wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl;
|
||||
static wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl;
|
||||
#if defined(CONFIG_FIRST_SCAN)
|
||||
static volatile uint g_first_broadcast_scan;
|
||||
static volatile uint g_first_counter_scans;
|
||||
|
|
@ -592,36 +594,6 @@ wl_iw_set_passive_scan(
|
|||
return error;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
wl_iw_set_txpower(
|
||||
struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu,
|
||||
char *extra
|
||||
)
|
||||
{
|
||||
int error = 0;
|
||||
char *p = extra;
|
||||
int txpower = -1;
|
||||
|
||||
txpower = bcm_atoi(extra + strlen(TXPOWER_SET_CMD) + 1);
|
||||
if ((txpower >= 0) && (txpower <= 127)) {
|
||||
txpower |= WL_TXPWR_OVERRIDE;
|
||||
txpower = htod32(txpower);
|
||||
|
||||
error = dev_wlc_intvar_set(dev, "qtxpower", txpower);
|
||||
p += snprintf(p, MAX_WX_STRING, "OK");
|
||||
WL_TRACE(("%s: set TXpower 0x%X is OK\n", __FUNCTION__, txpower));
|
||||
} else {
|
||||
WL_ERROR(("%s: set tx power failed\n", __FUNCTION__));
|
||||
p += snprintf(p, MAX_WX_STRING, "FAIL");
|
||||
}
|
||||
|
||||
wrqu->data.length = p - extra + 1;
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
wl_iw_get_macaddr(
|
||||
struct net_device *dev,
|
||||
|
|
@ -647,6 +619,31 @@ wl_iw_get_macaddr(
|
|||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
wl_iw_set_country_code(struct net_device *dev, char *ccode)
|
||||
{
|
||||
char country_code[WLC_CNTRY_BUF_SZ];
|
||||
int ret = -1;
|
||||
|
||||
WL_TRACE(("%s\n", __FUNCTION__));
|
||||
if (!ccode)
|
||||
ccode = dhd_bus_country_get(dev);
|
||||
strncpy(country_code, ccode, sizeof(country_code));
|
||||
if (ccode && (country_code[0] != 0)) {
|
||||
#ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY
|
||||
if (use_non_dfs_channels && !strncmp(country_code, "US", 2))
|
||||
strncpy(country_code, "Q2", WLC_CNTRY_BUF_SZ);
|
||||
if (!use_non_dfs_channels && !strncmp(country_code, "Q2", 2))
|
||||
strncpy(country_code, "US", WLC_CNTRY_BUF_SZ);
|
||||
#endif
|
||||
ret = dev_wlc_ioctl(dev, WLC_SET_COUNTRY, &country_code, sizeof(country_code));
|
||||
if (ret >= 0) {
|
||||
WL_TRACE(("%s: set country %s OK\n", __FUNCTION__, country_code));
|
||||
dhd_bus_country_set(dev, &country_code[0]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
wl_iw_set_country(
|
||||
|
|
@ -661,39 +658,25 @@ wl_iw_set_country(
|
|||
char *p = extra;
|
||||
int country_offset;
|
||||
int country_code_size;
|
||||
wl_country_t cspec = {{0}, 0, {0}};
|
||||
char smbuf[WLC_IOCTL_SMLEN];
|
||||
|
||||
cspec.rev = -1;
|
||||
WL_TRACE(("%s\n", __FUNCTION__));
|
||||
memset(country_code, 0, sizeof(country_code));
|
||||
memset(smbuf, 0, sizeof(smbuf));
|
||||
|
||||
country_offset = strcspn(extra, " ");
|
||||
country_code_size = strlen(extra) - country_offset;
|
||||
|
||||
if (country_offset != 0) {
|
||||
strncpy(country_code, extra + country_offset +1,
|
||||
strncpy(country_code, extra + country_offset + 1,
|
||||
MIN(country_code_size, sizeof(country_code)));
|
||||
|
||||
|
||||
memcpy(cspec.country_abbrev, country_code, WLC_CNTRY_BUF_SZ);
|
||||
memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ);
|
||||
|
||||
get_customized_country_code((char *)&cspec.country_abbrev, &cspec);
|
||||
|
||||
if ((error = dev_iw_iovar_setbuf(dev, "country", &cspec, \
|
||||
sizeof(cspec), smbuf, sizeof(smbuf))) >= 0) {
|
||||
error = wl_iw_set_country_code(dev, country_code);
|
||||
if (error >= 0) {
|
||||
p += snprintf(p, MAX_WX_STRING, "OK");
|
||||
WL_ERROR(("%s: set country for %s as %s rev %d is OK\n", \
|
||||
__FUNCTION__, country_code, cspec.ccode, cspec.rev));
|
||||
dhd_bus_country_set(dev, &cspec);
|
||||
WL_TRACE(("%s: set country %s OK\n", __FUNCTION__, country_code));
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
WL_ERROR(("%s: set country for %s as %s rev %d failed\n", \
|
||||
__FUNCTION__, country_code, cspec.ccode, cspec.rev));
|
||||
|
||||
WL_ERROR(("%s: set country %s failed code %d\n", __FUNCTION__, country_code, error));
|
||||
p += snprintf(p, MAX_WX_STRING, "FAIL");
|
||||
|
||||
exit:
|
||||
|
|
@ -701,6 +684,33 @@ exit:
|
|||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
wl_iw_get_country(
|
||||
struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu,
|
||||
char *extra
|
||||
)
|
||||
{
|
||||
char *ccode;
|
||||
int current_channels;
|
||||
|
||||
WL_TRACE(("%s\n", __FUNCTION__));
|
||||
|
||||
ccode = dhd_bus_country_get(dev);
|
||||
if(ccode){
|
||||
if(0 == strcmp(ccode, "Q2"))
|
||||
current_channels = 11;
|
||||
else if(0 == strcmp(ccode, "EU"))
|
||||
current_channels = 13;
|
||||
else if(0 == strcmp(ccode, "JP"))
|
||||
current_channels = 14;
|
||||
}
|
||||
sprintf(extra, "Scan-Channels = %d", current_channels);
|
||||
printk("Get Channels return %d,(country code = %s)\n",current_channels, ccode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CUSTOMER_HW2
|
||||
static int
|
||||
wl_iw_set_power_mode(
|
||||
|
|
@ -755,40 +765,26 @@ wl_iw_set_power_mode(
|
|||
#endif
|
||||
|
||||
|
||||
bool btcoex_is_sco_active(struct net_device *dev)
|
||||
static bool btcoex_is_sco_active(struct net_device *dev)
|
||||
{
|
||||
int ioc_res = 0;
|
||||
bool res = false;
|
||||
int sco_id_cnt = 0;
|
||||
int param27;
|
||||
int i;
|
||||
int temp = 0;
|
||||
|
||||
for (i = 0; i < 12; i++) {
|
||||
ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 4, &temp);
|
||||
|
||||
ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 27, ¶m27);
|
||||
if (ioc_res == 0) {
|
||||
WL_TRACE_COEX(("%s: read btc_params[4] = %x\n", __FUNCTION__, temp));
|
||||
|
||||
WL_TRACE_COEX(("%s, sample[%d], btc params: 27:%x\n",
|
||||
__FUNCTION__, i, param27));
|
||||
|
||||
if (ioc_res < 0) {
|
||||
WL_ERROR(("%s ioc read btc params error\n", __FUNCTION__));
|
||||
break;
|
||||
}
|
||||
|
||||
if ((param27 & 0x6) == 2) {
|
||||
sco_id_cnt++;
|
||||
}
|
||||
|
||||
if (sco_id_cnt > 2) {
|
||||
WL_TRACE_COEX(("%s, sco/esco detected, pkt id_cnt:%d samples:%d\n",
|
||||
__FUNCTION__, sco_id_cnt, i));
|
||||
if ((temp > 0xea0) && (temp < 0xed8)) {
|
||||
WL_TRACE_COEX(("%s: BT SCO/eSCO is ACTIVE\n", __FUNCTION__));
|
||||
res = true;
|
||||
break;
|
||||
} else {
|
||||
WL_TRACE_COEX(("%s: BT SCO/eSCO is NOT detected\n", __FUNCTION__));
|
||||
}
|
||||
|
||||
msleep(5);
|
||||
} else {
|
||||
WL_ERROR(("%s ioc read btc params error\n", __FUNCTION__));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -1074,6 +1070,21 @@ wl_iw_set_suspend(
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY
|
||||
static int
|
||||
wl_iw_set_dfs_channels(
|
||||
struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu,
|
||||
char *extra
|
||||
)
|
||||
{
|
||||
use_non_dfs_channels = *(extra + strlen(SETDFSCHANNELS_CMD) + 1) - '0';
|
||||
use_non_dfs_channels = (use_non_dfs_channels != 0) ? false : true;
|
||||
wl_iw_set_country_code(dev, NULL);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len)
|
||||
|
|
@ -1359,10 +1370,9 @@ wl_iw_set_pno_set(
|
|||
int nssid = 0;
|
||||
cmd_tlv_t *cmd_tlv_temp;
|
||||
char *str_ptr;
|
||||
char *str_ptr_end;
|
||||
int tlv_size_left;
|
||||
int pno_time;
|
||||
int pno_repeat;
|
||||
int pno_freq_expo_max;
|
||||
|
||||
#ifdef PNO_SET_DEBUG
|
||||
int i;
|
||||
|
|
@ -1376,10 +1386,6 @@ wl_iw_set_pno_set(
|
|||
'G', 'O', 'O', 'G',
|
||||
'T',
|
||||
'1','E',
|
||||
'R',
|
||||
'2',
|
||||
'M',
|
||||
'2',
|
||||
0x00
|
||||
};
|
||||
#endif
|
||||
|
|
@ -1423,7 +1429,6 @@ wl_iw_set_pno_set(
|
|||
|
||||
cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
|
||||
memset(ssids_local, 0, sizeof(ssids_local));
|
||||
pno_repeat = pno_freq_expo_max = 0;
|
||||
|
||||
if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) && \
|
||||
(cmd_tlv_temp->version == PNO_TLV_VERSION) && \
|
||||
|
|
@ -1444,28 +1449,9 @@ wl_iw_set_pno_set(
|
|||
goto exit_proc;
|
||||
}
|
||||
str_ptr++;
|
||||
pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
|
||||
WL_PNO(("%s: pno_time=%d\n", __FUNCTION__, pno_time));
|
||||
|
||||
if (str_ptr[0] != 0) {
|
||||
if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
|
||||
WL_ERROR(("%s pno repeat : corrupted field\n", \
|
||||
__FUNCTION__));
|
||||
goto exit_proc;
|
||||
}
|
||||
str_ptr++;
|
||||
pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
|
||||
WL_PNO(("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat));
|
||||
if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
|
||||
WL_ERROR(("%s FREQ_EXPO_MAX corrupted field size\n", \
|
||||
__FUNCTION__));
|
||||
goto exit_proc;
|
||||
}
|
||||
str_ptr++;
|
||||
pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
|
||||
WL_PNO(("%s: pno_freq_expo_max=%d\n", \
|
||||
__FUNCTION__, pno_freq_expo_max));
|
||||
}
|
||||
pno_time = simple_strtoul(str_ptr, &str_ptr_end, 16);
|
||||
WL_ERROR((" got %d bytes left pno_time %d or %#x\n", \
|
||||
tlv_size_left, pno_time, pno_time));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -1473,7 +1459,7 @@ wl_iw_set_pno_set(
|
|||
goto exit_proc;
|
||||
}
|
||||
|
||||
res = dhd_dev_pno_set(dev, ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max);
|
||||
res = dhd_dev_pno_set(dev, ssids_local, nssid, pno_time);
|
||||
|
||||
exit_proc:
|
||||
net_os_wake_unlock(dev);
|
||||
|
|
@ -1760,79 +1746,6 @@ int hstr_2_buf(const char *txt, u8 *buf, int len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(SOFTAP) && defined(SOFTAP_TLV_CFG)
|
||||
|
||||
static int wl_iw_softap_cfg_tlv(
|
||||
struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *wrqu,
|
||||
char *extra
|
||||
)
|
||||
{
|
||||
int res = -1;
|
||||
char *str_ptr;
|
||||
int tlv_size_left;
|
||||
|
||||
|
||||
#define SOFTAP_TLV_DEBUG 1
|
||||
#ifdef SOFTAP_TLV_DEBUG
|
||||
char softap_cmd_example[] = {
|
||||
|
||||
'S', 'O', 'F', 'T', 'A', 'P', 'S', 'E', 'T', ' ',
|
||||
|
||||
SOFTAP_TLV_PREFIX, SOFTAP_TLV_VERSION,
|
||||
SOFTAP_TLV_SUBVERSION, SOFTAP_TLV_RESERVED,
|
||||
|
||||
TLV_TYPE_SSID, 9, 'B', 'R', 'C', 'M', ',', 'G', 'O', 'O', 'G',
|
||||
|
||||
TLV_TYPE_SECUR, 4, 'O', 'P', 'E', 'N',
|
||||
|
||||
TLV_TYPE_KEY, 4, 0x31, 0x32, 0x33, 0x34,
|
||||
|
||||
TLV_TYPE_CHANNEL, 4, 0x06, 0x00, 0x00, 0x00
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SOFTAP_TLV_DEBUG
|
||||
{
|
||||
int i;
|
||||
if (!(extra = kmalloc(sizeof(softap_cmd_example) +10, GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
memcpy(extra, softap_cmd_example, sizeof(softap_cmd_example));
|
||||
wrqu->data.length = sizeof(softap_cmd_example);
|
||||
print_buf(extra, wrqu->data.length, 16);
|
||||
for (i = 0; i < wrqu->data.length; i++)
|
||||
printf("%c ", extra[i]);
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
WL_ERROR(("\n### %s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n",
|
||||
__FUNCTION__, info->cmd, info->flags,
|
||||
wrqu->data.pointer, wrqu->data.length));
|
||||
|
||||
if (g_onoff == G_WLAN_SET_OFF) {
|
||||
WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wrqu->data.length < (strlen(SOFTAP_SET_CMD) + sizeof(cmd_tlv_t))) {
|
||||
WL_ERROR(("%s argument=%d less %d\n", __FUNCTION__,
|
||||
wrqu->data.length, strlen(SOFTAP_SET_CMD) + sizeof(cmd_tlv_t)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
str_ptr = extra + strlen(SOFTAP_SET_CMD)+1;
|
||||
tlv_size_left = wrqu->data.length - (strlen(SOFTAP_SET_CMD)+1);
|
||||
|
||||
memset(&my_ap, 0, sizeof(my_ap));
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SOFTAP
|
||||
int init_ap_profile_from_string(char *param_str, struct ap_profile *ap_cfg)
|
||||
{
|
||||
|
|
@ -3800,7 +3713,6 @@ wl_iw_handle_scanresults_ies(char **event_p, char *end,
|
|||
wpa_snprintf_hex(buf + 10, 2+1, &(ie->len), 1);
|
||||
wpa_snprintf_hex(buf + 12, 2*ie->len+1, ie->data, ie->len);
|
||||
event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, buf);
|
||||
kfree(buf);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
|
@ -5842,7 +5754,7 @@ wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nss
|
|||
WL_SCAN(("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type));
|
||||
WL_SCAN(("\n###################\n"));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (params_size > WLC_IOCTL_MEDLEN) {
|
||||
WL_ERROR(("Set ISCAN for %s due to params_size=%d \n", \
|
||||
|
|
@ -5882,11 +5794,6 @@ static int iwpriv_set_cscan(struct net_device *dev, struct iw_request_info *info
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef PNO_SET_DEBUG
|
||||
wl_iw_set_pno_set(dev, info, wrqu, extra);
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if (wrqu->data.length != 0) {
|
||||
|
||||
char *str_ptr;
|
||||
|
|
@ -6414,8 +6321,16 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap)
|
|||
}
|
||||
|
||||
if (strlen(ap->country_code)) {
|
||||
WL_ERROR(("%s: Igonored: Country MUST be specified \
|
||||
COUNTRY command with \n", __FUNCTION__));
|
||||
int error = 0;
|
||||
if ((error = dev_wlc_ioctl(dev, WLC_SET_COUNTRY,
|
||||
ap->country_code, sizeof(ap->country_code))) >= 0) {
|
||||
WL_SOFTAP(("%s: set country %s OK\n",
|
||||
__FUNCTION__, ap->country_code));
|
||||
dhd_bus_country_set(dev, &ap->country_code[0]);
|
||||
} else {
|
||||
WL_ERROR(("%s: ERROR:%d setting country %s\n",
|
||||
__FUNCTION__, error, ap->country_code));
|
||||
}
|
||||
} else {
|
||||
WL_SOFTAP(("%s: Country code is not specified,"
|
||||
" will use Radio's default\n",
|
||||
|
|
@ -7157,6 +7072,30 @@ int wl_iw_process_private_ascii_cmd(
|
|||
}
|
||||
#endif
|
||||
|
||||
#define BCM4329_WAKELOCK_NAME "bcm4329_wifi_wakelock"
|
||||
|
||||
static struct wake_lock bcm4329_suspend_lock;
|
||||
|
||||
int bcm4329_wakelock_init = 0;
|
||||
|
||||
void bcm4329_power_save_init(void)
|
||||
{
|
||||
wake_lock_init(&bcm4329_suspend_lock, WAKE_LOCK_SUSPEND, BCM4329_WAKELOCK_NAME);
|
||||
wake_lock(&bcm4329_suspend_lock);
|
||||
|
||||
bcm4329_wakelock_init = 2;
|
||||
}
|
||||
|
||||
void bcm4329_power_save_exit(void)
|
||||
{
|
||||
bcm4329_wakelock_init = 0;
|
||||
msleep(100);
|
||||
|
||||
if (bcm4329_wakelock_init == 2)
|
||||
wake_unlock(&bcm4329_suspend_lock);
|
||||
wake_lock_destroy(&bcm4329_suspend_lock);
|
||||
}
|
||||
|
||||
static int wl_iw_set_priv(
|
||||
struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
|
|
@ -7182,6 +7121,11 @@ static int wl_iw_set_priv(
|
|||
|
||||
if (dwrq->length && extra) {
|
||||
if (strnicmp(extra, "START", strlen("START")) == 0) {
|
||||
if (bcm4329_wakelock_init == 1)
|
||||
{
|
||||
wake_lock(&bcm4329_suspend_lock);
|
||||
bcm4329_wakelock_init = 2;
|
||||
}
|
||||
wl_iw_control_wl_on(dev, info);
|
||||
WL_TRACE(("%s, Received regular START command\n", __FUNCTION__));
|
||||
}
|
||||
|
|
@ -7213,8 +7157,16 @@ static int wl_iw_set_priv(
|
|||
ret = wl_iw_get_macaddr(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
else if (strnicmp(extra, "COUNTRY", strlen("COUNTRY")) == 0)
|
||||
ret = wl_iw_set_country(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
else if (strnicmp(extra, "STOP", strlen("STOP")) == 0)
|
||||
else if (strnicmp(extra, "SCAN-CHANNELS", strlen("SCAN-CHANNELS")) == 0)
|
||||
ret = wl_iw_get_country(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
else if (strnicmp(extra, "STOP", strlen("STOP")) == 0){
|
||||
ret = wl_iw_control_wl_off(dev, info);
|
||||
if (bcm4329_wakelock_init == 2)
|
||||
{
|
||||
wake_unlock(&bcm4329_suspend_lock);
|
||||
bcm4329_wakelock_init = 1;
|
||||
}
|
||||
}
|
||||
else if (strnicmp(extra, BAND_GET_CMD, strlen(BAND_GET_CMD)) == 0)
|
||||
ret = wl_iw_get_band(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
else if (strnicmp(extra, BAND_SET_CMD, strlen(BAND_SET_CMD)) == 0)
|
||||
|
|
@ -7225,8 +7177,10 @@ static int wl_iw_set_priv(
|
|||
ret = wl_iw_set_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
else if (strnicmp(extra, SETSUSPEND_CMD, strlen(SETSUSPEND_CMD)) == 0)
|
||||
ret = wl_iw_set_suspend(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
else if (strnicmp(extra, TXPOWER_SET_CMD, strlen(TXPOWER_SET_CMD)) == 0)
|
||||
ret = wl_iw_set_txpower(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
#ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY
|
||||
else if (strnicmp(extra, SETDFSCHANNELS_CMD, strlen(SETDFSCHANNELS_CMD)) == 0)
|
||||
ret = wl_iw_set_dfs_channels(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
#endif
|
||||
#if defined(PNO_SUPPORT)
|
||||
else if (strnicmp(extra, PNOSSIDCLR_SET_CMD, strlen(PNOSSIDCLR_SET_CMD)) == 0)
|
||||
ret = wl_iw_set_pno_reset(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
|
|
@ -7236,40 +7190,21 @@ static int wl_iw_set_priv(
|
|||
ret = wl_iw_set_pno_enable(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
#endif
|
||||
#if defined(CSCAN)
|
||||
else if (strnicmp(extra, CSCAN_COMMAND, strlen(CSCAN_COMMAND)) == 0)
|
||||
else if (strnicmp(extra, CSCAN_COMMAND, strlen(CSCAN_COMMAND)) == 0)
|
||||
ret = wl_iw_set_cscan(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CUSTOMER_HW2
|
||||
else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0)
|
||||
ret = wl_iw_set_power_mode(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
else if (strnicmp(extra, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0) {
|
||||
WL_TRACE_COEX(("%s:got Framwrork cmd: 'BTCOEXMODE'\n", __FUNCTION__));
|
||||
else if (strnicmp(extra, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0)
|
||||
ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
}
|
||||
#else
|
||||
else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0)
|
||||
ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
#endif
|
||||
else if (strnicmp(extra, "GETPOWER", strlen("GETPOWER")) == 0)
|
||||
ret = wl_iw_get_power_mode(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
else if (strnicmp(extra, RXFILTER_START_CMD, strlen(RXFILTER_START_CMD)) == 0)
|
||||
ret = net_os_set_packet_filter(dev, 1);
|
||||
else if (strnicmp(extra, RXFILTER_STOP_CMD, strlen(RXFILTER_STOP_CMD)) == 0)
|
||||
ret = net_os_set_packet_filter(dev, 0);
|
||||
else if (strnicmp(extra, RXFILTER_ADD_CMD, strlen(RXFILTER_ADD_CMD)) == 0) {
|
||||
int filter_num = *(extra + strlen(RXFILTER_ADD_CMD) + 1) - '0';
|
||||
ret = net_os_rxfilter_add_remove(dev, TRUE, filter_num);
|
||||
}
|
||||
else if (strnicmp(extra, RXFILTER_REMOVE_CMD, strlen(RXFILTER_REMOVE_CMD)) == 0) {
|
||||
int filter_num = *(extra + strlen(RXFILTER_REMOVE_CMD) + 1) - '0';
|
||||
ret = net_os_rxfilter_add_remove(dev, FALSE, filter_num);
|
||||
}
|
||||
#ifdef SOFTAP
|
||||
#ifdef SOFTAP_TLV_CFG
|
||||
else if (strnicmp(extra, SOFTAP_SET_CMD, strlen(SOFTAP_SET_CMD)) == 0) {
|
||||
wl_iw_softap_cfg_tlv(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
}
|
||||
#endif
|
||||
else if (strnicmp(extra, "ASCII_CMD", strlen("ASCII_CMD")) == 0) {
|
||||
wl_iw_process_private_ascii_cmd(dev, info, (union iwreq_data *)dwrq, extra);
|
||||
} else if (strnicmp(extra, "AP_MAC_LIST_SET", strlen("AP_MAC_LIST_SET")) == 0) {
|
||||
|
|
@ -7790,10 +7725,9 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
|
|||
uint32 datalen = ntoh32(e->datalen);
|
||||
uint32 status = ntoh32(e->status);
|
||||
uint32 toto;
|
||||
#if defined(ROAM_NOT_USED)
|
||||
static uint32 roam_no_success = 0;
|
||||
static bool roam_no_success_send = FALSE;
|
||||
#endif
|
||||
|
||||
memset(&wrqu, 0, sizeof(wrqu));
|
||||
memset(extra, 0, sizeof(extra));
|
||||
|
||||
|
|
@ -7864,14 +7798,10 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
|
|||
break;
|
||||
case WLC_E_ROAM:
|
||||
if (status == WLC_E_STATUS_SUCCESS) {
|
||||
WL_ASSOC(("%s: WLC_E_ROAM: success\n", __FUNCTION__));
|
||||
#if defined(ROAM_NOT_USED)
|
||||
roam_no_success_send = FALSE;
|
||||
roam_no_success = 0;
|
||||
#endif
|
||||
goto wl_iw_event_end;
|
||||
memcpy(wrqu.addr.sa_data, &e->addr.octet, ETHER_ADDR_LEN);
|
||||
wrqu.addr.sa_family = ARPHRD_ETHER;
|
||||
cmd = SIOCGIWAP;
|
||||
}
|
||||
#if defined(ROAM_NOT_USED)
|
||||
else if (status == WLC_E_STATUS_NO_NETWORKS) {
|
||||
roam_no_success++;
|
||||
if ((roam_no_success == 5) && (roam_no_success_send == FALSE)) {
|
||||
|
|
@ -7886,7 +7816,6 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
|
|||
goto wl_iw_event_end;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case WLC_E_DEAUTH_IND:
|
||||
case WLC_E_DISASSOC_IND:
|
||||
|
|
@ -7942,10 +7871,8 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
|
|||
wl_iw_send_priv_event(priv_dev, "AP_UP");
|
||||
} else {
|
||||
WL_TRACE(("STA_LINK_UP\n"));
|
||||
#if defined(ROAM_NOT_USED)
|
||||
roam_no_success_send = FALSE;
|
||||
roam_no_success = 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
WL_TRACE(("Link UP\n"));
|
||||
|
|
@ -8073,6 +8000,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
|
|||
#endif
|
||||
|
||||
#if WIRELESS_EXT > 14
|
||||
|
||||
memset(extra, 0, sizeof(extra));
|
||||
if (wl_iw_check_conn_fail(e, extra, sizeof(extra))) {
|
||||
cmd = IWEVCUSTOM;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
* software in any way with any other Broadcom software provided under a license
|
||||
* other than the GPL, without Broadcom's express prior written consent.
|
||||
*
|
||||
* $Id: wl_iw.h,v 1.5.34.1.6.36.4.18 2011/02/10 19:33:12 Exp $
|
||||
* $Id: wl_iw.h,v 1.5.34.1.6.36.4.15 2010/11/17 03:13:51 Exp $
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -52,11 +52,7 @@
|
|||
#define PNOSETUP_SET_CMD "PNOSETUP "
|
||||
#define PNOENABLE_SET_CMD "PNOFORCE"
|
||||
#define PNODEBUG_SET_CMD "PNODEBUG"
|
||||
#define TXPOWER_SET_CMD "TXPOWER"
|
||||
#define RXFILTER_START_CMD "RXFILTER-START"
|
||||
#define RXFILTER_STOP_CMD "RXFILTER-STOP"
|
||||
#define RXFILTER_ADD_CMD "RXFILTER-ADD"
|
||||
#define RXFILTER_REMOVE_CMD "RXFILTER-REMOVE"
|
||||
#define SETDFSCHANNELS_CMD "SETDFSCHANNELS"
|
||||
|
||||
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
|
||||
#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
|
||||
|
|
@ -66,12 +62,6 @@ typedef struct wl_iw_extra_params {
|
|||
int target_channel;
|
||||
} wl_iw_extra_params_t;
|
||||
|
||||
struct cntry_locales_custom {
|
||||
char iso_abbrev[WLC_CNTRY_BUF_SZ];
|
||||
char custom_locale[WLC_CNTRY_BUF_SZ];
|
||||
int32 custom_locale_rev;
|
||||
};
|
||||
|
||||
#define WL_IW_RSSI_MINVAL -200
|
||||
#define WL_IW_RSSI_NO_SIGNAL -91
|
||||
#define WL_IW_RSSI_VERY_LOW -80
|
||||
|
|
@ -143,13 +133,13 @@ typedef struct wl_iw_ss_cache {
|
|||
} wl_iw_ss_cache_t;
|
||||
|
||||
typedef struct wl_iw_ss_cache_ctrl {
|
||||
wl_iw_ss_cache_t *m_cache_head;
|
||||
int m_link_down;
|
||||
int m_timer_expired;
|
||||
char m_active_bssid[ETHER_ADDR_LEN];
|
||||
uint m_prev_scan_mode;
|
||||
uint m_cons_br_scan_cnt;
|
||||
struct timer_list *m_timer;
|
||||
wl_iw_ss_cache_t *m_cache_head;
|
||||
int m_link_down;
|
||||
int m_timer_expired;
|
||||
char m_active_bssid[ETHER_ADDR_LEN];
|
||||
uint m_prev_scan_mode;
|
||||
uint m_cons_br_scan_cnt;
|
||||
struct timer_list *m_timer;
|
||||
} wl_iw_ss_cache_ctrl_t;
|
||||
|
||||
typedef enum broadcast_first_scan {
|
||||
|
|
@ -175,7 +165,7 @@ struct ap_profile {
|
|||
};
|
||||
|
||||
|
||||
#define MACLIST_MODE_DISABLED 0
|
||||
#define MACLIST_MODE_DISABLED 0
|
||||
#define MACLIST_MODE_DENY 1
|
||||
#define MACLIST_MODE_ALLOW 2
|
||||
struct mflist {
|
||||
|
|
@ -208,7 +198,8 @@ extern int net_os_wake_lock_timeout_enable(struct net_device *dev);
|
|||
extern int net_os_set_suspend_disable(struct net_device *dev, int val);
|
||||
extern int net_os_set_suspend(struct net_device *dev, int val);
|
||||
extern int net_os_set_dtim_skip(struct net_device *dev, int val);
|
||||
extern void get_customized_country_code(char *country_iso_code, wl_country_t *cspec);
|
||||
extern int net_os_set_packet_filter(struct net_device *dev, int val);
|
||||
extern void dhd_bus_country_set(struct net_device *dev, char *country_code);
|
||||
extern char *dhd_bus_country_get(struct net_device *dev);
|
||||
extern int dhd_get_dtim_skip(dhd_pub_t *dhd);
|
||||
|
||||
|
|
@ -230,15 +221,13 @@ extern int dhd_get_dtim_skip(dhd_pub_t *dhd);
|
|||
|
||||
extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled);
|
||||
extern int dhd_pno_clean(dhd_pub_t *dhd);
|
||||
extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, \
|
||||
ushort scan_fr, int pno_repeat, int pno_freq_expo_max);
|
||||
extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr);
|
||||
extern int dhd_pno_get_status(dhd_pub_t *dhd);
|
||||
extern int dhd_dev_pno_reset(struct net_device *dev);
|
||||
extern int dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, \
|
||||
int nssid, ushort scan_fr, int pno_repeat, int pno_freq_expo_max);
|
||||
int nssid, ushort scan_fr);
|
||||
extern int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled);
|
||||
extern int dhd_dev_get_pno_status(struct net_device *dev);
|
||||
extern void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec);
|
||||
|
||||
#define PNO_TLV_PREFIX 'S'
|
||||
#define PNO_TLV_VERSION '1'
|
||||
|
|
@ -246,9 +235,8 @@ extern void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec);
|
|||
#define PNO_TLV_RESERVED '0'
|
||||
#define PNO_TLV_TYPE_SSID_IE 'S'
|
||||
#define PNO_TLV_TYPE_TIME 'T'
|
||||
#define PNO_TLV_FREQ_REPEAT 'R'
|
||||
#define PNO_TLV_FREQ_EXPO_MAX 'M'
|
||||
#define PNO_EVENT_UP "PNO_EVENT"
|
||||
#define PNO_EVENT_UP "PNO_EVENT"
|
||||
#define PNO_SCAN_MAX_FW 508
|
||||
|
||||
typedef struct cmd_tlv {
|
||||
char prefix;
|
||||
|
|
@ -257,19 +245,6 @@ typedef struct cmd_tlv {
|
|||
char reserved;
|
||||
} cmd_tlv_t;
|
||||
|
||||
#ifdef SOFTAP_TLV_CFG
|
||||
#define SOFTAP_SET_CMD "SOFTAPSET "
|
||||
#define SOFTAP_TLV_PREFIX 'A'
|
||||
#define SOFTAP_TLV_VERSION '1'
|
||||
#define SOFTAP_TLV_SUBVERSION '0'
|
||||
#define SOFTAP_TLV_RESERVED '0'
|
||||
|
||||
#define TLV_TYPE_SSID 'S'
|
||||
#define TLV_TYPE_SECUR 'E'
|
||||
#define TLV_TYPE_KEY 'K'
|
||||
#define TLV_TYPE_CHANNEL 'C'
|
||||
#endif
|
||||
|
||||
#if defined(CSCAN)
|
||||
|
||||
typedef struct cscan_tlv {
|
||||
|
|
@ -304,6 +279,6 @@ extern int wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int
|
|||
|
||||
extern int wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -18,14 +18,110 @@
|
|||
#include <linux/mfd/wm831x/auxadc.h>
|
||||
#include <linux/mfd/wm831x/pmu.h>
|
||||
#include <linux/mfd/wm831x/pdata.h>
|
||||
#include <linux/mfd/wm831x/irq.h>
|
||||
|
||||
#define WM831X_DEBUG
|
||||
#undef WM831X_DEBUG
|
||||
|
||||
#ifdef WM831X_DEBUG
|
||||
#define WM_BATT_DBG(x...) printk(KERN_INFO x)
|
||||
#else
|
||||
#define WM_BATT_DBG(x...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#define WM831X_CHG_SYSLO_SHIFT 4
|
||||
#define WM831X_CHG_SYSOK_SHIFT 0
|
||||
#define WM831X_CHG_SYSLO_MASK ~(0x7 << 4)
|
||||
#define WM831X_CHG_SYSOK_MASK ~(0x7 << 0)
|
||||
|
||||
#define batt_num 52
|
||||
|
||||
static int batt_step_table[batt_num] = {
|
||||
3400,3420,3440,3475,3505,3525,
|
||||
3540,3557,3570,3580,3610,
|
||||
3630,3640,3652,3662,3672,
|
||||
3680,3687,3693,3699,3705,
|
||||
3710,3714,3718,3722,3726,
|
||||
3730,3734,3738,3742,3746,
|
||||
3750,3756,3764,3774,3786,
|
||||
3800,3808,3817,3827,3838,
|
||||
3950,3964,3982,4002,4026,
|
||||
4050,4074,4098,4123,4149,4178
|
||||
};
|
||||
|
||||
static int batt_disp_table[batt_num] = {
|
||||
0,1,2,3,5,7,
|
||||
9,11,13,15,17,
|
||||
19,21,23,25,27,
|
||||
29,31,33,35,37,
|
||||
39,41,43,45,47,
|
||||
49,51,53,55,57,
|
||||
59,61,63,65,67,
|
||||
69,71,73,75,77,
|
||||
79,81,83,85,87,
|
||||
89,91,93,95,97,100
|
||||
};
|
||||
|
||||
static int batt_chg_step_table[batt_num] = {
|
||||
3530,3565,3600,3635,3655,3680,//+160
|
||||
3700,3717,3734,3745,3755,//+150
|
||||
3770,3778,3786,3795,3803,//+140
|
||||
3810,3814,3818,3822,3825,//+130
|
||||
3830,3832,3834,3836,3837,//+120
|
||||
3840,3842,3844,3846,3847,//+110
|
||||
3850,3857,3864,3871,3876,//+100
|
||||
3890,3897,3904,3911,3918,//+90
|
||||
4030,4047,4064,4080,4096,//+80
|
||||
4120,4132,4144,4156,4170,4180//+70
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define TIMER_MS_COUNTS 1000
|
||||
struct wm_batt_priv_data {
|
||||
int online;
|
||||
int status;
|
||||
int health;
|
||||
int level;
|
||||
int temp;
|
||||
int voltage;
|
||||
};
|
||||
|
||||
struct wm831x_power {
|
||||
struct wm831x *wm831x;
|
||||
struct power_supply wall;
|
||||
struct power_supply usb;
|
||||
struct power_supply battery;
|
||||
struct work_struct batt_work;
|
||||
struct timer_list timer;
|
||||
struct wm_batt_priv_data batt_info;
|
||||
struct wake_lock syslo_wake;
|
||||
int interval;
|
||||
};
|
||||
|
||||
struct wm831x_power *g_wm831x_power;
|
||||
|
||||
static int power_test_sysfs_init(void);
|
||||
extern void wm831x_batt_vol_level(struct wm831x_power *power, int batt_vol, int *level);
|
||||
static DEFINE_MUTEX(charging_mutex);
|
||||
|
||||
int wm831x_read_on_pin_status(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if(!g_wm831x_power)
|
||||
{
|
||||
printk("err:%s:g_wm831x_power address is 0\n",__FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = wm831x_reg_read(g_wm831x_power->wm831x, WM831X_ON_PIN_CONTROL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return !(ret & WM831X_ON_PIN_STS) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
|
|
@ -43,19 +139,55 @@ static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int wm831x_read_chg_status(void)
|
||||
{
|
||||
int ret, usb_chg = 0, wall_chg = 0;
|
||||
|
||||
if(!g_wm831x_power)
|
||||
{
|
||||
printk("err:%s:g_wm831x_power address is 0\n",__FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = wm831x_reg_read(g_wm831x_power->wm831x, WM831X_SYSTEM_STATUS);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret & WM831X_PWR_USB)
|
||||
usb_chg = 1;
|
||||
if (ret & WM831X_PWR_WALL)
|
||||
wall_chg = 1;
|
||||
|
||||
return ((usb_chg | wall_chg) ? 1 : 0);
|
||||
}
|
||||
|
||||
static int wm831x_power_read_voltage(struct wm831x *wm831x,
|
||||
enum wm831x_auxadc src,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = wm831x_auxadc_read_uv(wm831x, src);
|
||||
if (ret >= 0)
|
||||
val->intval = ret;
|
||||
|
||||
return ret;
|
||||
val->intval = ret / 1000;
|
||||
|
||||
return ret ;
|
||||
}
|
||||
|
||||
int wm831x_read_batt_voltage(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if(!g_wm831x_power)
|
||||
{
|
||||
printk("err:%s:g_wm831x_power address is 0\n",__FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = wm831x_auxadc_read_uv(g_wm831x_power->wm831x, WM831X_AUX_BATT);
|
||||
return ret / 1000;
|
||||
}
|
||||
//EXPORT_SYMBOL_GPL(wm831x_get_batt_voltage);
|
||||
|
||||
/*********************************************************************
|
||||
* WALL Power
|
||||
*********************************************************************/
|
||||
|
|
@ -190,13 +322,34 @@ static struct chg_map chg_times[] = {
|
|||
{ 510, 15 << WM831X_CHG_TIME_SHIFT },
|
||||
};
|
||||
|
||||
static struct chg_map chg_syslos[] = {
|
||||
{ 2800, 0 << WM831X_CHG_SYSLO_SHIFT},
|
||||
{ 2900, 1 << WM831X_CHG_SYSLO_SHIFT},
|
||||
{ 3000, 2 << WM831X_CHG_SYSLO_SHIFT},
|
||||
{ 3100, 3 << WM831X_CHG_SYSLO_SHIFT},
|
||||
{ 3200, 4 << WM831X_CHG_SYSLO_SHIFT},
|
||||
{ 3300, 5 << WM831X_CHG_SYSLO_SHIFT},
|
||||
{ 3400, 6 << WM831X_CHG_SYSLO_SHIFT},
|
||||
{ 3500, 7 << WM831X_CHG_SYSLO_SHIFT},
|
||||
};
|
||||
|
||||
static struct chg_map chg_sysoks[] = {
|
||||
{ 2800, 0 << WM831X_CHG_SYSOK_SHIFT},
|
||||
{ 2900, 1 << WM831X_CHG_SYSOK_SHIFT},
|
||||
{ 3000, 2 << WM831X_CHG_SYSOK_SHIFT},
|
||||
{ 3100, 3 << WM831X_CHG_SYSOK_SHIFT},
|
||||
{ 3200, 4 << WM831X_CHG_SYSOK_SHIFT},
|
||||
{ 3300, 5 << WM831X_CHG_SYSOK_SHIFT},
|
||||
{ 3400, 6 << WM831X_CHG_SYSOK_SHIFT},
|
||||
{ 3500, 7 << WM831X_CHG_SYSOK_SHIFT},
|
||||
};
|
||||
|
||||
static void wm831x_battey_apply_config(struct wm831x *wm831x,
|
||||
struct chg_map *map, int count, int val,
|
||||
int *reg, const char *name,
|
||||
const char *units)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
if (val == map[i].val)
|
||||
break;
|
||||
|
|
@ -213,7 +366,7 @@ static void wm831x_config_battery(struct wm831x *wm831x)
|
|||
{
|
||||
struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data;
|
||||
struct wm831x_battery_pdata *pdata;
|
||||
int ret, reg1, reg2;
|
||||
int ret, reg1, reg2, reg3;
|
||||
|
||||
if (!wm831x_pdata || !wm831x_pdata->battery) {
|
||||
dev_warn(wm831x->dev,
|
||||
|
|
@ -225,6 +378,7 @@ static void wm831x_config_battery(struct wm831x *wm831x)
|
|||
|
||||
reg1 = 0;
|
||||
reg2 = 0;
|
||||
reg3 = 0;
|
||||
|
||||
if (!pdata->enable) {
|
||||
dev_info(wm831x->dev, "Battery charger disabled\n");
|
||||
|
|
@ -258,6 +412,14 @@ static void wm831x_config_battery(struct wm831x *wm831x)
|
|||
pdata->timeout, ®2,
|
||||
"charger timeout", "min");
|
||||
|
||||
wm831x_battey_apply_config(wm831x, chg_syslos, ARRAY_SIZE(chg_syslos),
|
||||
pdata->syslo, ®3,
|
||||
"syslo voltage", "mV");
|
||||
|
||||
wm831x_battey_apply_config(wm831x, chg_sysoks, ARRAY_SIZE(chg_sysoks),
|
||||
pdata->sysok, ®3,
|
||||
"sysok voltage", "mV");
|
||||
|
||||
ret = wm831x_reg_unlock(wm831x);
|
||||
if (ret != 0) {
|
||||
dev_err(wm831x->dev, "Failed to unlock registers: %d\n", ret);
|
||||
|
|
@ -269,10 +431,10 @@ static void wm831x_config_battery(struct wm831x *wm831x)
|
|||
WM831X_CHG_FAST_MASK |
|
||||
WM831X_CHG_ITERM_MASK,
|
||||
reg1);
|
||||
if (ret != 0)
|
||||
if (ret != 0) {
|
||||
dev_err(wm831x->dev, "Failed to set charger control 1: %d\n",
|
||||
ret);
|
||||
|
||||
}
|
||||
ret = wm831x_set_bits(wm831x, WM831X_CHARGER_CONTROL_2,
|
||||
WM831X_CHG_OFF_MSK |
|
||||
WM831X_CHG_TIME_MASK |
|
||||
|
|
@ -280,9 +442,18 @@ static void wm831x_config_battery(struct wm831x *wm831x)
|
|||
WM831X_CHG_TRKL_ILIM_MASK |
|
||||
WM831X_CHG_VSEL_MASK,
|
||||
reg2);
|
||||
if (ret != 0)
|
||||
if (ret != 0) {
|
||||
dev_err(wm831x->dev, "Failed to set charger control 2: %d\n",
|
||||
ret);
|
||||
}
|
||||
|
||||
ret = wm831x_set_bits(wm831x, WM831X_SYSVDD_CONTROL,
|
||||
WM831X_CHG_SYSLO_MASK |
|
||||
WM831X_CHG_SYSOK_MASK,
|
||||
reg3);
|
||||
if (ret < 0) {
|
||||
dev_err(wm831x->dev, "Failed to set sysvdd control reg: %d\n",ret);
|
||||
}
|
||||
|
||||
wm831x_reg_lock(wm831x);
|
||||
}
|
||||
|
|
@ -320,10 +491,53 @@ static int wm831x_bat_check_status(struct wm831x *wm831x, int *status)
|
|||
|
||||
return 0;
|
||||
}
|
||||
int wm831x_read_bat_charging_status(void)
|
||||
{
|
||||
int ret, status;
|
||||
|
||||
if(!g_wm831x_power)
|
||||
{
|
||||
printk("err:%s:g_wm831x_power address is 0\n",__FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = wm831x_bat_check_status(g_wm831x_power->wm831x, &status);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (status == POWER_SUPPLY_STATUS_CHARGING)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm831x_bat_check_type(struct wm831x *wm831x, int *type)
|
||||
{
|
||||
int ret;
|
||||
#ifdef WM831X_DEBUG_0
|
||||
ret = wm831x_reg_read(wm831x, WM831X_POWER_STATE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
WM_BATT_DBG("%s: wm831x power status %#x\n", __FUNCTION__, ret);
|
||||
|
||||
ret = wm831x_reg_read(wm831x, WM831X_SYSTEM_STATUS);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
WM_BATT_DBG("%s: wm831x system status %#x\n", __FUNCTION__, ret);
|
||||
|
||||
ret = wm831x_reg_read(wm831x, WM831X_CHARGER_CONTROL_1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
WM_BATT_DBG("%s: wm831x charger control1 %#x\n", __FUNCTION__, ret);
|
||||
|
||||
ret = wm831x_reg_read(wm831x, WM831X_CHARGER_CONTROL_2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
WM_BATT_DBG("%s: wm831x charger control2 %#x\n", __FUNCTION__, ret);
|
||||
|
||||
ret = wm831x_reg_read(wm831x, WM831X_CHARGER_STATUS);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
WM_BATT_DBG("%s: wm831x charger status %#x\n\n", __FUNCTION__, ret);
|
||||
#endif
|
||||
|
||||
ret = wm831x_reg_read(wm831x, WM831X_CHARGER_STATUS);
|
||||
if (ret < 0)
|
||||
|
|
@ -396,20 +610,36 @@ static int wm831x_bat_get_prop(struct power_supply *psy,
|
|||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
ret = wm831x_bat_check_status(wm831x, &val->intval);
|
||||
//val->intval = wm831x_power->batt_info.status;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
ret = wm831x_power_check_online(wm831x, WM831X_PWR_SRC_BATT,
|
||||
val);
|
||||
//ret = wm831x_power_check_online(wm831x, WM831X_PWR_SRC_BATT, val);
|
||||
val->intval = wm831x_power->batt_info.online;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
ret = wm831x_power_read_voltage(wm831x, WM831X_AUX_BATT, val);
|
||||
//ret = wm831x_power_read_voltage(wm831x, WM831X_AUX_BATT, val);
|
||||
val->intval = wm831x_power->batt_info.voltage*1000;//uV
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_HEALTH:
|
||||
ret = wm831x_bat_check_health(wm831x, &val->intval);
|
||||
//ret = wm831x_bat_check_health(wm831x, &val->intval);
|
||||
val->intval = wm831x_power->batt_info.health;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CHARGE_TYPE:
|
||||
ret = wm831x_bat_check_type(wm831x, &val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CAPACITY:
|
||||
//ret = wm831x_power_read_voltage(wm831x, WM831X_AUX_BATT, val);
|
||||
//wm831x_batt_vol_level(wm831x_power, val->intval, &level);
|
||||
//val->intval = level;
|
||||
val->intval = wm831x_power->batt_info.level;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TEMP:
|
||||
val->intval = 0;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TECHNOLOGY:
|
||||
val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
|
|
@ -420,12 +650,16 @@ static int wm831x_bat_get_prop(struct power_supply *psy,
|
|||
|
||||
static enum power_supply_property wm831x_bat_props[] = {
|
||||
POWER_SUPPLY_PROP_STATUS,
|
||||
POWER_SUPPLY_PROP_ONLINE,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||
POWER_SUPPLY_PROP_HEALTH,
|
||||
POWER_SUPPLY_PROP_PRESENT,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||
POWER_SUPPLY_PROP_CAPACITY, /* in percents! */
|
||||
POWER_SUPPLY_PROP_TECHNOLOGY,
|
||||
POWER_SUPPLY_PROP_TEMP,
|
||||
POWER_SUPPLY_PROP_CHARGE_TYPE,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_WM831X_WITH_BATTERY
|
||||
static const char *wm831x_bat_irqs[] = {
|
||||
"BATT HOT",
|
||||
"BATT COLD",
|
||||
|
|
@ -441,16 +675,18 @@ static irqreturn_t wm831x_bat_irq(int irq, void *data)
|
|||
{
|
||||
struct wm831x_power *wm831x_power = data;
|
||||
struct wm831x *wm831x = wm831x_power->wm831x;
|
||||
|
||||
dev_dbg(wm831x->dev, "Battery status changed: %d\n", irq);
|
||||
|
||||
int irq0;
|
||||
|
||||
irq0 = wm831x->irq_base + WM831X_IRQ_CHG_BATT_HOT + 1;
|
||||
dev_crit(wm831x->dev, "battery changed: i=%d\n", irq-irq0);
|
||||
|
||||
/* The battery charger is autonomous so we don't need to do
|
||||
* anything except kick user space */
|
||||
power_supply_changed(&wm831x_power->battery);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
* Initialisation
|
||||
|
|
@ -463,8 +699,8 @@ static irqreturn_t wm831x_syslo_irq(int irq, void *data)
|
|||
|
||||
/* Not much we can actually *do* but tell people for
|
||||
* posterity, we're probably about to run out of power. */
|
||||
dev_crit(wm831x->dev, "SYSVDD under voltage\n");
|
||||
|
||||
dev_crit(wm831x->dev, "SYSVDD under voltage and wake lock 60s\n");
|
||||
wake_lock_timeout(&wm831x_power->syslo_wake,60*HZ);//wait for android closing system
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
|
@ -474,7 +710,7 @@ static irqreturn_t wm831x_pwr_src_irq(int irq, void *data)
|
|||
struct wm831x *wm831x = wm831x_power->wm831x;
|
||||
|
||||
dev_dbg(wm831x->dev, "Power source changed\n");
|
||||
|
||||
WM_BATT_DBG("%s:Power source changed\n", __FUNCTION__);
|
||||
/* Just notify for everything - little harm in overnotifying. */
|
||||
power_supply_changed(&wm831x_power->battery);
|
||||
power_supply_changed(&wm831x_power->usb);
|
||||
|
|
@ -483,6 +719,289 @@ static irqreturn_t wm831x_pwr_src_irq(int irq, void *data)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void wm831x_batt_timer_handler(unsigned long data)
|
||||
{
|
||||
struct wm831x_power *wm831x_power = (struct wm831x_power*)data;
|
||||
schedule_work(&wm831x_power->batt_work);
|
||||
mod_timer(&wm831x_power->timer, jiffies + msecs_to_jiffies(wm831x_power->interval));
|
||||
}
|
||||
|
||||
void wm831x_batt_vol_level(struct wm831x_power *wm831x_power, int batt_vol, int *level)
|
||||
{
|
||||
int i, ret, status;
|
||||
static int chg_plus = 1000;
|
||||
static int chg_minus = 1000;
|
||||
static int chg_curr = 0;
|
||||
static int chg_num = 60;
|
||||
static int disp_plus = 1000;
|
||||
static int disp_minus = 1000;
|
||||
static int disp_curr = 0;
|
||||
static int disp_num = 50;
|
||||
|
||||
|
||||
*level = wm831x_power->batt_info.level;
|
||||
ret = wm831x_bat_check_status(wm831x_power->wm831x, &status);
|
||||
if (ret < 0) {
|
||||
printk("%s: check bat status failer...err = %d\n", __FUNCTION__, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == POWER_SUPPLY_STATUS_NOT_CHARGING
|
||||
&& batt_vol >= batt_step_table[batt_num-1]) {
|
||||
*level = 100;
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == POWER_SUPPLY_STATUS_CHARGING)
|
||||
{
|
||||
disp_plus = 0;
|
||||
disp_minus = 0;
|
||||
disp_curr = 0;
|
||||
|
||||
for(i = 0; i < batt_num; i++){
|
||||
if((batt_chg_step_table[i] <= batt_vol) &&
|
||||
(batt_chg_step_table[i+1] > batt_vol))
|
||||
break;
|
||||
}
|
||||
*level = batt_disp_table[i];
|
||||
|
||||
if (batt_vol <= batt_chg_step_table[0])
|
||||
*level = 0;
|
||||
if (batt_vol >= batt_chg_step_table[batt_num - 1])
|
||||
*level = 100;
|
||||
|
||||
// ³õʼ״̬
|
||||
if ((chg_plus == 1000) && (chg_minus == 1000))
|
||||
{
|
||||
*level = *level;
|
||||
chg_plus = 0;
|
||||
chg_minus = 0;
|
||||
chg_curr = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (*level >= (wm831x_power->batt_info.level+1))
|
||||
{
|
||||
chg_minus = 0;
|
||||
chg_curr = 0;
|
||||
|
||||
if (++chg_plus > chg_num)
|
||||
{
|
||||
*level = wm831x_power->batt_info.level + 1;
|
||||
chg_plus = 0;
|
||||
|
||||
if(*level < 85)
|
||||
chg_num = 60;
|
||||
else
|
||||
chg_num = 20;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
*level = wm831x_power->batt_info.level;
|
||||
}
|
||||
}
|
||||
|
||||
else if (*level >= wm831x_power->batt_info.level)
|
||||
{
|
||||
chg_plus = 0;
|
||||
chg_minus = 0;
|
||||
|
||||
if (++chg_curr > chg_num)
|
||||
{
|
||||
*level = *level;
|
||||
chg_curr = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*level = wm831x_power->batt_info.level;
|
||||
}
|
||||
}
|
||||
else if (*level < (wm831x_power->batt_info.level-1))
|
||||
{
|
||||
chg_plus = 0;
|
||||
chg_curr = 0;
|
||||
|
||||
if (++chg_minus > (chg_num<<1))
|
||||
{
|
||||
*level = wm831x_power->batt_info.level - 1;
|
||||
chg_minus = 0;
|
||||
|
||||
if(*level < 85)
|
||||
chg_num = 60;
|
||||
else
|
||||
chg_num = 20;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
*level = wm831x_power->batt_info.level;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chg_plus = 0;
|
||||
chg_minus = 0;
|
||||
chg_curr = 0;
|
||||
*level = wm831x_power->batt_info.level;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (*level >= 100)
|
||||
*level = 100;
|
||||
if (*level < 0)
|
||||
*level = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
chg_plus = 0;
|
||||
chg_minus = 0;
|
||||
chg_curr = 0;
|
||||
|
||||
for(i = 0; i < batt_num; i++){
|
||||
if(batt_vol >= batt_step_table[i] &&
|
||||
batt_vol < batt_step_table[i+1])
|
||||
break;
|
||||
}
|
||||
*level = batt_disp_table[i];
|
||||
|
||||
if (batt_vol <= batt_step_table[0])
|
||||
*level = 0;
|
||||
if (batt_vol >= batt_step_table[batt_num - 1])
|
||||
*level = 100;
|
||||
|
||||
// ³õʼ״̬
|
||||
if ((disp_plus == 1000) && (disp_minus == 1000))
|
||||
{
|
||||
*level = *level;
|
||||
disp_plus = 0;
|
||||
disp_minus = 0;
|
||||
disp_curr = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (*level <= (wm831x_power->batt_info.level-1))
|
||||
{
|
||||
disp_plus = 0;
|
||||
disp_curr = 0;
|
||||
|
||||
if (++disp_minus > disp_num)
|
||||
{
|
||||
*level = wm831x_power->batt_info.level - 1;
|
||||
disp_minus = 0;
|
||||
|
||||
if((*level < 17) || (*level > 85))
|
||||
disp_num = 10;
|
||||
else
|
||||
disp_num = 50;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
*level = wm831x_power->batt_info.level;
|
||||
}
|
||||
}
|
||||
else if (*level <= wm831x_power->batt_info.level)
|
||||
{
|
||||
disp_plus = 0;
|
||||
disp_minus = 0;
|
||||
|
||||
if (++disp_curr > disp_num)
|
||||
{
|
||||
*level = *level;
|
||||
disp_curr = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*level = wm831x_power->batt_info.level;
|
||||
}
|
||||
}
|
||||
else if (*level >= (wm831x_power->batt_info.level+1))
|
||||
{
|
||||
disp_minus = 0;
|
||||
disp_curr = 0;
|
||||
|
||||
if (++disp_plus > (disp_num<<1))
|
||||
{
|
||||
*level = wm831x_power->batt_info.level + 1;
|
||||
disp_plus = 0;
|
||||
if((*level < 17) || (*level > 85))
|
||||
disp_num = 10;
|
||||
else
|
||||
disp_num = 50;
|
||||
}
|
||||
else
|
||||
{
|
||||
*level = wm831x_power->batt_info.level;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
disp_plus = 0;
|
||||
disp_minus = 0;
|
||||
disp_curr = 0;
|
||||
*level = wm831x_power->batt_info.level;
|
||||
}
|
||||
}
|
||||
|
||||
if (*level >= 100)
|
||||
*level = 100;
|
||||
if (*level < 0)
|
||||
*level = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void wm831x_batt_work(struct work_struct *work)
|
||||
{
|
||||
int online, status,health,level, ret;
|
||||
union power_supply_propval val;
|
||||
struct wm831x_power *power = container_of(work, struct wm831x_power, batt_work);
|
||||
|
||||
ret = wm831x_power_check_online(power->wm831x, WM831X_PWR_SRC_BATT, &val);
|
||||
if (ret < 0) {
|
||||
printk("%s: check bat online failer... err = %d\n", __FUNCTION__, ret);
|
||||
return;
|
||||
}
|
||||
online = val.intval;
|
||||
|
||||
ret = wm831x_bat_check_status(power->wm831x, &status);
|
||||
if (ret < 0) {
|
||||
printk("%s: check bat status failer... err = %d\n", __FUNCTION__, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = wm831x_bat_check_health(power->wm831x, &health);
|
||||
if (ret < 0) {
|
||||
printk("%s: check bat health failer... err = %d\n", __FUNCTION__, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = wm831x_power_read_voltage(power->wm831x, WM831X_AUX_BATT, &val);
|
||||
if (ret < 0) {
|
||||
printk("%s: read bat voltage failer...err = %d\n", __FUNCTION__, ret);
|
||||
return;
|
||||
}
|
||||
power->batt_info.voltage = val.intval;
|
||||
|
||||
wm831x_batt_vol_level(power, val.intval, &level);
|
||||
//mod_timer(&power->timer, jiffies + msecs_to_jiffies(power->interval));
|
||||
|
||||
if (online != power->batt_info.online || status != power->batt_info.status
|
||||
|| health != power->batt_info.health || level != power->batt_info.level)
|
||||
{
|
||||
power->batt_info.online = online;
|
||||
power->batt_info.status = status;
|
||||
power->batt_info.health = health;
|
||||
power->batt_info.level = level;
|
||||
|
||||
power_supply_changed(&power->battery);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static __devinit int wm831x_power_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
|
||||
|
|
@ -555,12 +1074,14 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
|
|||
goto err_syslo;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WM831X_WITH_BATTERY
|
||||
for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
|
||||
irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]);
|
||||
ret = request_threaded_irq(irq, NULL, wm831x_bat_irq,
|
||||
IRQF_TRIGGER_RISING,
|
||||
wm831x_bat_irqs[i],
|
||||
power);
|
||||
WM_BATT_DBG("%s: %s irq no %d\n", __FUNCTION__, wm831x_bat_irqs[i], irq);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to request %s IRQ %d: %d\n",
|
||||
|
|
@ -568,9 +1089,27 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
|
|||
goto err_bat_irq;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
power->interval = TIMER_MS_COUNTS;
|
||||
power->batt_info.level = 100;
|
||||
power->batt_info.voltage = 4200;
|
||||
power->batt_info.online = 1;
|
||||
power->batt_info.status = POWER_SUPPLY_STATUS_DISCHARGING;
|
||||
power->batt_info.health = POWER_SUPPLY_HEALTH_GOOD;
|
||||
|
||||
wake_lock_init(&power->syslo_wake, WAKE_LOCK_SUSPEND, "wm831x_syslo_wake");
|
||||
INIT_WORK(&power->batt_work, wm831x_batt_work);
|
||||
setup_timer(&power->timer, wm831x_batt_timer_handler, (unsigned long)power);
|
||||
power->timer.expires = jiffies + msecs_to_jiffies(1000);
|
||||
add_timer(&power->timer);
|
||||
|
||||
g_wm831x_power = power;
|
||||
printk("%s:wm831x_power initialized\n",__FUNCTION__);
|
||||
power_test_sysfs_init();
|
||||
return ret;
|
||||
|
||||
|
||||
#ifdef CONFIG_WM831X_WITH_BATTERY
|
||||
err_bat_irq:
|
||||
for (; i >= 0; i--) {
|
||||
irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]);
|
||||
|
|
@ -578,6 +1117,8 @@ err_bat_irq:
|
|||
}
|
||||
irq = platform_get_irq_byname(pdev, "PWR SRC");
|
||||
free_irq(irq, power);
|
||||
#endif
|
||||
|
||||
err_syslo:
|
||||
irq = platform_get_irq_byname(pdev, "SYSLO");
|
||||
free_irq(irq, power);
|
||||
|
|
@ -596,12 +1137,12 @@ static __devexit int wm831x_power_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct wm831x_power *wm831x_power = platform_get_drvdata(pdev);
|
||||
int irq, i;
|
||||
|
||||
#ifdef CONFIG_WM831X_WITH_BATTERY
|
||||
for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
|
||||
irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]);
|
||||
free_irq(irq, wm831x_power);
|
||||
}
|
||||
|
||||
#endif
|
||||
irq = platform_get_irq_byname(pdev, "PWR SRC");
|
||||
free_irq(irq, wm831x_power);
|
||||
|
||||
|
|
@ -615,14 +1156,36 @@ static __devexit int wm831x_power_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wm831x_battery_suspend(struct platform_device *dev, pm_message_t state)
|
||||
{
|
||||
struct wm831x_power *power = (struct wm831x_power *)platform_get_drvdata(dev);
|
||||
flush_scheduled_work();
|
||||
del_timer(&power->timer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm831x_battery_resume(struct platform_device *dev)
|
||||
{
|
||||
struct wm831x_power *power = (struct wm831x_power *)platform_get_drvdata(dev);
|
||||
power->timer.expires = jiffies + msecs_to_jiffies(power->interval);
|
||||
add_timer(&power->timer);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define wm831x_battery_suspend NULL
|
||||
#define wm831x_battery_resume NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver wm831x_power_driver = {
|
||||
.probe = wm831x_power_probe,
|
||||
.remove = __devexit_p(wm831x_power_remove),
|
||||
.suspend = wm831x_battery_suspend,
|
||||
.resume = wm831x_battery_resume,
|
||||
.driver = {
|
||||
.name = "wm831x-power",
|
||||
},
|
||||
};
|
||||
|
||||
static int __init wm831x_power_init(void)
|
||||
{
|
||||
return platform_driver_register(&wm831x_power_driver);
|
||||
|
|
@ -635,6 +1198,96 @@ static void __exit wm831x_power_exit(void)
|
|||
}
|
||||
module_exit(wm831x_power_exit);
|
||||
|
||||
|
||||
static ssize_t power_prop_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t ret = 0;
|
||||
int level, power_status, system_status, chg_ctl1, chg_ctl2, chg_status;
|
||||
union power_supply_propval val;
|
||||
|
||||
if (!g_wm831x_power)
|
||||
return -1;
|
||||
power_status = wm831x_reg_read(g_wm831x_power->wm831x, WM831X_POWER_STATE);
|
||||
if (power_status < 0)
|
||||
return power_status;
|
||||
//printk("wm831x power status %#x\n", ret);
|
||||
|
||||
system_status = wm831x_reg_read(g_wm831x_power->wm831x, WM831X_SYSTEM_STATUS);
|
||||
if (system_status < 0)
|
||||
return system_status;
|
||||
//printk("wm831x system status %#x\n", ret);
|
||||
|
||||
chg_ctl1 = wm831x_reg_read(g_wm831x_power->wm831x, WM831X_CHARGER_CONTROL_1);
|
||||
if (chg_ctl1 < 0)
|
||||
return chg_ctl1;
|
||||
//printk("wm831x charger control1 %#x\n", ret);
|
||||
|
||||
chg_ctl2 = wm831x_reg_read(g_wm831x_power->wm831x, WM831X_CHARGER_CONTROL_2);
|
||||
if (chg_ctl2 < 0)
|
||||
return chg_ctl2;
|
||||
//printk("wm831x charger control2 %#x\n", ret);
|
||||
|
||||
chg_status = wm831x_reg_read(g_wm831x_power->wm831x, WM831X_CHARGER_STATUS);
|
||||
if (chg_status < 0)
|
||||
return chg_status;
|
||||
//printk("wm831x charger status %#x\n", ret);
|
||||
|
||||
ret = wm831x_power_read_voltage(g_wm831x_power->wm831x, WM831X_AUX_BATT, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
wm831x_batt_vol_level(g_wm831x_power, val.intval, &level);
|
||||
//printk("batt_vol = %d batt_level = %d\n", val.intval, level);
|
||||
//
|
||||
sprintf(buf, "power_status=%#x\n"
|
||||
"system_status=%#x\n"
|
||||
"chg_ctl1=%#x\n"
|
||||
"chg_ctl2=%#x\n"
|
||||
"chg_status=%#x\n"
|
||||
"batt_vol=%d\n"
|
||||
"batt_level=%d%%\n",
|
||||
power_status,
|
||||
system_status,
|
||||
chg_ctl1,
|
||||
chg_ctl2,
|
||||
chg_status,
|
||||
val.intval,
|
||||
level);
|
||||
ret = strlen(buf) + 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(prop, 0444, power_prop_show, NULL);
|
||||
|
||||
static struct kobject *power_test_kobj;
|
||||
|
||||
static int power_test_sysfs_init(void)
|
||||
{
|
||||
int ret ;
|
||||
power_test_kobj = kobject_create_and_add("power_test_prop", NULL);
|
||||
if (power_test_kobj == NULL) {
|
||||
printk(KERN_ERR
|
||||
"power_test_sysfs_init:"\
|
||||
"subsystem_register failed\n");
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
ret = sysfs_create_file(power_test_kobj, &dev_attr_prop.attr);
|
||||
if (ret) {
|
||||
printk(KERN_ERR
|
||||
"power_test_sysfs_init:"\
|
||||
"sysfs_create_group failed\n");
|
||||
goto err1;
|
||||
}
|
||||
|
||||
return 0 ;
|
||||
err1:
|
||||
kobject_del(power_test_kobj);
|
||||
err:
|
||||
return ret ;
|
||||
}
|
||||
|
||||
|
||||
MODULE_DESCRIPTION("Power supply driver for WM831x PMICs");
|
||||
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
|||
|
|
@ -132,13 +132,6 @@ config REGULATOR_TWL4030
|
|||
This driver supports the voltage regulators provided by
|
||||
this family of companion chips.
|
||||
|
||||
config REGULATOR_TPS65910
|
||||
bool "TI TPS69510x PMIC"
|
||||
depends on TPS65910_CORE
|
||||
help
|
||||
This driver supports the voltage regulators provided by
|
||||
this family of companion chips.
|
||||
|
||||
config REGULATOR_WM831X
|
||||
tristate "Wolfson Microelcronics WM831x PMIC regulators"
|
||||
depends on MFD_WM831X
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@ obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
|
|||
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
|
||||
obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
|
||||
obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
|
||||
obj-$(CONFIG_RK2818_REGULATOR_LP8725) += rk2818_lp8725.o
|
||||
obj-$(CONFIG_RK2818_REGULATOR_CHARGE) += charge-regulator.o
|
||||
obj-$(CONFIG_RK29_PWM_REGULATOR) += rk29-pwm-regulator.o
|
||||
|
||||
obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
|
||||
|
|
@ -43,5 +47,6 @@ obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
|
|||
obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
|
||||
obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
|
||||
obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_ACT8891) += act8891.o
|
||||
|
||||
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
|
||||
|
|
|
|||
|
|
@ -1785,6 +1785,24 @@ out:
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_set_voltage);
|
||||
|
||||
int regulator_set_suspend_voltage(struct regulator *regulator, int uV)
|
||||
{
|
||||
struct regulator_dev *rdev = regulator->rdev;
|
||||
int ret = 0;
|
||||
|
||||
if (rdev->desc->ops->set_suspend_voltage && uV > 0) {
|
||||
ret = rdev->desc->ops->set_suspend_voltage(rdev, uV);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "%s: failed to set voltage\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_set_suspend_voltage);
|
||||
|
||||
/**
|
||||
* regulator_set_voltage_time - get raise/fall time
|
||||
* @regulator: regulator source
|
||||
|
|
|
|||
|
|
@ -27,6 +27,11 @@
|
|||
#include <linux/mfd/wm831x/regulator.h>
|
||||
#include <linux/mfd/wm831x/pdata.h>
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#define WM831X_BUCKV_MAX_SELECTOR 0x68
|
||||
#define WM831X_BUCKP_MAX_SELECTOR 0x66
|
||||
|
||||
|
|
@ -35,7 +40,7 @@
|
|||
#define WM831X_DCDC_MODE_IDLE 2
|
||||
#define WM831X_DCDC_MODE_STANDBY 3
|
||||
|
||||
#define WM831X_DCDC_MAX_NAME 6
|
||||
//#define WM831X_DCDC_MAX_NAME 6
|
||||
|
||||
/* Register offsets in control block */
|
||||
#define WM831X_DCDC_CONTROL_1 0
|
||||
|
|
@ -47,7 +52,7 @@
|
|||
/*
|
||||
* Shared
|
||||
*/
|
||||
|
||||
#if 0
|
||||
struct wm831x_dcdc {
|
||||
char name[WM831X_DCDC_MAX_NAME];
|
||||
struct regulator_desc desc;
|
||||
|
|
@ -59,6 +64,7 @@ struct wm831x_dcdc {
|
|||
int on_vsel;
|
||||
int dvs_vsel;
|
||||
};
|
||||
#endif
|
||||
|
||||
static int wm831x_dcdc_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
|
|
@ -302,6 +308,23 @@ static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int wm831x_buckv_read_voltage(struct regulator_dev *rdev)
|
||||
{
|
||||
int vol_read;
|
||||
int ret;
|
||||
struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
|
||||
struct wm831x *wm831x = dcdc->wm831x;
|
||||
int on_reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
|
||||
|
||||
ret = wm831x_reg_read(wm831x, on_reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret &= WM831X_DC1_ON_VSEL_MASK;
|
||||
vol_read = (ret-8)*12500 + 600000;
|
||||
|
||||
return vol_read;
|
||||
}
|
||||
|
||||
static int wm831x_buckv_set_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV, unsigned *selector)
|
||||
{
|
||||
|
|
@ -393,6 +416,71 @@ static u16 wm831x_dcdc_ilim[] = {
|
|||
125, 250, 375, 500, 625, 750, 875, 1000
|
||||
};
|
||||
|
||||
static int wm831x_buckv_set_voltage_step(struct regulator_dev * rdev, int min_uV, int max_uV)
|
||||
{
|
||||
int old_vol;
|
||||
int new_min_uV,new_max_uV;
|
||||
int diff_value,step;
|
||||
int ret=0;
|
||||
|
||||
struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
|
||||
struct wm831x *wm831x = dcdc->wm831x;
|
||||
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
|
||||
|
||||
//if(strcmp(rdev->constraints->name,"DCDC2") != 0)
|
||||
if(strcmp(pdata->dcdc[1]->consumer_supplies[1].supply,"vcore") != 0)
|
||||
{
|
||||
ret = wm831x_buckv_set_voltage(rdev,min_uV,max_uV);
|
||||
}
|
||||
else
|
||||
{
|
||||
old_vol = wm831x_buckv_read_voltage(rdev);
|
||||
|
||||
new_min_uV = old_vol;
|
||||
new_max_uV = old_vol+max_uV-min_uV;
|
||||
|
||||
if(old_vol > min_uV) //reduce voltage
|
||||
{
|
||||
diff_value = (old_vol - min_uV);
|
||||
|
||||
for(step = 100000; step<=diff_value; step += 100000)
|
||||
{
|
||||
new_min_uV = old_vol-step;
|
||||
new_max_uV = old_vol+max_uV-min_uV-step;
|
||||
|
||||
ret = wm831x_buckv_set_voltage(rdev,new_min_uV,new_max_uV);
|
||||
usleep_range(1000,1000);
|
||||
}
|
||||
|
||||
if(new_min_uV > min_uV) //0< old_vol - min_uV < 100000 ||0< new_min_uV - min_uV < 1000000
|
||||
{
|
||||
ret = wm831x_buckv_set_voltage(rdev,min_uV,max_uV);
|
||||
usleep_range(1000,1000);
|
||||
}
|
||||
}
|
||||
else //rise voltage
|
||||
{
|
||||
diff_value = (min_uV- old_vol);
|
||||
|
||||
for(step = 100000; step<=diff_value; step += 100000)
|
||||
{
|
||||
new_min_uV = old_vol + step;
|
||||
new_max_uV = old_vol+max_uV-min_uV+step;
|
||||
|
||||
ret = wm831x_buckv_set_voltage(rdev,new_min_uV,new_max_uV);
|
||||
usleep_range(1000,1000);
|
||||
}
|
||||
if(new_min_uV < min_uV)// min_uV - old_vol < 100000 || new_min_uV - old_vol < 100000
|
||||
{
|
||||
ret = wm831x_buckv_set_voltage(rdev,min_uV,max_uV);
|
||||
usleep_range(1000,1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wm831x_buckv_set_current_limit(struct regulator_dev *rdev,
|
||||
int min_uA, int max_uA)
|
||||
{
|
||||
|
|
@ -425,8 +513,18 @@ static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev)
|
|||
return wm831x_dcdc_ilim[val & WM831X_DC1_HC_THR_MASK];
|
||||
}
|
||||
|
||||
static int wm831x_dcdc_set_suspend_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm831x_dcdc_set_suspend_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct regulator_ops wm831x_buckv_ops = {
|
||||
.set_voltage = wm831x_buckv_set_voltage,
|
||||
.set_voltage = wm831x_buckv_set_voltage_step,
|
||||
.get_voltage_sel = wm831x_buckv_get_voltage_sel,
|
||||
.list_voltage = wm831x_buckv_list_voltage,
|
||||
.set_suspend_voltage = wm831x_buckv_set_suspend_voltage,
|
||||
|
|
@ -440,6 +538,8 @@ static struct regulator_ops wm831x_buckv_ops = {
|
|||
.get_mode = wm831x_dcdc_get_mode,
|
||||
.set_mode = wm831x_dcdc_set_mode,
|
||||
.set_suspend_mode = wm831x_dcdc_set_suspend_mode,
|
||||
.set_suspend_enable = wm831x_dcdc_set_suspend_enable,
|
||||
.set_suspend_disable = wm831x_dcdc_set_suspend_disable,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -703,6 +803,8 @@ static struct regulator_ops wm831x_buckp_ops = {
|
|||
.get_mode = wm831x_dcdc_get_mode,
|
||||
.set_mode = wm831x_dcdc_set_mode,
|
||||
.set_suspend_mode = wm831x_dcdc_set_suspend_mode,
|
||||
.set_suspend_enable = wm831x_dcdc_set_suspend_enable,
|
||||
.set_suspend_disable = wm831x_dcdc_set_suspend_disable,
|
||||
};
|
||||
|
||||
static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
|
||||
|
|
@ -1011,6 +1113,7 @@ static struct platform_driver wm831x_epe_driver = {
|
|||
static int __init wm831x_dcdc_init(void)
|
||||
{
|
||||
int ret;
|
||||
printk("%s \n", __FUNCTION__);
|
||||
ret = platform_driver_register(&wm831x_buckv_driver);
|
||||
if (ret != 0)
|
||||
pr_err("Failed to register WM831x BUCKV driver: %d\n", ret);
|
||||
|
|
|
|||
|
|
@ -25,8 +25,9 @@
|
|||
#include <linux/mfd/wm831x/regulator.h>
|
||||
#include <linux/mfd/wm831x/pdata.h>
|
||||
|
||||
#define WM831X_ISINK_MAX_NAME 7
|
||||
//#define WM831X_ISINK_MAX_NAME 7
|
||||
|
||||
#if 0
|
||||
struct wm831x_isink {
|
||||
char name[WM831X_ISINK_MAX_NAME];
|
||||
struct regulator_desc desc;
|
||||
|
|
@ -34,13 +35,14 @@ struct wm831x_isink {
|
|||
struct wm831x *wm831x;
|
||||
struct regulator_dev *regulator;
|
||||
};
|
||||
#endif
|
||||
|
||||
static int wm831x_isink_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm831x_isink *isink = rdev_get_drvdata(rdev);
|
||||
struct wm831x *wm831x = isink->wm831x;
|
||||
int ret;
|
||||
|
||||
printk("%s:line=%d\n",__FUNCTION__,__LINE__);
|
||||
/* We have a two stage enable: first start the ISINK... */
|
||||
ret = wm831x_set_bits(wm831x, isink->reg, WM831X_CS1_ENA,
|
||||
WM831X_CS1_ENA);
|
||||
|
|
@ -52,7 +54,7 @@ static int wm831x_isink_enable(struct regulator_dev *rdev)
|
|||
WM831X_CS1_DRIVE);
|
||||
if (ret != 0)
|
||||
wm831x_set_bits(wm831x, isink->reg, WM831X_CS1_ENA, 0);
|
||||
|
||||
printk("%s:line=%d,ret=0x%x\n",__FUNCTION__,__LINE__,ret);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
|
@ -62,7 +64,7 @@ static int wm831x_isink_disable(struct regulator_dev *rdev)
|
|||
struct wm831x_isink *isink = rdev_get_drvdata(rdev);
|
||||
struct wm831x *wm831x = isink->wm831x;
|
||||
int ret;
|
||||
|
||||
printk("%s:line=%d\n",__FUNCTION__,__LINE__);
|
||||
ret = wm831x_set_bits(wm831x, isink->reg, WM831X_CS1_DRIVE, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
@ -80,11 +82,11 @@ static int wm831x_isink_is_enabled(struct regulator_dev *rdev)
|
|||
struct wm831x_isink *isink = rdev_get_drvdata(rdev);
|
||||
struct wm831x *wm831x = isink->wm831x;
|
||||
int ret;
|
||||
|
||||
printk("%s:line=%d\n",__FUNCTION__,__LINE__);
|
||||
ret = wm831x_reg_read(wm831x, isink->reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
||||
if ((ret & (WM831X_CS1_ENA | WM831X_CS1_DRIVE)) ==
|
||||
(WM831X_CS1_ENA | WM831X_CS1_DRIVE))
|
||||
return 1;
|
||||
|
|
@ -158,7 +160,7 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev)
|
|||
int ret, irq;
|
||||
|
||||
dev_dbg(&pdev->dev, "Probing ISINK%d\n", id + 1);
|
||||
|
||||
printk("%s:line=%d\n",__FUNCTION__,__LINE__);
|
||||
if (pdata == NULL || pdata->isink[id] == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
|
|
@ -198,8 +200,15 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
<<<<<<< HEAD
|
||||
ret = request_threaded_irq(irq, NULL, wm831x_isink_irq,
|
||||
IRQF_TRIGGER_RISING, isink->name, isink);
|
||||
=======
|
||||
printk("%s:line=%d,irq=%d\n",__FUNCTION__,__LINE__,irq);
|
||||
ret = wm831x_request_irq(wm831x, irq, wm831x_isink_irq,
|
||||
IRQF_TRIGGER_RISING, isink->name,
|
||||
isink);
|
||||
>>>>>>> parent of 15f7fab... temp revert rk change
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "Failed to request ISINK IRQ %d: %d\n",
|
||||
irq, ret);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
#include <linux/mfd/wm831x/regulator.h>
|
||||
#include <linux/mfd/wm831x/pdata.h>
|
||||
|
||||
#define WM831X_LDO_MAX_NAME 6
|
||||
//#define WM831X_LDO_MAX_NAME 6
|
||||
|
||||
#define WM831X_LDO_CONTROL 0
|
||||
#define WM831X_LDO_ON_CONTROL 1
|
||||
|
|
@ -34,6 +34,7 @@
|
|||
#define WM831X_ALIVE_LDO_ON_CONTROL 0
|
||||
#define WM831X_ALIVE_LDO_SLEEP_CONTROL 1
|
||||
|
||||
#if 0
|
||||
struct wm831x_ldo {
|
||||
char name[WM831X_LDO_MAX_NAME];
|
||||
struct regulator_desc desc;
|
||||
|
|
@ -41,11 +42,12 @@ struct wm831x_ldo {
|
|||
struct wm831x *wm831x;
|
||||
struct regulator_dev *regulator;
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Shared
|
||||
*/
|
||||
|
||||
extern int reboot_cmd_get(void);
|
||||
static int wm831x_ldo_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
|
|
@ -68,7 +70,7 @@ static int wm831x_ldo_enable(struct regulator_dev *rdev)
|
|||
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
struct wm831x *wm831x = ldo->wm831x;
|
||||
int mask = 1 << rdev_get_id(rdev);
|
||||
|
||||
//printk("%s,%x\n", __FUNCTION__,mask);
|
||||
return wm831x_set_bits(wm831x, WM831X_LDO_ENABLE, mask, mask);
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +79,7 @@ static int wm831x_ldo_disable(struct regulator_dev *rdev)
|
|||
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
struct wm831x *wm831x = ldo->wm831x;
|
||||
int mask = 1 << rdev_get_id(rdev);
|
||||
|
||||
//printk("%s\n", __FUNCTION__);
|
||||
return wm831x_set_bits(wm831x, WM831X_LDO_ENABLE, mask, 0);
|
||||
}
|
||||
|
||||
|
|
@ -170,7 +172,7 @@ static int wm831x_gp_ldo_get_voltage_sel(struct regulator_dev *rdev)
|
|||
ret = wm831x_reg_read(wm831x, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
//printk("%s base=%x,ret=%x\n", __FUNCTION__,ldo->base,ret);
|
||||
ret &= WM831X_LDO1_ON_VSEL_MASK;
|
||||
|
||||
return ret;
|
||||
|
|
@ -210,7 +212,7 @@ static int wm831x_gp_ldo_set_mode(struct regulator_dev *rdev,
|
|||
int on_reg = ldo->base + WM831X_LDO_ON_CONTROL;
|
||||
int ret;
|
||||
|
||||
|
||||
printk("%s base=%x,mode=%x\n", __FUNCTION__,ldo->base,mode);
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
ret = wm831x_set_bits(wm831x, on_reg,
|
||||
|
|
@ -290,6 +292,16 @@ static unsigned int wm831x_gp_ldo_get_optimum_mode(struct regulator_dev *rdev,
|
|||
return REGULATOR_MODE_NORMAL;
|
||||
}
|
||||
|
||||
int wm831x_ldo_set_suspend_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
int wm831x_ldo_set_suspend_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct regulator_ops wm831x_gp_ldo_ops = {
|
||||
.list_voltage = wm831x_gp_ldo_list_voltage,
|
||||
|
|
@ -304,6 +316,8 @@ static struct regulator_ops wm831x_gp_ldo_ops = {
|
|||
.is_enabled = wm831x_ldo_is_enabled,
|
||||
.enable = wm831x_ldo_enable,
|
||||
.disable = wm831x_ldo_disable,
|
||||
.set_suspend_enable = wm831x_ldo_set_suspend_enable,
|
||||
.set_suspend_disable = wm831x_ldo_set_suspend_disable,
|
||||
};
|
||||
|
||||
static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
|
||||
|
|
@ -316,7 +330,7 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
|
|||
int ret, irq;
|
||||
|
||||
dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
|
||||
|
||||
printk("Probing LDO%d\n", id + 1);
|
||||
if (pdata == NULL || pdata->ldo[id] == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
|
|
@ -450,6 +464,7 @@ static int wm831x_aldo_set_voltage(struct regulator_dev *rdev,
|
|||
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
|
||||
int reg = ldo->base + WM831X_LDO_ON_CONTROL;
|
||||
|
||||
printk("%s base=%x,min_uV=%d,%d\n", __FUNCTION__,ldo->base,min_uV,max_uV);
|
||||
return wm831x_aldo_set_voltage_int(rdev, reg, min_uV, max_uV,
|
||||
selector);
|
||||
}
|
||||
|
|
@ -474,7 +489,7 @@ static int wm831x_aldo_get_voltage_sel(struct regulator_dev *rdev)
|
|||
ret = wm831x_reg_read(wm831x, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
printk("%s base=%x,ret=%x\n", __FUNCTION__,ldo->base,ret);
|
||||
ret &= WM831X_LDO7_ON_VSEL_MASK;
|
||||
|
||||
return ret;
|
||||
|
|
@ -568,6 +583,8 @@ static struct regulator_ops wm831x_aldo_ops = {
|
|||
.is_enabled = wm831x_ldo_is_enabled,
|
||||
.enable = wm831x_ldo_enable,
|
||||
.disable = wm831x_ldo_disable,
|
||||
.set_suspend_enable = wm831x_ldo_set_suspend_enable,
|
||||
.set_suspend_disable = wm831x_ldo_set_suspend_disable,
|
||||
};
|
||||
|
||||
static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
|
||||
|
|
@ -580,7 +597,7 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
|
|||
int ret, irq;
|
||||
|
||||
dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
|
||||
|
||||
printk("Probing LDO%d--\n", id + 1);
|
||||
if (pdata == NULL || pdata->ldo[id] == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
|
|
@ -758,6 +775,8 @@ static struct regulator_ops wm831x_alive_ldo_ops = {
|
|||
.is_enabled = wm831x_ldo_is_enabled,
|
||||
.enable = wm831x_ldo_enable,
|
||||
.disable = wm831x_ldo_disable,
|
||||
.set_suspend_enable = wm831x_ldo_set_suspend_enable,
|
||||
.set_suspend_disable = wm831x_ldo_set_suspend_disable,
|
||||
};
|
||||
|
||||
static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
|
||||
|
|
@ -770,7 +789,7 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
|
|||
int ret;
|
||||
|
||||
dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
|
||||
|
||||
printk("wm831x_alive_ldo_probe Probing LDO%d\n", id + 1);
|
||||
if (pdata == NULL || pdata->ldo[id] == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
|
|
@ -826,9 +845,64 @@ static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static __devexit int wm831x_alive_ldo_shutdown(struct platform_device *pdev) /*ZMF*/
|
||||
{
|
||||
//struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
|
||||
#if 0
|
||||
//close ldo in wm831x_last_deinit()
|
||||
struct regulator* ldo;
|
||||
|
||||
//if (reboot_cmd_get())
|
||||
// return 0;
|
||||
printk("%s\n", __FUNCTION__);
|
||||
|
||||
ldo = regulator_get(NULL, "ldo1");
|
||||
regulator_disable(ldo);
|
||||
regulator_put(ldo);
|
||||
|
||||
ldo = regulator_get(NULL, "ldo2");
|
||||
regulator_disable(ldo);
|
||||
regulator_put(ldo);
|
||||
|
||||
ldo = regulator_get(NULL, "ldo3");
|
||||
regulator_disable(ldo);
|
||||
regulator_put(ldo);
|
||||
|
||||
ldo = regulator_get(NULL, "ldo4");
|
||||
//regulator_disable(ldo);
|
||||
regulator_put(ldo);
|
||||
|
||||
ldo = regulator_get(NULL, "ldo5");
|
||||
regulator_disable(ldo);
|
||||
regulator_put(ldo);
|
||||
|
||||
ldo = regulator_get(NULL, "ldo6");
|
||||
regulator_disable(ldo);
|
||||
regulator_put(ldo);
|
||||
|
||||
ldo = regulator_get(NULL, "ldo7");
|
||||
regulator_disable(ldo);
|
||||
regulator_put(ldo);
|
||||
|
||||
ldo = regulator_get(NULL, "ldo8");
|
||||
//regulator_disable(ldo);
|
||||
regulator_put(ldo);
|
||||
|
||||
ldo = regulator_get(NULL, "ldo9");
|
||||
regulator_disable(ldo);
|
||||
regulator_put(ldo);
|
||||
|
||||
ldo = regulator_get(NULL, "ldo10");
|
||||
regulator_disable(ldo);
|
||||
regulator_put(ldo);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver wm831x_alive_ldo_driver = {
|
||||
.probe = wm831x_alive_ldo_probe,
|
||||
.remove = __devexit_p(wm831x_alive_ldo_remove),
|
||||
.shutdown = __devexit_p(wm831x_alive_ldo_shutdown),
|
||||
.driver = {
|
||||
.name = "wm831x-alive-ldo",
|
||||
.owner = THIS_MODULE,
|
||||
|
|
@ -838,7 +912,7 @@ static struct platform_driver wm831x_alive_ldo_driver = {
|
|||
static int __init wm831x_ldo_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printk("%s \n", __FUNCTION__);
|
||||
ret = platform_driver_register(&wm831x_gp_ldo_driver);
|
||||
if (ret != 0)
|
||||
pr_err("Failed to register WM831x GP LDO driver: %d\n", ret);
|
||||
|
|
|
|||
|
|
@ -153,6 +153,21 @@ config RTC_DRV_88PM860X
|
|||
This driver can also be built as a module. If so, the module
|
||||
will be called rtc-88pm860x.
|
||||
|
||||
config RTC_HYM8563
|
||||
tristate "RK2818 or RK29 extern HYM8563 RTC"
|
||||
depends on I2C_RK2818 || I2C_RK29
|
||||
help
|
||||
If you say yes here you will get support for the
|
||||
HYM8563 I2C RTC chip.
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called rtc-HYM8563.
|
||||
|
||||
config RTC_M41T66
|
||||
tristate "ST M41T66"
|
||||
depends on I2C_RK2818 || I2C_RK29
|
||||
help
|
||||
If you say Y here you will get support for the ST M41T66.
|
||||
|
||||
config RTC_DRV_DS1307
|
||||
tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025"
|
||||
help
|
||||
|
|
@ -351,6 +366,16 @@ config RTC_DRV_S35390A
|
|||
This driver can also be built as a module. If so the module
|
||||
will be called rtc-s35390a.
|
||||
|
||||
config RTC_DRV_S35392A
|
||||
tristate "Seiko Instruments S-35392A"
|
||||
select BITREVERSE
|
||||
help
|
||||
If you say yes here you will get support for the Seiko
|
||||
Instruments S-35392A.
|
||||
|
||||
This driver can also be built as a module. If so the module
|
||||
will be called rtc-s35392a.
|
||||
|
||||
config RTC_DRV_FM3130
|
||||
tristate "Ramtron FM3130"
|
||||
help
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o
|
|||
obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o
|
||||
obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o
|
||||
obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o
|
||||
obj-$(CONFIG_RTC_DRV_S35392A) += rtc-s35392a.o
|
||||
obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o
|
||||
obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o
|
||||
obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o
|
||||
|
|
@ -110,3 +111,5 @@ obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o
|
|||
obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o
|
||||
obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
|
||||
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
|
||||
obj-$(CONFIG_RTC_HYM8563) += rtc-HYM8563.o
|
||||
obj-$(CONFIG_RTC_M41T66) += rtc-m41t66.o
|
||||
|
|
|
|||
|
|
@ -423,6 +423,7 @@ static int alarm_suspend(struct platform_device *pdev, pm_message_t state)
|
|||
if (rtc_current_time + 1 >= rtc_alarm_time) {
|
||||
pr_alarm(SUSPEND, "alarm about to go off\n");
|
||||
memset(&rtc_alarm, 0, sizeof(rtc_alarm));
|
||||
rtc_time_to_tm(0, &rtc_alarm.time);
|
||||
rtc_alarm.enabled = 0;
|
||||
rtc_set_alarm(alarm_rtc_dev, &rtc_alarm);
|
||||
|
||||
|
|
@ -448,6 +449,7 @@ static int alarm_resume(struct platform_device *pdev)
|
|||
pr_alarm(SUSPEND, "alarm_resume(%p)\n", pdev);
|
||||
|
||||
memset(&alarm, 0, sizeof(alarm));
|
||||
rtc_time_to_tm(0, &alarm.time);
|
||||
alarm.enabled = 0;
|
||||
rtc_set_alarm(alarm_rtc_dev, &alarm);
|
||||
|
||||
|
|
@ -461,6 +463,18 @@ static int alarm_resume(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void alarm_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct rtc_wkalrm alarm;
|
||||
|
||||
pr_alarm(FLOW, "alarm_shutdown(%p)\n", pdev);
|
||||
|
||||
memset(&alarm, 0, sizeof(alarm));
|
||||
rtc_time_to_tm(0, &alarm.time);
|
||||
alarm.enabled = 0;
|
||||
rtc_set_alarm(alarm_rtc_dev, &alarm);
|
||||
}
|
||||
|
||||
static struct rtc_task alarm_rtc_task = {
|
||||
.func = alarm_triggered_func
|
||||
};
|
||||
|
|
@ -520,6 +534,7 @@ static struct class_interface rtc_alarm_interface = {
|
|||
static struct platform_driver alarm_driver = {
|
||||
.suspend = alarm_suspend,
|
||||
.resume = alarm_resume,
|
||||
.shutdown = alarm_shutdown,
|
||||
.driver = {
|
||||
.name = "alarm"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -401,16 +401,7 @@ static int __devinit hym8563_probe(struct i2c_client *client, const struct i2c_d
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rtc = rtc_device_register(client->name, &client->dev,
|
||||
&hym8563_rtc_ops, THIS_MODULE);
|
||||
if (IS_ERR(rtc)) {
|
||||
rc = PTR_ERR(rtc);
|
||||
rtc = NULL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
hym8563->client = client;
|
||||
hym8563->rtc = rtc;
|
||||
mutex_init(&hym8563->mutex);
|
||||
wake_lock_init(&hym8563->wake_lock, WAKE_LOCK_SUSPEND, "rtc_hym8563");
|
||||
INIT_WORK(&hym8563->work, hym8563_work_func);
|
||||
|
|
@ -447,6 +438,16 @@ static int __devinit hym8563_probe(struct i2c_client *client, const struct i2c_d
|
|||
goto exit;
|
||||
}
|
||||
enable_irq_wake(hym8563->irq);
|
||||
|
||||
rtc = rtc_device_register(client->name, &client->dev,
|
||||
&hym8563_rtc_ops, THIS_MODULE);
|
||||
if (IS_ERR(rtc)) {
|
||||
rc = PTR_ERR(rtc);
|
||||
rtc = NULL;
|
||||
goto exit;
|
||||
}
|
||||
hym8563->rtc = rtc;
|
||||
|
||||
return 0;
|
||||
|
||||
exit:
|
||||
|
|
|
|||
|
|
@ -1,698 +0,0 @@
|
|||
/*
|
||||
* rtc-tps65910.c -- TPS65910 Real Time Clock interface
|
||||
*
|
||||
* Copyright (C) 2010 Mistral Solutions Pvt Ltd. <www.mistralsolutions.com>
|
||||
* Author: Umesh K <umeshk@mistralsolutions.com>
|
||||
*
|
||||
* Based on rtc-twl.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c/tps65910.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#if 0
|
||||
#define DBG(x...) printk(KERN_INFO x)
|
||||
#else
|
||||
#define DBG(x...)
|
||||
#endif
|
||||
|
||||
/* RTC Definitions */
|
||||
/* RTC_CTRL_REG bitfields */
|
||||
#define BIT_RTC_CTRL_REG_STOP_RTC_M 0x01
|
||||
#define BIT_RTC_CTRL_REG_ROUND_30S_M 0x02
|
||||
#define BIT_RTC_CTRL_REG_AUTO_COMP_M 0x04
|
||||
#define BIT_RTC_CTRL_REG_MODE_12_24_M 0x08
|
||||
#define BIT_RTC_CTRL_REG_TEST_MODE_M 0x10
|
||||
#define BIT_RTC_CTRL_REG_SET_32_COUNTER_M 0x20
|
||||
#define BIT_RTC_CTRL_REG_GET_TIME_M 0x40
|
||||
#define BIT_RTC_CTRL_REG_RTC_V_OPT_M 0x80
|
||||
|
||||
/* RTC_STATUS_REG bitfields */
|
||||
#define BIT_RTC_STATUS_REG_RUN_M 0x02
|
||||
#define BIT_RTC_STATUS_REG_1S_EVENT_M 0x04
|
||||
#define BIT_RTC_STATUS_REG_1M_EVENT_M 0x08
|
||||
#define BIT_RTC_STATUS_REG_1H_EVENT_M 0x10
|
||||
#define BIT_RTC_STATUS_REG_1D_EVENT_M 0x20
|
||||
#define BIT_RTC_STATUS_REG_ALARM_M 0x40
|
||||
#define BIT_RTC_STATUS_REG_POWER_UP_M 0x80
|
||||
|
||||
/* RTC_INTERRUPTS_REG bitfields */
|
||||
#define BIT_RTC_INTERRUPTS_REG_EVERY_M 0x03
|
||||
#define BIT_RTC_INTERRUPTS_REG_IT_TIMER_M 0x04
|
||||
#define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M 0x08
|
||||
|
||||
/* DEVCTRL bitfields */
|
||||
#define BIT_RTC_PWDN 0x40
|
||||
|
||||
/* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */
|
||||
#define ALL_TIME_REGS 6
|
||||
|
||||
/*
|
||||
* Supports 1 byte read from TPS65910 RTC register.
|
||||
*/
|
||||
static int tps65910_rtc_read_u8(u8 *data, u8 reg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = tps65910_i2c_read_u8(TPS65910_I2C_ID0, data, reg);
|
||||
|
||||
if (ret < 0)
|
||||
pr_err("tps65910_rtc: Could not read TPS65910"
|
||||
"register %X - error %d\n", reg, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Supports 1 byte write to TPS65910 RTC registers.
|
||||
*/
|
||||
static int tps65910_rtc_write_u8(u8 data, u8 reg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = tps65910_i2c_write_u8(TPS65910_I2C_ID0, data, reg);
|
||||
if (ret < 0)
|
||||
pr_err("tps65910_rtc: Could not write TPS65910"
|
||||
"register %X - error %d\n", reg, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cache the value for timer/alarm interrupts register; this is
|
||||
* only changed by callers holding rtc ops lock (or resume).
|
||||
*/
|
||||
static unsigned char rtc_irq_bits;
|
||||
|
||||
/*
|
||||
* Enable 1/second update and/or alarm interrupts.
|
||||
*/
|
||||
static int set_rtc_irq_bit(unsigned char bit)
|
||||
{
|
||||
unsigned char val;
|
||||
int ret;
|
||||
|
||||
val = rtc_irq_bits | bit;
|
||||
val |= bit;
|
||||
ret = tps65910_rtc_write_u8(val, TPS65910_REG_RTC_INTERRUPTS);
|
||||
if (ret == 0)
|
||||
rtc_irq_bits = val;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable update and/or alarm interrupts.
|
||||
*/
|
||||
static int mask_rtc_irq_bit(unsigned char bit)
|
||||
{
|
||||
unsigned char val;
|
||||
int ret;
|
||||
|
||||
val = rtc_irq_bits & ~bit;
|
||||
ret = tps65910_rtc_write_u8(val, TPS65910_REG_RTC_INTERRUPTS);
|
||||
if (ret == 0)
|
||||
rtc_irq_bits = val;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps65910_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (enabled)
|
||||
ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
|
||||
else
|
||||
ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps65910_rtc_update_irq_enable(struct device *dev, unsigned enabled)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (enabled)
|
||||
ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
|
||||
else
|
||||
ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 1 /* Debugging periodic interrupts */
|
||||
/*
|
||||
* We will just handle setting the frequency and make use the framework for
|
||||
* reading the periodic interupts.
|
||||
*
|
||||
* @freq: Current periodic IRQ freq:
|
||||
* bit 0: every second
|
||||
* bit 1: every minute
|
||||
* bit 2: every hour
|
||||
* bit 3: every day
|
||||
*/
|
||||
|
||||
static int tps65910_rtc_irq_set_freq(struct device *dev, int freq)
|
||||
{
|
||||
struct rtc_device *rtc = dev_get_drvdata(dev);
|
||||
|
||||
if (freq < 0 || freq > 3)
|
||||
return -EINVAL;
|
||||
|
||||
rtc->irq_freq = freq;
|
||||
/* set rtc irq freq to user defined value */
|
||||
set_rtc_irq_bit(freq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Gets current TPS65910 RTC time and date parameters.
|
||||
*
|
||||
* The RTC's time/alarm representation is not what gmtime(3) requires
|
||||
* Linux to use:
|
||||
*
|
||||
* - Months are 1..12 vs Linux 0-11
|
||||
* - Years are 0..99 vs Linux 1900..N (we assume 21st century)
|
||||
*/
|
||||
static int tps65910_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
unsigned char rtc_data[ALL_TIME_REGS + 1];
|
||||
int ret;
|
||||
u8 save_control;
|
||||
|
||||
tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
|
||||
ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
save_control &= ~BIT_RTC_CTRL_REG_RTC_V_OPT_M;
|
||||
|
||||
ret = tps65910_rtc_write_u8(save_control, TPS65910_REG_RTC_CTRL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = tps65910_rtc_read_u8(&rtc_data[0], TPS65910_REG_SECONDS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_read_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_read_u8(&rtc_data[1], TPS65910_REG_MINUTES);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_read_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_read_u8(&rtc_data[2], TPS65910_REG_HOURS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_read_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_read_u8(&rtc_data[3], TPS65910_REG_DAYS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_read_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_read_u8(&rtc_data[4], TPS65910_REG_MONTHS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_read_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_read_u8(&rtc_data[5], TPS65910_REG_YEARS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_read_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
tm->tm_sec = bcd2bin(rtc_data[0]);
|
||||
tm->tm_min = bcd2bin(rtc_data[1]);
|
||||
tm->tm_hour = bcd2bin(rtc_data[2]);
|
||||
tm->tm_mday = bcd2bin(rtc_data[3]);
|
||||
tm->tm_mon = bcd2bin(rtc_data[4]) - 1;
|
||||
tm->tm_year = bcd2bin(rtc_data[5]) + 100;
|
||||
|
||||
DBG("%s [%d]tm_wday=%d \n",__FUNCTION__,__LINE__,tm->tm_wday);
|
||||
DBG("%s [%d]tm_sec=%d \n",__FUNCTION__,__LINE__,tm->tm_sec);
|
||||
DBG("%s [%d]tm_min=%d \n",__FUNCTION__,__LINE__,tm->tm_min);
|
||||
DBG("%s [%d]tm_hour=%d \n",__FUNCTION__,__LINE__,tm->tm_hour);
|
||||
DBG("%s [%d]tm_mday=%d \n",__FUNCTION__,__LINE__,tm->tm_mday);
|
||||
DBG("%s [%d]tm_mon=%d \n",__FUNCTION__,__LINE__,tm->tm_mon);
|
||||
DBG("%s [%d]tm_year=%d \n",__FUNCTION__,__LINE__,tm->tm_year);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps65910_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
unsigned char save_control;
|
||||
unsigned char rtc_data[ALL_TIME_REGS + 1];
|
||||
int ret;
|
||||
|
||||
DBG("%s [%d]tm_wday=%d \n",__FUNCTION__,__LINE__,tm->tm_wday);
|
||||
DBG("%s [%d]tm_sec=%d \n",__FUNCTION__,__LINE__,tm->tm_sec);
|
||||
DBG("%s [%d]tm_min=%d \n",__FUNCTION__,__LINE__,tm->tm_min);
|
||||
DBG("%s [%d]tm_hour=%d \n",__FUNCTION__,__LINE__,tm->tm_hour);
|
||||
DBG("%s [%d]tm_mday=%d \n",__FUNCTION__,__LINE__,tm->tm_mday);
|
||||
DBG("%s [%d]tm_mon=%d \n",__FUNCTION__,__LINE__,tm->tm_mon);
|
||||
DBG("%s [%d]tm_year=%d \n",__FUNCTION__,__LINE__,tm->tm_year);
|
||||
|
||||
rtc_data[1] = bin2bcd(tm->tm_sec);
|
||||
rtc_data[2] = bin2bcd(tm->tm_min);
|
||||
rtc_data[3] = bin2bcd(tm->tm_hour);
|
||||
rtc_data[4] = bin2bcd(tm->tm_mday);
|
||||
rtc_data[5] = bin2bcd(tm->tm_mon + 1);
|
||||
rtc_data[6] = bin2bcd(tm->tm_year - 100);
|
||||
|
||||
/*Dummy read*/
|
||||
ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
|
||||
|
||||
/* Stop RTC while updating the TC registers */
|
||||
ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M;
|
||||
|
||||
tps65910_rtc_write_u8(save_control, TPS65910_REG_RTC_CTRL);
|
||||
|
||||
/* update all the time registers in one shot */
|
||||
ret = tps65910_rtc_write_u8(rtc_data[1], TPS65910_REG_SECONDS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_write_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_write_u8(rtc_data[2], TPS65910_REG_MINUTES);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_write_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_write_u8(rtc_data[3], TPS65910_REG_HOURS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_write_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_write_u8(rtc_data[4], TPS65910_REG_DAYS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_write_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_write_u8(rtc_data[5], TPS65910_REG_MONTHS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_write_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_write_u8(rtc_data[6], TPS65910_REG_YEARS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_write_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Dummy read*/
|
||||
ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
|
||||
|
||||
ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
/* Start back RTC */
|
||||
save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M;
|
||||
ret = tps65910_rtc_write_u8(save_control, TPS65910_REG_RTC_CTRL);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets current TPS65910 RTC alarm time.
|
||||
*/
|
||||
static int tps65910_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
|
||||
{
|
||||
unsigned char rtc_data[ALL_TIME_REGS + 1];
|
||||
int ret;
|
||||
|
||||
ret = tps65910_rtc_read_u8(&rtc_data[0], TPS65910_REG_ALARM_SECONDS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_read_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_read_u8(&rtc_data[1], TPS65910_REG_ALARM_MINUTES);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_read_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_read_u8(&rtc_data[2], TPS65910_REG_ALARM_HOURS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_read_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_read_u8(&rtc_data[3], TPS65910_REG_ALARM_DAYS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_read_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_read_u8(&rtc_data[4], TPS65910_REG_ALARM_MONTHS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_read_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_read_u8(&rtc_data[5], TPS65910_REG_ALARM_YEARS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_read_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* some of these fields may be wildcard/"match all" */
|
||||
alm->time.tm_sec = bcd2bin(rtc_data[0]);
|
||||
alm->time.tm_min = bcd2bin(rtc_data[1]);
|
||||
alm->time.tm_hour = bcd2bin(rtc_data[2]);
|
||||
alm->time.tm_mday = bcd2bin(rtc_data[3]);
|
||||
alm->time.tm_mon = bcd2bin(rtc_data[4]) - 1;
|
||||
alm->time.tm_year = bcd2bin(rtc_data[5]) + 100;
|
||||
|
||||
/* report cached alarm enable state */
|
||||
if (rtc_irq_bits & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M)
|
||||
alm->enabled = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps65910_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
|
||||
{
|
||||
unsigned char alarm_data[ALL_TIME_REGS + 1];
|
||||
int ret;
|
||||
|
||||
ret = tps65910_rtc_alarm_irq_enable(dev, 0);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
alarm_data[1] = bin2bcd(alm->time.tm_sec);
|
||||
alarm_data[2] = bin2bcd(alm->time.tm_min);
|
||||
alarm_data[3] = bin2bcd(alm->time.tm_hour);
|
||||
alarm_data[4] = bin2bcd(alm->time.tm_mday);
|
||||
alarm_data[5] = bin2bcd(alm->time.tm_mon + 1);
|
||||
alarm_data[6] = bin2bcd(alm->time.tm_year - 100);
|
||||
|
||||
/* update all the alarm registers in one shot */
|
||||
ret = tps65910_rtc_write_u8(alarm_data[1], TPS65910_REG_ALARM_SECONDS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_write_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_write_u8(alarm_data[2], TPS65910_REG_ALARM_MINUTES);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_write_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_write_u8(alarm_data[3], TPS65910_REG_ALARM_HOURS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_write_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_write_u8(alarm_data[4], TPS65910_REG_ALARM_DAYS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_write_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_write_u8(alarm_data[5], TPS65910_REG_ALARM_MONTHS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_write_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps65910_rtc_write_u8(alarm_data[6], TPS65910_REG_ALARM_YEARS);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rtc_write_time error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (alm->enabled)
|
||||
ret = tps65910_rtc_alarm_irq_enable(dev, 1);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct work_struct rtc_wq;
|
||||
unsigned long rtc_events;
|
||||
struct rtc_device *global_rtc;
|
||||
|
||||
void tps65910_rtc_work(void *data)
|
||||
{
|
||||
int res;
|
||||
u8 rd_reg;
|
||||
unsigned long events = 0;
|
||||
|
||||
DBG("Enter::%s %d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_INT_STS);
|
||||
|
||||
if (res < 0)
|
||||
goto out;
|
||||
/*
|
||||
* Figure out source of interrupt: ALARM or TIMER in RTC_STATUS_REG.
|
||||
* only one (ALARM or RTC) interrupt source may be enabled
|
||||
* at time, we also could check our results
|
||||
* by reading RTS_INTERRUPTS_REGISTER[IT_TIMER,IT_ALARM]
|
||||
*/
|
||||
if (rd_reg & TPS65910_RTC_ALARM_IT) {
|
||||
res = tps65910_rtc_write_u8(rd_reg | TPS65910_RTC_ALARM_IT,
|
||||
TPS65910_REG_INT_STS);
|
||||
if (res < 0)
|
||||
goto out;
|
||||
|
||||
/*Dummy read -- mandatory for status register*/
|
||||
res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
|
||||
mdelay(100);
|
||||
res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
|
||||
res = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_RTC_STATUS);
|
||||
|
||||
rtc_events |= RTC_IRQF | RTC_AF;
|
||||
} else if (rd_reg & TPS65910_RTC_PERIOD_IT) {
|
||||
res = tps65910_rtc_write_u8(rd_reg | TPS65910_RTC_PERIOD_IT,
|
||||
TPS65910_REG_INT_STS);
|
||||
if (res < 0)
|
||||
goto out;
|
||||
|
||||
/*Dummy read -- mandatory for status register*/
|
||||
res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
|
||||
mdelay(100);
|
||||
res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
|
||||
rd_reg &= 0xC3;
|
||||
res = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_RTC_STATUS);
|
||||
rtc_events |= RTC_IRQF | RTC_UF;
|
||||
}
|
||||
out:
|
||||
/* Notify RTC core on event */
|
||||
events = rtc_events;
|
||||
rtc_update_irq(global_rtc, 1, events);
|
||||
}
|
||||
|
||||
static struct rtc_class_ops tps65910_rtc_ops = {
|
||||
.read_time = tps65910_rtc_read_time,
|
||||
.set_time = tps65910_rtc_set_time,
|
||||
.read_alarm = tps65910_rtc_read_alarm,
|
||||
.set_alarm = tps65910_rtc_set_alarm,
|
||||
.alarm_irq_enable = tps65910_rtc_alarm_irq_enable,
|
||||
.update_irq_enable = tps65910_rtc_update_irq_enable,
|
||||
.irq_set_freq = tps65910_rtc_irq_set_freq,
|
||||
};
|
||||
|
||||
static int __devinit tps65910_rtc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rtc_device *rtc;
|
||||
int ret = 0, stop_run = 0;
|
||||
u8 rd_reg;
|
||||
struct rtc_time tm_def = { // 2011.1.1 12:00:00 Saturday
|
||||
.tm_wday = 6,
|
||||
.tm_year = 111,
|
||||
.tm_mon = 0,
|
||||
.tm_mday = 1,
|
||||
.tm_hour = 12,
|
||||
.tm_min = 0,
|
||||
.tm_sec = 0,
|
||||
};
|
||||
|
||||
rtc = rtc_device_register(pdev->name,
|
||||
&pdev->dev, &tps65910_rtc_ops, THIS_MODULE);
|
||||
|
||||
if (IS_ERR(rtc)) {
|
||||
ret = PTR_ERR(rtc);
|
||||
dev_err(&pdev->dev, "can't register TPS65910 RTC device,\
|
||||
err %ld\n", PTR_ERR(rtc));
|
||||
goto out0;
|
||||
|
||||
}
|
||||
printk(KERN_INFO "TPS65910 RTC device successfully registered\n");
|
||||
|
||||
platform_set_drvdata(pdev, rtc);
|
||||
/* Take rtc out of reset */
|
||||
tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_DEVCTRL);
|
||||
rd_reg &= ~BIT_RTC_PWDN;
|
||||
ret = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_DEVCTRL);
|
||||
|
||||
/* Dummy read to ensure that the register gets updated.
|
||||
* Please refer tps65910 TRM table:25 for details
|
||||
*/
|
||||
stop_run = 0;
|
||||
ret = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "TPS65910 RTC STATUS REG READ FAILED\n");
|
||||
goto out1;
|
||||
}
|
||||
|
||||
if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M) {
|
||||
dev_warn(&pdev->dev, "Power up reset detected.\n");
|
||||
// cwz:if rtc power up reset, set default time.
|
||||
printk(KERN_INFO "TPS65910 RTC set to default time\n");
|
||||
tps65910_rtc_set_time(rtc, &tm_def);
|
||||
}
|
||||
if (!(rd_reg & BIT_RTC_STATUS_REG_RUN_M)) {
|
||||
dev_warn(&pdev->dev, "RTC stop run.\n");
|
||||
stop_run = 1;
|
||||
}
|
||||
if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M)
|
||||
dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n");
|
||||
|
||||
/* Clear RTC Power up reset and pending alarm interrupts */
|
||||
ret = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_RTC_STATUS);
|
||||
if (ret < 0)
|
||||
goto out1;
|
||||
|
||||
ret = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_INT_STS);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "TPS65910 RTC STATUS REG READ FAILED\n");
|
||||
goto out1;
|
||||
}
|
||||
|
||||
if (rd_reg & 0x40) {
|
||||
printk(KERN_INFO "pending alarm interrupt!!! clearing!!!");
|
||||
tps65910_rtc_write_u8(rd_reg, TPS65910_REG_INT_STS);
|
||||
}
|
||||
|
||||
global_rtc = rtc;
|
||||
|
||||
/* Link RTC IRQ handler to TPS65910 Core */
|
||||
tps65910_add_irq_work(TPS65910_RTC_ALARM_IRQ, tps65910_rtc_work);
|
||||
tps65910_add_irq_work(TPS65910_RTC_PERIOD_IRQ, tps65910_rtc_work);
|
||||
|
||||
/* Check RTC module status, Enable if it is off */
|
||||
if (stop_run) {
|
||||
dev_info(&pdev->dev, "Enabling TPS65910-RTC.\n");
|
||||
// cwz:if rtc stop, set default time, then enable rtc
|
||||
printk(KERN_INFO "TPS65910 RTC set to default time\n");
|
||||
tps65910_rtc_set_time(rtc, &tm_def);
|
||||
ret = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_CTRL);
|
||||
if (ret < 0)
|
||||
goto out1;
|
||||
|
||||
rd_reg |= BIT_RTC_CTRL_REG_STOP_RTC_M;
|
||||
ret = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_RTC_CTRL);
|
||||
if (ret < 0)
|
||||
goto out1;
|
||||
}
|
||||
|
||||
/* init cached IRQ enable bits */
|
||||
ret = tps65910_rtc_read_u8(&rtc_irq_bits, TPS65910_REG_RTC_INTERRUPTS);
|
||||
if (ret < 0)
|
||||
goto out1;
|
||||
|
||||
tps65910_rtc_write_u8(0x3F, TPS65910_REG_INT_MSK);
|
||||
return ret;
|
||||
|
||||
out1:
|
||||
rtc_device_unregister(rtc);
|
||||
out0:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable all TPS65910 RTC module interrupts.
|
||||
* Sets status flag to free.
|
||||
*/
|
||||
static int __devexit tps65910_rtc_remove(struct platform_device *pdev)
|
||||
{
|
||||
/* leave rtc running, but disable irqs */
|
||||
struct rtc_device *rtc = platform_get_drvdata(pdev);
|
||||
int irq = platform_get_irq(pdev, 0);
|
||||
|
||||
mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
|
||||
mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
|
||||
|
||||
|
||||
free_irq(irq, rtc);
|
||||
|
||||
rtc_device_unregister(rtc);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tps65910_rtc_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
/* mask timer interrupts, but leave alarm interrupts on to enable
|
||||
* power-on when alarm is triggered
|
||||
*/
|
||||
mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static unsigned char irqstat;
|
||||
|
||||
static
|
||||
int tps65910_rtc_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
irqstat = rtc_irq_bits;
|
||||
mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps65910_rtc_resume(struct platform_device *pdev)
|
||||
{
|
||||
set_rtc_irq_bit(irqstat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#define tps65910_rtc_suspend NULL
|
||||
#define tps65910_rtc_resume NULL
|
||||
#endif
|
||||
|
||||
|
||||
static struct platform_driver tps65910rtc_driver = {
|
||||
.probe = tps65910_rtc_probe,
|
||||
.remove = __devexit_p(tps65910_rtc_remove),
|
||||
.shutdown = tps65910_rtc_shutdown,
|
||||
.suspend = tps65910_rtc_suspend,
|
||||
.resume = tps65910_rtc_resume,
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "tps65910_rtc",
|
||||
},
|
||||
};
|
||||
static int __init tps65910_rtc_init(void)
|
||||
{
|
||||
return platform_driver_register(&tps65910rtc_driver);
|
||||
}
|
||||
module_init(tps65910_rtc_init);
|
||||
|
||||
static void __exit tps65910_rtc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&tps65910rtc_driver);
|
||||
}
|
||||
module_exit(tps65910_rtc_exit);
|
||||
|
||||
MODULE_ALIAS("platform:tps65910_rtc");
|
||||
MODULE_AUTHOR("cwz <cwz@rockchips.com");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -1,834 +0,0 @@
|
|||
/*
|
||||
* drivers/serial/rk29_serial.c - driver for rk29 serial device and console
|
||||
*
|
||||
* Copyright (C) 2010 ROCKCHIP, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
|
||||
#if defined(CONFIG_SERIAL_RK29_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
||||
#define SUPPORT_SYSRQ
|
||||
#endif
|
||||
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <mach/iomux.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board.h>
|
||||
#include "rk2818_serial.h"
|
||||
|
||||
#define DBG_PORT 0
|
||||
#if 0
|
||||
#define DBG(msg...) printk(msg);
|
||||
#else
|
||||
#define DBG(...)
|
||||
#endif
|
||||
/*
|
||||
* We wrap our port structure around the generic uart_port.
|
||||
*/
|
||||
struct rk29_port {
|
||||
struct uart_port uart;
|
||||
char name[16];
|
||||
struct clk *clk;
|
||||
unsigned int imr;
|
||||
};
|
||||
|
||||
#define UART_TO_RK29(uart_port) ((struct rk29_port *) uart_port)
|
||||
#define RK29_SERIAL_MAJOR TTY_MAJOR
|
||||
#define RK29_SERIAL_MINOR 64
|
||||
|
||||
|
||||
static inline void rk29_uart_write(struct uart_port *port, unsigned int val,
|
||||
unsigned int off)
|
||||
{
|
||||
__raw_writel(val, port->membase + off);
|
||||
}
|
||||
|
||||
static inline unsigned int rk29_uart_read(struct uart_port *port, unsigned int off)
|
||||
{
|
||||
return __raw_readl(port->membase + off);
|
||||
}
|
||||
|
||||
static int rk29_set_baud_rate(struct uart_port *port, unsigned int baud)
|
||||
{
|
||||
unsigned int uartTemp;
|
||||
|
||||
rk29_uart_write(port,rk29_uart_read(port,UART_LCR) | LCR_DLA_EN,UART_LCR);
|
||||
uartTemp = port->uartclk / (16 * baud);
|
||||
rk29_uart_write(port,uartTemp & 0xff,UART_DLL);
|
||||
rk29_uart_write(port,(uartTemp>>8) & 0xff,UART_DLH);
|
||||
rk29_uart_write(port,rk29_uart_read(port,UART_LCR) & (~LCR_DLA_EN),UART_LCR);
|
||||
return baud;
|
||||
}
|
||||
|
||||
/*
|
||||
* 判断发送缓冲区是否为空
|
||||
*先以FIFO打开做,后面可以做成FIFO关或FIFO开。
|
||||
*/
|
||||
static u_int rk29_serial_tx_empty(struct uart_port *port)
|
||||
{
|
||||
int timeout = 10000000;
|
||||
while(!(rk29_uart_read(port,UART_USR)&UART_TRANSMIT_FIFO_EMPTY))
|
||||
if(timeout-- ==0)
|
||||
break;
|
||||
cpu_relax();
|
||||
if(rk29_uart_read(port,UART_USR)&UART_TRANSMIT_FIFO_EMPTY)
|
||||
{
|
||||
return (1);///1:空
|
||||
}else{
|
||||
return (0);///0:非空
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Power / Clock management.
|
||||
*/
|
||||
static void rk29_serial_pm(struct uart_port *port, unsigned int state,
|
||||
unsigned int oldstate)
|
||||
{
|
||||
struct rk29_port *rk29_port = UART_TO_RK29(port);
|
||||
|
||||
switch (state) {
|
||||
case 0:
|
||||
/*
|
||||
* Enable the peripheral clock for this serial port.
|
||||
* This is called on uart_open() or a resume event.
|
||||
*/
|
||||
clk_enable(rk29_port->clk);
|
||||
break;
|
||||
case 3:
|
||||
/*
|
||||
* Disable the peripheral clock for this serial port.
|
||||
* This is called on uart_close() or a suspend event.
|
||||
*/
|
||||
clk_disable(rk29_port->clk);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "rk29_serial: unknown pm %d\n", state);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return string describing the specified port
|
||||
*/
|
||||
static const char *rk29_serial_type(struct uart_port *port)
|
||||
{
|
||||
return (port->type == PORT_RK29) ? "RK29_SERIAL" : NULL;
|
||||
}
|
||||
|
||||
static void rk29_serial_enable_ms(struct uart_port *port)
|
||||
{
|
||||
#ifdef DEBUG_LHH
|
||||
printk("Enter::%s\n",__FUNCTION__);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* no modem control lines */
|
||||
static unsigned int rk29_serial_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
unsigned int result = 0;
|
||||
unsigned int status;
|
||||
|
||||
status = rk29_uart_read(port,UART_MSR);
|
||||
if (status & UART_MSR_URCTS)
|
||||
{
|
||||
result = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
|
||||
printk("UART_GET_MSR:0x%x\n",result);
|
||||
}else{
|
||||
result = TIOCM_CAR | TIOCM_DSR;
|
||||
printk("UART_GET_MSR:0x%x\n",result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void rk29_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
#ifdef DEBUG_LHH
|
||||
printk("Enter::%s\n",__FUNCTION__);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop transmitting.
|
||||
*/
|
||||
static void rk29_serial_stop_tx(struct uart_port *port)
|
||||
{
|
||||
#ifdef DEBUG_LHH
|
||||
printk("Enter::%s\n",__FUNCTION__);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Start transmitting.
|
||||
*/
|
||||
static void rk29_serial_start_tx(struct uart_port *port)
|
||||
{
|
||||
struct circ_buf *xmit = &port->state->xmit;
|
||||
|
||||
if(DBG_PORT == port->line) {
|
||||
DBG("TX:");
|
||||
}
|
||||
|
||||
while(!(uart_circ_empty(xmit)))
|
||||
{
|
||||
while (!(rk29_uart_read(port,UART_USR) & UART_TRANSMIT_FIFO_NOT_FULL)){
|
||||
rk29_uart_write(port,UART_IER_RECV_DATA_AVAIL_INT_ENABLE|UART_IER_SEND_EMPTY_INT_ENABLE,UART_IER);
|
||||
return;
|
||||
}
|
||||
rk29_uart_write(port,xmit->buf[xmit->tail],UART_THR);
|
||||
|
||||
if(DBG_PORT == port->line) {
|
||||
DBG("0x%x, ", xmit->buf[xmit->tail]);
|
||||
}
|
||||
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
}
|
||||
if((uart_circ_empty(xmit)))
|
||||
rk29_uart_write(port,UART_IER_RECV_DATA_AVAIL_INT_ENABLE,UART_IER);
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if(DBG_PORT == port->line) {
|
||||
DBG("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop receiving - port is in process of being closed.
|
||||
*/
|
||||
static void rk29_serial_stop_rx(struct uart_port *port)
|
||||
{
|
||||
#ifdef DEBUG_LHH
|
||||
printk("Enter::%s\n",__FUNCTION__);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Control the transmission of a break signal
|
||||
*/
|
||||
static void rk29_serial_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
unsigned int temp;
|
||||
temp = rk29_uart_read(port,UART_LCR);
|
||||
if (break_state != 0)
|
||||
temp = temp & (~BREAK_CONTROL_BIT);/* start break */
|
||||
else
|
||||
temp = temp | BREAK_CONTROL_BIT; /* stop break */
|
||||
rk29_uart_write(port,temp,UART_LCR);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Characters received (called from interrupt handler)
|
||||
*/
|
||||
static void rk29_rx_chars(struct uart_port *port)
|
||||
{
|
||||
unsigned int ch, flag;
|
||||
|
||||
if(DBG_PORT == port->line) {
|
||||
DBG("RX:");
|
||||
}
|
||||
|
||||
while((rk29_uart_read(port,UART_USR) & UART_RECEIVE_FIFO_NOT_EMPTY) == UART_RECEIVE_FIFO_NOT_EMPTY)
|
||||
{
|
||||
u32 lsr = rk29_uart_read(port, UART_LSR);
|
||||
ch = rk29_uart_read(port,UART_RBR);
|
||||
flag = TTY_NORMAL;
|
||||
port->icount.rx++;
|
||||
if (lsr & UART_BREAK_INT_BIT) {
|
||||
port->icount.brk++;
|
||||
if (uart_handle_break(port))
|
||||
continue;
|
||||
}
|
||||
#if 1
|
||||
if (uart_handle_sysrq_char(port, ch))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
uart_insert_char(port, 0, 0, ch, flag);
|
||||
|
||||
if(DBG_PORT == port->line) {
|
||||
DBG("0x%x, ", ch);
|
||||
}
|
||||
}
|
||||
tty_flip_buffer_push(port->state->port.tty);
|
||||
|
||||
if(DBG_PORT == port->line) {
|
||||
DBG("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt handler
|
||||
*/
|
||||
static irqreturn_t rk29_uart_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct uart_port *port = dev_id;
|
||||
unsigned int status, pending;
|
||||
|
||||
spin_lock(&port->lock);
|
||||
status = rk29_uart_read(port,UART_IIR);
|
||||
pending = status & 0x0f;
|
||||
if((pending == UART_IIR_RECV_AVAILABLE) || (pending == UART_IIR_CHAR_TIMEOUT))
|
||||
rk29_rx_chars(port);
|
||||
if(pending == UART_IIR_THR_EMPTY)
|
||||
rk29_serial_start_tx(port);
|
||||
spin_unlock(&port->lock);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable the port
|
||||
*/
|
||||
static void rk29_serial_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct rk29_port *rk29_port = UART_TO_RK29(port);
|
||||
rk29_uart_write(port,0x00,UART_IER);
|
||||
rk29_uart_write(port, UART_FCR_FIFO_ENABLE |
|
||||
UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, UART_FCR);
|
||||
//rk29_uart_write(port, 0, UART_FCR);
|
||||
clk_disable(rk29_port->clk);
|
||||
free_irq(port->irq, port);
|
||||
}
|
||||
/*
|
||||
* Perform initialization and enable port for reception
|
||||
*/
|
||||
static int rk29_serial_startup(struct uart_port *port)
|
||||
{
|
||||
struct rk29_port *rk29_port = UART_TO_RK29(port);
|
||||
struct tty_struct *tty = port->state->port.tty;
|
||||
int retval;
|
||||
DBG("%s\n",__FUNCTION__);
|
||||
|
||||
if(2 == port->line)
|
||||
{
|
||||
rk29_mux_api_set(GPIO2B1_UART2SOUT_NAME, GPIO2L_UART2_SOUT);
|
||||
rk29_mux_api_set(GPIO2B0_UART2SIN_NAME, GPIO2L_UART2_SIN);
|
||||
}
|
||||
else if(0 == port->line)
|
||||
{
|
||||
rk29_mux_api_set(GPIO1B7_UART0SOUT_NAME, GPIO1L_UART0_SOUT);
|
||||
rk29_mux_api_set(GPIO1B6_UART0SIN_NAME, GPIO1L_UART0_SIN);
|
||||
}
|
||||
else if(3 == port->line)
|
||||
{
|
||||
rk29_mux_api_set(GPIO2B3_UART3SOUT_NAME, GPIO2L_UART3_SOUT);
|
||||
rk29_mux_api_set(GPIO2B2_UART3SIN_NAME, GPIO2L_UART3_SIN);
|
||||
}
|
||||
|
||||
retval = request_irq(port->irq,rk29_uart_interrupt,IRQF_SHARED,
|
||||
tty ? tty->name : "rk29_serial",port);
|
||||
if(retval)
|
||||
{
|
||||
printk("\nrk29_serial_startup err \n");
|
||||
rk29_serial_shutdown(port);
|
||||
return retval;
|
||||
}
|
||||
clk_enable(rk29_port->clk);
|
||||
#if 0
|
||||
if(port->irq == IRQ_NR_UART0)
|
||||
rk29_uart_write(port,0xf7,UART_FCR); //enable and clear fifo if busy while starting
|
||||
else
|
||||
rk29_uart_write(port,0xf1,UART_FCR); //enable fifo
|
||||
rk29_uart_write(port,0x01,UART_SFE);
|
||||
rk29_uart_write(port,UART_IER_RECV_DATA_AVAIL_INT_ENABLE,UART_IER); //enable uart recevice IRQ
|
||||
#else
|
||||
//lw modify on 110309
|
||||
/*
|
||||
* Clear the FIFO buffers and disable them.
|
||||
*/
|
||||
rk29_uart_write(port, UART_FCR_FIFO_ENABLE, UART_FCR);
|
||||
rk29_uart_write(port, UART_FCR_FIFO_ENABLE |
|
||||
UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, UART_FCR);
|
||||
rk29_uart_write(port, 0, UART_FCR);
|
||||
|
||||
/*
|
||||
* Clear the interrupt registers.
|
||||
*/
|
||||
(void) rk29_uart_read(port, UART_LSR);
|
||||
(void) rk29_uart_read(port, UART_RBR);
|
||||
(void) rk29_uart_read(port, UART_IIR);
|
||||
(void) rk29_uart_read(port, UART_MSR);
|
||||
|
||||
/*
|
||||
* And clear the user registers.
|
||||
*/
|
||||
(void) rk29_uart_read(port, UART_USR);
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the port parameters
|
||||
*/
|
||||
static void rk29_serial_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
struct ktermios *old)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int mode, baud;
|
||||
unsigned int umcon,fcr;
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
/* Get current mode register */
|
||||
mode = rk29_uart_read(port,UART_LCR) & (BREAK_CONTROL_BIT | EVEN_PARITY_SELECT | PARITY_ENABLED
|
||||
| ONE_HALF_OR_TWO_BIT | UART_DATABIT_MASK);
|
||||
|
||||
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
|
||||
/* byte size */
|
||||
switch (termios->c_cflag & CSIZE) {
|
||||
case CS5:
|
||||
mode |= LCR_WLS_5;
|
||||
break;
|
||||
case CS6:
|
||||
mode |= LCR_WLS_6;
|
||||
break;
|
||||
case CS7:
|
||||
mode |= LCR_WLS_7;
|
||||
break;
|
||||
default:
|
||||
mode |= LCR_WLS_8;
|
||||
break;
|
||||
}
|
||||
|
||||
/* stop bits */
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
mode |= ONE_STOP_BIT;
|
||||
|
||||
/* parity */
|
||||
if (termios->c_cflag & PARENB)
|
||||
{
|
||||
mode |= PARITY_ENABLED;
|
||||
if (termios->c_cflag & PARODD)
|
||||
mode |= ODD_PARITY;
|
||||
else
|
||||
mode |= EVEN_PARITY;
|
||||
}
|
||||
|
||||
int timeout = 10000000;
|
||||
while(rk29_uart_read(port,UART_USR)&UART_USR_BUSY){
|
||||
if(timeout-- == 0){
|
||||
printk("rk29_serial_set_termios uart timeout,irq=%d,ret=0x%x\n",port->irq,rk29_uart_read(port,UART_USR));
|
||||
break;
|
||||
}
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
rk29_uart_write(port,mode,UART_LCR);
|
||||
baud = rk29_set_baud_rate(port, baud);
|
||||
uart_update_timeout(port, termios->c_cflag, baud);
|
||||
|
||||
/*
|
||||
* enable FIFO and interrupt
|
||||
*/
|
||||
if(termios->c_cflag & CRTSCTS)
|
||||
{
|
||||
/*开启uart0硬件流控*/
|
||||
printk("start CRTSCTS control and baudrate is %d,irq=%d\n",baud,port->irq);
|
||||
if(2 == port->line)
|
||||
{
|
||||
rk29_mux_api_set(GPIO2A7_UART2RTSN_NAME, GPIO2L_UART2_RTS_N);
|
||||
rk29_mux_api_set(GPIO2A6_UART2CTSN_NAME, GPIO2L_UART2_CTS_N);
|
||||
}
|
||||
else if(0 == port->line)
|
||||
{
|
||||
rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_UART0_RTS_N);
|
||||
rk29_mux_api_set(GPIO1C0_UART0CTSN_SDMMC1DETECTN_NAME, GPIO1H_UART0_CTS_N);
|
||||
}
|
||||
else if(3 == port->line)
|
||||
{
|
||||
rk29_mux_api_set(GPIO2B5_UART3RTSN_I2C3SCL_NAME, GPIO2L_UART3_RTS_N);
|
||||
rk29_mux_api_set(GPIO2B4_UART3CTSN_I2C3SDA_NAME, GPIO2L_UART3_CTS_N);
|
||||
}
|
||||
|
||||
umcon=rk29_uart_read(port,UART_MCR);
|
||||
umcon |= UART_MCR_AFCEN;
|
||||
umcon |= UART_MCR_URRTS;
|
||||
umcon &=~UART_SIR_ENABLE;
|
||||
rk29_uart_write(port,umcon,UART_MCR);
|
||||
printk("UART_GET_MCR umcon=0x%x\n",umcon);
|
||||
}
|
||||
mode = mode | LCR_DLA_EN;
|
||||
|
||||
#if 1
|
||||
//lw modify on 110309
|
||||
fcr = UART_FCR_FIFO_ENABLE | UART_FCR_R_TRIG_10 | UART_FCR_T_TRIG_10;
|
||||
rk29_uart_write(port, fcr, UART_FCR);
|
||||
rk29_uart_write(port,0x01,UART_SFE);
|
||||
rk29_uart_write(port,UART_IER_RECV_DATA_AVAIL_INT_ENABLE,UART_IER); //enable uart recevice IRQ
|
||||
printk("%s:fcr=0x%x,irq=%d\n",__FUNCTION__,fcr,port->irq);
|
||||
#endif
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void rk29_serial_release_port(struct uart_port *port)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(port->dev);
|
||||
struct resource *resource;
|
||||
resource_size_t size;
|
||||
|
||||
resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (unlikely(!resource))
|
||||
return;
|
||||
size = resource->end - resource->start + 1;
|
||||
|
||||
release_mem_region(port->mapbase, size);
|
||||
iounmap(port->membase);
|
||||
port->membase = NULL;
|
||||
}
|
||||
|
||||
static int rk29_serial_request_port(struct uart_port *port)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(port->dev);
|
||||
struct resource *resource;
|
||||
resource_size_t size;
|
||||
|
||||
resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (unlikely(!resource))
|
||||
return -ENXIO;
|
||||
size = resource->end - resource->start + 1;
|
||||
|
||||
if (unlikely(!request_mem_region(port->mapbase, size, "rk29_serial")))
|
||||
return -EBUSY;
|
||||
|
||||
port->membase = ioremap(port->mapbase, size);
|
||||
if (!port->membase) {
|
||||
release_mem_region(port->mapbase, size);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure/autoconfigure the port.
|
||||
*/
|
||||
static void rk29_serial_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
if (flags & UART_CONFIG_TYPE) {
|
||||
port->type = PORT_RK29;
|
||||
rk29_serial_request_port(port);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify the new serial_struct (for TIOCSSERIAL).
|
||||
*/
|
||||
static int rk29_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||
{
|
||||
int ret = 0;
|
||||
if (ser->type != PORT_UNKNOWN && ser->type != PORT_RK29)
|
||||
ret = -EINVAL;
|
||||
if (port->irq != ser->irq)
|
||||
ret = -EINVAL;
|
||||
if (ser->io_type != SERIAL_IO_MEM)
|
||||
ret = -EINVAL;
|
||||
if (port->uartclk / 16 != ser->baud_base)
|
||||
ret = -EINVAL;
|
||||
if ((void *)port->mapbase != ser->iomem_base)
|
||||
ret = -EINVAL;
|
||||
if (port->iobase != ser->port)
|
||||
ret = -EINVAL;
|
||||
if (ser->hub6 != 0)
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CONSOLE_POLL
|
||||
/*
|
||||
* Console polling routines for writing and reading from the uart while
|
||||
* in an interrupt or debug context.
|
||||
*/
|
||||
|
||||
static int rk29_serial_poll_get_char(struct uart_port *port)
|
||||
{
|
||||
while (!((rk29_uart_read(port, UART_USR) & UART_RECEIVE_FIFO_NOT_EMPTY) == UART_RECEIVE_FIFO_NOT_EMPTY))
|
||||
barrier();
|
||||
return rk29_uart_read(port, UART_RBR);
|
||||
}
|
||||
|
||||
static void rk29_serial_poll_put_char(struct uart_port *port, unsigned char c)
|
||||
{
|
||||
while (!(rk29_uart_read(port, UART_USR) & UART_TRANSMIT_FIFO_NOT_FULL))
|
||||
barrier();
|
||||
rk29_uart_write(port, c, UART_THR);
|
||||
}
|
||||
#endif /* CONFIG_CONSOLE_POLL */
|
||||
|
||||
static struct uart_ops rk29_uart_pops = {
|
||||
.tx_empty = rk29_serial_tx_empty,
|
||||
.set_mctrl = rk29_serial_set_mctrl,
|
||||
.get_mctrl = rk29_serial_get_mctrl,
|
||||
.stop_tx = rk29_serial_stop_tx,
|
||||
.start_tx = rk29_serial_start_tx,
|
||||
.stop_rx = rk29_serial_stop_rx,
|
||||
.enable_ms = rk29_serial_enable_ms,
|
||||
.break_ctl = rk29_serial_break_ctl,
|
||||
.startup = rk29_serial_startup,
|
||||
.shutdown = rk29_serial_shutdown,
|
||||
.set_termios = rk29_serial_set_termios,
|
||||
.type = rk29_serial_type,
|
||||
.release_port = rk29_serial_release_port,
|
||||
.request_port = rk29_serial_request_port,
|
||||
.config_port = rk29_serial_config_port,
|
||||
.verify_port = rk29_serial_verify_port,
|
||||
.pm = rk29_serial_pm,
|
||||
#ifdef CONFIG_CONSOLE_POLL
|
||||
.poll_get_char = rk29_serial_poll_get_char,
|
||||
.poll_put_char = rk29_serial_poll_put_char,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
static struct rk29_port rk29_uart_ports[] = {
|
||||
{
|
||||
.uart = {
|
||||
.iotype = UPIO_MEM,
|
||||
.ops = &rk29_uart_pops,
|
||||
.flags = UPF_BOOT_AUTOCONF,
|
||||
.fifosize = 32,
|
||||
.line = 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
.uart = {
|
||||
.iotype = UPIO_MEM,
|
||||
.ops = &rk29_uart_pops,
|
||||
.flags = UPF_BOOT_AUTOCONF,
|
||||
.fifosize = 32,
|
||||
.line = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
.uart = {
|
||||
.iotype = UPIO_MEM,
|
||||
.ops = &rk29_uart_pops,
|
||||
.flags = UPF_BOOT_AUTOCONF,
|
||||
.fifosize = 32,
|
||||
.line = 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
.uart = {
|
||||
.iotype = UPIO_MEM,
|
||||
.ops = &rk29_uart_pops,
|
||||
.flags = UPF_BOOT_AUTOCONF,
|
||||
.fifosize = 32,
|
||||
.line = 3,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
#define UART_NR ARRAY_SIZE(rk29_uart_ports)
|
||||
|
||||
static inline struct uart_port *get_port_from_line(unsigned int line)
|
||||
{
|
||||
return &rk29_uart_ports[line].uart;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_RK29_CONSOLE
|
||||
static void rk29_console_putchar(struct uart_port *port, int ch)
|
||||
{
|
||||
while (!(rk29_uart_read(port,UART_USR) & UART_TRANSMIT_FIFO_NOT_FULL))
|
||||
cpu_relax();
|
||||
rk29_uart_write(port,ch,UART_THR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupts are disabled on entering
|
||||
*/
|
||||
static void rk29_console_write(struct console *co, const char *s, u_int count)
|
||||
{
|
||||
struct uart_port *port;
|
||||
struct rk29_port *rk29_port;
|
||||
|
||||
BUG_ON(co->index < 0 || co->index >= UART_NR);
|
||||
|
||||
port = get_port_from_line(co->index);
|
||||
rk29_port = UART_TO_RK29(port);
|
||||
|
||||
spin_lock(&port->lock);
|
||||
uart_console_write(port, s, count, rk29_console_putchar);
|
||||
spin_unlock(&port->lock);
|
||||
}
|
||||
|
||||
static int __init rk29_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_port *port;
|
||||
int baud, flow, bits, parity;
|
||||
|
||||
if (unlikely(co->index >= UART_NR || co->index < 0))
|
||||
return -ENXIO;
|
||||
|
||||
port = get_port_from_line(co->index);
|
||||
|
||||
if (unlikely(!port->membase))
|
||||
return -ENXIO;
|
||||
|
||||
port->cons = co;
|
||||
|
||||
//rk29_init_clock(port);
|
||||
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
|
||||
bits = 8;
|
||||
parity = 'n';
|
||||
flow = 'n';
|
||||
rk29_uart_write(port,rk29_uart_read(port,UART_LCR) | LCR_WLS_8 | PARITY_DISABLED | ONE_STOP_BIT,UART_LCR); /* 8N1 */
|
||||
if (baud < 300 || baud > 115200)
|
||||
baud = 115200;
|
||||
rk29_set_baud_rate(port, baud);
|
||||
|
||||
printk(KERN_INFO "rk29_serial: console setup on port %d\n", port->line);
|
||||
|
||||
/* clear rx fifo, else will blocked on set_termios (always busy) */
|
||||
while ((rk29_uart_read(port, UART_USR) & UART_RECEIVE_FIFO_NOT_EMPTY) == UART_RECEIVE_FIFO_NOT_EMPTY)
|
||||
rk29_uart_read(port, UART_RBR);
|
||||
|
||||
return uart_set_options(port, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
static struct uart_driver rk29_uart_driver;
|
||||
|
||||
static struct console rk29_console = {
|
||||
.name = "ttyS",
|
||||
.write = rk29_console_write,
|
||||
.device = uart_console_device,
|
||||
.setup = rk29_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = 1,
|
||||
.data = &rk29_uart_driver,
|
||||
};
|
||||
|
||||
#define RK29_CONSOLE (&rk29_console)
|
||||
|
||||
#else
|
||||
#define RK29_CONSOLE NULL
|
||||
#endif
|
||||
|
||||
static struct uart_driver rk29_uart_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = "rk29_serial",
|
||||
.dev_name = "ttyS",
|
||||
.nr = UART_NR,
|
||||
.cons = RK29_CONSOLE,
|
||||
.major = RK29_SERIAL_MAJOR,
|
||||
.minor = RK29_SERIAL_MINOR,
|
||||
};
|
||||
|
||||
static int __devinit rk29_serial_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rk29_port *rk29_port;
|
||||
struct resource *resource;
|
||||
struct uart_port *port;
|
||||
//struct rk29_serial_platform_data *pdata = pdev->dev.platform_data;
|
||||
|
||||
if (unlikely(pdev->id < 0 || pdev->id >= UART_NR))
|
||||
return -ENXIO;
|
||||
|
||||
printk(KERN_INFO "rk29_serial: detected port %d\n", pdev->id);
|
||||
|
||||
//if (pdata && pdata->io_init)
|
||||
//pdata->io_init();
|
||||
|
||||
port = get_port_from_line(pdev->id);
|
||||
port->dev = &pdev->dev;
|
||||
rk29_port = UART_TO_RK29(port);
|
||||
|
||||
rk29_port->clk = clk_get(&pdev->dev, "uart");
|
||||
if (unlikely(IS_ERR(rk29_port->clk)))
|
||||
return PTR_ERR(rk29_port->clk);
|
||||
port->uartclk = 24000000; ///clk_get_rate(rk29_port->clk);
|
||||
|
||||
resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (unlikely(!resource))
|
||||
return -ENXIO;
|
||||
port->mapbase = resource->start;
|
||||
|
||||
port->irq = platform_get_irq(pdev, 0);
|
||||
if (unlikely(port->irq < 0))
|
||||
return -ENXIO;
|
||||
|
||||
platform_set_drvdata(pdev, port);
|
||||
|
||||
return uart_add_one_port(&rk29_uart_driver, port);
|
||||
}
|
||||
|
||||
static int __devexit rk29_serial_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rk29_port *rk29_port = platform_get_drvdata(pdev);
|
||||
|
||||
clk_put(rk29_port->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver rk29_platform_driver = {
|
||||
.remove = rk29_serial_remove,
|
||||
.driver = {
|
||||
.name = "rk29_serial",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init rk29_serial_init(void)
|
||||
{
|
||||
int ret;
|
||||
ret = uart_register_driver(&rk29_uart_driver);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
ret = platform_driver_probe(&rk29_platform_driver, rk29_serial_probe);
|
||||
if (unlikely(ret))
|
||||
uart_unregister_driver(&rk29_uart_driver);
|
||||
|
||||
printk(KERN_INFO "rk29_serial: driver initialized\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit rk29_serial_exit(void)
|
||||
{
|
||||
#ifdef CONFIG_SERIAL_RK29_CONSOLE
|
||||
unregister_console(&rk29_console);
|
||||
#endif
|
||||
platform_driver_unregister(&rk29_platform_driver);
|
||||
uart_unregister_driver(&rk29_uart_driver);
|
||||
}
|
||||
|
||||
/*
|
||||
* While this can be a module, if builtin it's most likely the console
|
||||
* So let's leave module_exit but move module_init to an earlier place
|
||||
*/
|
||||
arch_initcall(rk29_serial_init);
|
||||
module_exit(rk29_serial_exit);
|
||||
|
||||
MODULE_AUTHOR("lhh lhh@rock-chips.com");
|
||||
MODULE_DESCRIPTION("Rockchip rk29 Serial port driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
||||
|
|
@ -104,6 +104,9 @@ source "drivers/staging/iio/Kconfig"
|
|||
|
||||
source "drivers/staging/cs5535_gpio/Kconfig"
|
||||
|
||||
source "drivers/staging/rk29/vivante/Kconfig"
|
||||
source "drivers/staging/rk29/ipp/Kconfig"
|
||||
|
||||
source "drivers/staging/zram/Kconfig"
|
||||
|
||||
source "drivers/staging/zcache/Kconfig"
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ obj-$(CONFIG_VME_BUS) += vme/
|
|||
obj-$(CONFIG_DX_SEP) += sep/
|
||||
obj-$(CONFIG_IIO) += iio/
|
||||
obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio/
|
||||
obj-$(CONFIG_VIVANTE) += rk29/vivante/
|
||||
obj-$(CONFIG_RK29_IPP) += rk29/ipp/
|
||||
obj-$(CONFIG_ZRAM) += zram/
|
||||
obj-$(CONFIG_XVMALLOC) += zram/
|
||||
obj-$(CONFIG_ZCACHE) += zcache/
|
||||
|
|
|
|||
|
|
@ -20,10 +20,12 @@
|
|||
#include <linux/hrtimer.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <linux/wakelock.h>
|
||||
#include <linux/delay.h>
|
||||
#include "timed_output.h"
|
||||
#include "timed_gpio.h"
|
||||
|
||||
#define GPIO_TYPE 0
|
||||
|
||||
struct timed_gpio_data {
|
||||
struct timed_output_dev dev;
|
||||
|
|
@ -32,14 +34,40 @@ struct timed_gpio_data {
|
|||
unsigned gpio;
|
||||
int max_timeout;
|
||||
u8 active_low;
|
||||
int adjust_time;
|
||||
#if (GPIO_TYPE == 1)
|
||||
struct work_struct timed_gpio_work;
|
||||
#endif
|
||||
struct wake_lock irq_wake;
|
||||
};
|
||||
|
||||
#if (GPIO_TYPE == 1)
|
||||
static void timed_gpio_work_handler(struct work_struct *work)
|
||||
{
|
||||
struct timed_gpio_data *data =
|
||||
container_of(work, struct timed_gpio_data, timed_gpio_work);
|
||||
int ret = 0,i = 0;
|
||||
//set gpio several times once error happened
|
||||
for(i=0; i<3; i++)
|
||||
{
|
||||
ret = gpio_direction_output(data->gpio, data->active_low ? 1 : 0);
|
||||
if(!ret)
|
||||
break;
|
||||
printk("%s:ret=%d,fail to set gpio and set again,i=%d\n",__FUNCTION__,ret,i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static enum hrtimer_restart gpio_timer_func(struct hrtimer *timer)
|
||||
{
|
||||
struct timed_gpio_data *data =
|
||||
container_of(timer, struct timed_gpio_data, timer);
|
||||
|
||||
|
||||
#if (GPIO_TYPE == 0)
|
||||
gpio_direction_output(data->gpio, data->active_low ? 1 : 0);
|
||||
#else
|
||||
schedule_work(&data->timed_gpio_work);
|
||||
#endif
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
|
|
@ -60,24 +88,26 @@ static void gpio_enable(struct timed_output_dev *dev, int value)
|
|||
{
|
||||
struct timed_gpio_data *data =
|
||||
container_of(dev, struct timed_gpio_data, dev);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&data->lock, flags);
|
||||
int ret = 0,i = 0;
|
||||
|
||||
/* cancel previous timer and set GPIO according to value */
|
||||
hrtimer_cancel(&data->timer);
|
||||
gpio_direction_output(data->gpio, data->active_low ? !value : !!value);
|
||||
|
||||
//set gpio several times once error happened
|
||||
for(i=0; i<3; i++)
|
||||
{
|
||||
ret = gpio_direction_output(data->gpio, data->active_low ? !value : !!value);
|
||||
if(!ret)
|
||||
break;
|
||||
printk("%s:ret=%d,fail to set gpio and set again,i=%d\n",__FUNCTION__,ret,i);
|
||||
}
|
||||
if (value > 0) {
|
||||
value += data->adjust_time;
|
||||
if (value > data->max_timeout)
|
||||
value = data->max_timeout;
|
||||
|
||||
hrtimer_start(&data->timer,
|
||||
ktime_set(value / 1000, (value % 1000) * 1000000),
|
||||
HRTIMER_MODE_REL);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&data->lock, flags);
|
||||
}
|
||||
|
||||
static int timed_gpio_probe(struct platform_device *pdev)
|
||||
|
|
@ -125,10 +155,17 @@ static int timed_gpio_probe(struct platform_device *pdev)
|
|||
gpio_dat->gpio = cur_gpio->gpio;
|
||||
gpio_dat->max_timeout = cur_gpio->max_timeout;
|
||||
gpio_dat->active_low = cur_gpio->active_low;
|
||||
gpio_dat->adjust_time = cur_gpio->adjust_time;
|
||||
gpio_direction_output(gpio_dat->gpio, gpio_dat->active_low);
|
||||
}
|
||||
|
||||
#if (GPIO_TYPE == 1)
|
||||
INIT_WORK(&gpio_dat->timed_gpio_work, timed_gpio_work_handler);
|
||||
#endif
|
||||
platform_set_drvdata(pdev, gpio_data);
|
||||
wake_lock_init(&gpio_data->irq_wake, WAKE_LOCK_SUSPEND, "timed_gpio_wake");
|
||||
|
||||
gpio_enable(&gpio_data ->dev, 100);
|
||||
printk("%s\n",__FUNCTION__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -168,7 +205,7 @@ static void __exit timed_gpio_exit(void)
|
|||
platform_driver_unregister(&timed_gpio_driver);
|
||||
}
|
||||
|
||||
module_init(timed_gpio_init);
|
||||
subsys_initcall(timed_gpio_init);
|
||||
module_exit(timed_gpio_exit);
|
||||
|
||||
MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ struct timed_gpio {
|
|||
unsigned gpio;
|
||||
int max_timeout;
|
||||
u8 active_low;
|
||||
int adjust_time;
|
||||
};
|
||||
|
||||
struct timed_gpio_platform_data {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ static gceSTATUS _lastError = gcvSTATUS_OK;
|
|||
static gctUINT32 _debugLevel = gcvLEVEL_ERROR;
|
||||
static gctUINT32 _debugZones = gcvZONE_NONE;
|
||||
static gctINT _indent = 0;
|
||||
static spinlock_t _lock = SPIN_LOCK_UNLOCKED;
|
||||
static DEFINE_SPINLOCK(_lock);
|
||||
|
||||
static void
|
||||
OutputDebugString(
|
||||
|
|
|
|||
|
|
@ -2443,7 +2443,7 @@ gceSTATUS gckOS_CreateMutex(
|
|||
}
|
||||
|
||||
/* Initialize the semaphore.. Come up in unlocked state. */
|
||||
init_MUTEX(*Mutex);
|
||||
sema_init(*Mutex, 1);
|
||||
|
||||
/* Return status. */
|
||||
return gcvSTATUS_OK;
|
||||
|
|
|
|||
|
|
@ -1512,6 +1512,63 @@ config SERIAL_BCM63XX_CONSOLE
|
|||
If you have enabled the serial port on the bcm63xx CPU
|
||||
you can make it the console by answering Y to this option.
|
||||
|
||||
config SERIAL_RK29
|
||||
bool "RockChip rk29 serial port support"
|
||||
depends on ARM && ARCH_RK29
|
||||
select SERIAL_CORE
|
||||
|
||||
config UART0_RK29
|
||||
bool "RockChip rk29 serial port 0 support"
|
||||
depends on SERIAL_RK29
|
||||
|
||||
config UART0_CTS_RTS_RK29
|
||||
bool "RockChip rk29 serial port 0 CTS/RTS support"
|
||||
depends on UART0_RK29
|
||||
|
||||
config UART0_DMA_RK29
|
||||
bool "RockChip rk29 serial port 0 DMA support (EXPERIMENTAL)"
|
||||
depends on UART0_RK29
|
||||
|
||||
config UART1_RK29
|
||||
bool "RockChip rk29 serial port 1 support"
|
||||
depends on SERIAL_RK29
|
||||
|
||||
config UART2_RK29
|
||||
bool "RockChip rk29 serial port 2 support"
|
||||
depends on SERIAL_RK29
|
||||
|
||||
config UART2_CTS_RTS_RK29
|
||||
bool "RockChip rk29 serial port 2 CTS/RTS support"
|
||||
depends on UART2_RK29
|
||||
|
||||
config UART2_DMA_RK29
|
||||
bool "RockChip rk29 serial port 2 DMA support (EXPERIMENTAL)"
|
||||
depends on UART2_RK29
|
||||
|
||||
config UART3_RK29
|
||||
bool "RockChip rk29 serial port 3 support"
|
||||
depends on SERIAL_RK29
|
||||
|
||||
config UART3_CTS_RTS_RK29
|
||||
bool "RockChip rk29 serial port 3 CTS/RTS support"
|
||||
depends on UART3_RK29
|
||||
|
||||
config UART3_DMA_RK29
|
||||
bool "RockChip rk29 serial port 3 DMA support (EXPERIMENTAL)"
|
||||
depends on UART3_RK29
|
||||
|
||||
config SERIAL_RK29_CONSOLE
|
||||
bool "Rockchip rk29 serial console support"
|
||||
depends on SERIAL_RK29=y
|
||||
select SERIAL_CORE_CONSOLE
|
||||
|
||||
config SERIAL_SC8800
|
||||
tristate "SC8800 support"
|
||||
depends on SPI
|
||||
select SERIAL_CORE
|
||||
help
|
||||
SC8800 spi-serial support
|
||||
|
||||
config SERIAL_GRLIB_GAISLER_APBUART
|
||||
tristate "GRLIB APBUART serial support"
|
||||
depends on OF && SPARC
|
||||
|
|
|
|||
|
|
@ -83,6 +83,8 @@ obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
|
|||
obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
|
||||
obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
|
||||
obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
|
||||
obj-$(CONFIG_SERIAL_RK29) += rk_serial.o
|
||||
obj-$(CONFIG_SERIAL_SC8800) += sc8800.o
|
||||
obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o
|
||||
obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o
|
||||
obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue