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:
黄涛 2011-11-04 17:43:18 +08:00
commit 1bcabbad76
140 changed files with 9469 additions and 5111 deletions

2
.gitignore vendored
View file

@ -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

View file

@ -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

View file

@ -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}

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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>

View file

@ -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[] = {

View file

@ -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

View file

@ -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;

View file

@ -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>

View file

@ -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

View file

@ -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>

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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/

View file

@ -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);

View file

@ -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)

View file

@ -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

View file

@ -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
View 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

View file

@ -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);

View file

@ -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];

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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>");

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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");

View file

@ -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");

View file

@ -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], &reg, 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);

View file

@ -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);

View file

@ -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
View file

21
drivers/misc/Kconfig Executable file → Normal file
View 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
View 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

View file

@ -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

View file

@ -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, &region,
sizeof(struct pmem_region)))
return -EFAULT;

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -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.

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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/

View file

@ -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
View 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 \

View file

@ -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 */

View file

@ -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)

File diff suppressed because it is too large Load diff

View file

@ -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_ */

View file

@ -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);

View file

@ -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));
}

View file

@ -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
}

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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, &param27);
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;

View file

@ -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

View file

@ -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, &reg2,
"charger timeout", "min");
wm831x_battey_apply_config(wm831x, chg_syslos, ARRAY_SIZE(chg_syslos),
pdata->syslo, &reg3,
"syslo voltage", "mV");
wm831x_battey_apply_config(wm831x, chg_sysoks, ARRAY_SIZE(chg_sysoks),
pdata->sysok, &reg3,
"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");

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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"
}

View file

@ -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:

View file

@ -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");

View file

@ -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");

View file

@ -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"

View file

@ -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/

View file

@ -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>");

View file

@ -23,6 +23,7 @@ struct timed_gpio {
unsigned gpio;
int max_timeout;
u8 active_low;
int adjust_time;
};
struct timed_gpio_platform_data {

View file

@ -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(

View file

@ -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;

View file

@ -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

View file

@ -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