diff --git a/[refs] b/[refs] index a8cb627f214f..ee03529e5615 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5bf68592e72eb0ded154efaaf43b39aab6964fc3 +refs/heads/master: 050afc92ee394ccdd953f91dcbbf9af863af8efc diff --git a/trunk/arch/arm/mach-shmobile/Kconfig b/trunk/arch/arm/mach-shmobile/Kconfig index 54b479c35ee0..51dcd59eda6a 100644 --- a/trunk/arch/arm/mach-shmobile/Kconfig +++ b/trunk/arch/arm/mach-shmobile/Kconfig @@ -116,4 +116,6 @@ endmenu config SH_CLK_CPG bool +source "drivers/sh/Kconfig" + endif diff --git a/trunk/arch/arm/mach-shmobile/board-ap4evb.c b/trunk/arch/arm/mach-shmobile/board-ap4evb.c index 46ca4d4abf91..32d9e2816e56 100644 --- a/trunk/arch/arm/mach-shmobile/board-ap4evb.c +++ b/trunk/arch/arm/mach-shmobile/board-ap4evb.c @@ -565,12 +565,50 @@ static struct platform_device *qhd_devices[] __initdata = { /* FSI */ #define IRQ_FSI evt2irq(0x1840) + +static int fsi_set_rate(int is_porta, int rate) +{ + struct clk *fsib_clk; + struct clk *fdiv_clk = &sh7372_fsidivb_clk; + int ret; + + /* set_rate is not needed if port A */ + if (is_porta) + return 0; + + fsib_clk = clk_get(NULL, "fsib_clk"); + if (IS_ERR(fsib_clk)) + return -EINVAL; + + switch (rate) { + case 48000: + clk_set_rate(fsib_clk, clk_round_rate(fsib_clk, 85428000)); + clk_set_rate(fdiv_clk, clk_round_rate(fdiv_clk, 12204000)); + ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; + break; + default: + pr_err("unsupported rate in FSI2 port B\n"); + ret = -EINVAL; + break; + } + + clk_put(fsib_clk); + + return ret; +} + static struct sh_fsi_platform_info fsi_info = { .porta_flags = SH_FSI_BRS_INV | SH_FSI_OUT_SLAVE_MODE | SH_FSI_IN_SLAVE_MODE | SH_FSI_OFMT(PCM) | SH_FSI_IFMT(PCM), + + .portb_flags = SH_FSI_BRS_INV | + SH_FSI_BRM_INV | + SH_FSI_LRS_INV | + SH_FSI_OFMT(SPDIF), + .set_rate = fsi_set_rate, }; static struct resource fsi_resources[] = { @@ -634,6 +672,7 @@ static struct platform_device lcdc1_device = { static struct sh_mobile_hdmi_info hdmi_info = { .lcd_chan = &sh_mobile_lcdc1_info.ch[0], .lcd_dev = &lcdc1_device.dev, + .flags = HDMI_SND_SRC_SPDIF, }; static struct resource hdmi_resources[] = { @@ -992,6 +1031,7 @@ static void __init ap4evb_map_io(void) #define GPIO_PORT9CR 0xE6051009 #define GPIO_PORT10CR 0xE605100A +#define USCCR1 0xE6058144 static void __init ap4evb_init(void) { u32 srcr4; @@ -1062,7 +1102,7 @@ static void __init ap4evb_init(void) /* setup USB phy */ __raw_writew(0x8a0a, 0xE6058130); /* USBCR2 */ - /* enable FSI2 */ + /* enable FSI2 port A (ak4643) */ gpio_request(GPIO_FN_FSIAIBT, NULL); gpio_request(GPIO_FN_FSIAILR, NULL); gpio_request(GPIO_FN_FSIAISLD, NULL); @@ -1079,6 +1119,10 @@ static void __init ap4evb_init(void) gpio_request(GPIO_PORT41, NULL); gpio_direction_input(GPIO_PORT41); + /* setup FSI2 port B (HDMI) */ + gpio_request(GPIO_FN_FSIBCK, NULL); + __raw_writew(__raw_readw(USCCR1) & ~(1 << 6), USCCR1); /* use SPDIF */ + /* set SPU2 clock to 119.6 MHz */ clk = clk_get(NULL, "spu_clk"); if (!IS_ERR(clk)) { diff --git a/trunk/arch/arm/mach-shmobile/clock-sh7372.c b/trunk/arch/arm/mach-shmobile/clock-sh7372.c index 8565aefa21fd..7db31e6c6bf2 100644 --- a/trunk/arch/arm/mach-shmobile/clock-sh7372.c +++ b/trunk/arch/arm/mach-shmobile/clock-sh7372.c @@ -50,6 +50,9 @@ #define SMSTPCR3 0xe615013c #define SMSTPCR4 0xe6150140 +#define FSIDIVA 0xFE1F8000 +#define FSIDIVB 0xFE1F8008 + /* Platforms must set frequency on their DV_CLKI pin */ struct clk sh7372_dv_clki_clk = { }; @@ -288,6 +291,7 @@ struct clk sh7372_pllc2_clk = { .ops = &pllc2_clk_ops, .parent = &extal1_div2_clk, .freq_table = pllc2_freq_table, + .nr_freqs = ARRAY_SIZE(pllc2_freq_table) - 1, .parent_table = pllc2_parent, .parent_num = ARRAY_SIZE(pllc2_parent), }; @@ -417,6 +421,101 @@ static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { fsibckcr_parent, ARRAY_SIZE(fsibckcr_parent), 6, 2), }; +/* FSI DIV */ +static unsigned long fsidiv_recalc(struct clk *clk) +{ + unsigned long value; + + value = __raw_readl(clk->mapping->base); + + if ((value & 0x3) != 0x3) + return 0; + + value >>= 16; + if (value < 2) + return 0; + + return clk->parent->rate / value; +} + +static long fsidiv_round_rate(struct clk *clk, unsigned long rate) +{ + return clk_rate_div_range_round(clk, 2, 0xffff, rate); +} + +static void fsidiv_disable(struct clk *clk) +{ + __raw_writel(0, clk->mapping->base); +} + +static int fsidiv_enable(struct clk *clk) +{ + unsigned long value; + + value = __raw_readl(clk->mapping->base) >> 16; + if (value < 2) { + fsidiv_disable(clk); + return -ENOENT; + } + + __raw_writel((value << 16) | 0x3, clk->mapping->base); + + return 0; +} + +static int fsidiv_set_rate(struct clk *clk, + unsigned long rate, int algo_id) +{ + int idx; + + if (clk->parent->rate == rate) { + fsidiv_disable(clk); + return 0; + } + + idx = (clk->parent->rate / rate) & 0xffff; + if (idx < 2) + return -ENOENT; + + __raw_writel(idx << 16, clk->mapping->base); + return fsidiv_enable(clk); +} + +static struct clk_ops fsidiv_clk_ops = { + .recalc = fsidiv_recalc, + .round_rate = fsidiv_round_rate, + .set_rate = fsidiv_set_rate, + .enable = fsidiv_enable, + .disable = fsidiv_disable, +}; + +static struct clk_mapping sh7372_fsidiva_clk_mapping = { + .phys = FSIDIVA, + .len = 8, +}; + +struct clk sh7372_fsidiva_clk = { + .ops = &fsidiv_clk_ops, + .parent = &div6_reparent_clks[DIV6_FSIA], /* late install */ + .mapping = &sh7372_fsidiva_clk_mapping, +}; + +static struct clk_mapping sh7372_fsidivb_clk_mapping = { + .phys = FSIDIVB, + .len = 8, +}; + +struct clk sh7372_fsidivb_clk = { + .ops = &fsidiv_clk_ops, + .parent = &div6_reparent_clks[DIV6_FSIB], /* late install */ + .mapping = &sh7372_fsidivb_clk_mapping, +}; + +static struct clk *late_main_clks[] = { + &sh7372_fsidiva_clk, + &sh7372_fsidivb_clk, +}; + enum { MSTP001, MSTP131, MSTP130, MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, @@ -585,6 +684,9 @@ void __init sh7372_clock_init(void) if (!ret) ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); + for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++) + ret = clk_register(late_main_clks[k]); + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); if (!ret) diff --git a/trunk/arch/arm/mach-shmobile/include/mach/gpio.h b/trunk/arch/arm/mach-shmobile/include/mach/gpio.h index 5bc6bd444d72..2b1bb9e43dda 100644 --- a/trunk/arch/arm/mach-shmobile/include/mach/gpio.h +++ b/trunk/arch/arm/mach-shmobile/include/mach/gpio.h @@ -35,12 +35,12 @@ static inline int gpio_cansleep(unsigned gpio) static inline int gpio_to_irq(unsigned gpio) { - return -ENOSYS; + return __gpio_to_irq(gpio); } static inline int irq_to_gpio(unsigned int irq) { - return -EINVAL; + return -ENOSYS; } #endif /* CONFIG_GPIOLIB */ diff --git a/trunk/arch/arm/mach-shmobile/include/mach/sh7372.h b/trunk/arch/arm/mach-shmobile/include/mach/sh7372.h index 147775a94bce..e4f9004e7103 100644 --- a/trunk/arch/arm/mach-shmobile/include/mach/sh7372.h +++ b/trunk/arch/arm/mach-shmobile/include/mach/sh7372.h @@ -464,5 +464,7 @@ extern struct clk sh7372_dv_clki_div2_clk; extern struct clk sh7372_pllc2_clk; extern struct clk sh7372_fsiack_clk; extern struct clk sh7372_fsibck_clk; +extern struct clk sh7372_fsidiva_clk; +extern struct clk sh7372_fsidivb_clk; #endif /* __ASM_SH7372_H__ */ diff --git a/trunk/arch/m68k/include/asm/irqflags.h b/trunk/arch/m68k/include/asm/irqflags.h index 4a5b284a1550..7ef4115b8c4a 100644 --- a/trunk/arch/m68k/include/asm/irqflags.h +++ b/trunk/arch/m68k/include/asm/irqflags.h @@ -2,7 +2,9 @@ #define _M68K_IRQFLAGS_H #include +#ifdef CONFIG_MMU #include +#endif #include #include #include diff --git a/trunk/arch/m68k/include/asm/machdep.h b/trunk/arch/m68k/include/asm/machdep.h index 789f3b2de0e9..415d5484916c 100644 --- a/trunk/arch/m68k/include/asm/machdep.h +++ b/trunk/arch/m68k/include/asm/machdep.h @@ -40,5 +40,6 @@ extern unsigned long hw_timer_offset(void); extern irqreturn_t arch_timer_interrupt(int irq, void *dummy); extern void config_BSP(char *command, int len); +extern void do_IRQ(int irq, struct pt_regs *fp); #endif /* _M68K_MACHDEP_H */ diff --git a/trunk/arch/powerpc/kernel/kvm.c b/trunk/arch/powerpc/kernel/kvm.c index 428d0e538aec..b06bdae04064 100644 --- a/trunk/arch/powerpc/kernel/kvm.c +++ b/trunk/arch/powerpc/kernel/kvm.c @@ -127,7 +127,7 @@ static void kvm_patch_ins_nop(u32 *inst) static void kvm_patch_ins_b(u32 *inst, int addr) { -#ifdef CONFIG_RELOCATABLE +#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_PPC_BOOK3S) /* On relocatable kernels interrupts handlers and our code can be in different regions, so we don't patch them */ diff --git a/trunk/arch/powerpc/kvm/booke_interrupts.S b/trunk/arch/powerpc/kvm/booke_interrupts.S index 049846911ce4..1cc471faac2d 100644 --- a/trunk/arch/powerpc/kvm/booke_interrupts.S +++ b/trunk/arch/powerpc/kvm/booke_interrupts.S @@ -416,7 +416,7 @@ lightweight_exit: lwz r3, VCPU_PC(r4) mtsrr0 r3 lwz r3, VCPU_SHARED(r4) - lwz r3, VCPU_SHARED_MSR(r3) + lwz r3, (VCPU_SHARED_MSR + 4)(r3) oris r3, r3, KVMPPC_MSR_MASK@h ori r3, r3, KVMPPC_MSR_MASK@l mtsrr1 r3 diff --git a/trunk/arch/powerpc/kvm/e500.c b/trunk/arch/powerpc/kvm/e500.c index 71750f2dd5d3..e3768ee9b595 100644 --- a/trunk/arch/powerpc/kvm/e500.c +++ b/trunk/arch/powerpc/kvm/e500.c @@ -138,8 +138,8 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); free_page((unsigned long)vcpu->arch.shared); - kvmppc_e500_tlb_uninit(vcpu_e500); kvm_vcpu_uninit(vcpu); + kvmppc_e500_tlb_uninit(vcpu_e500); kmem_cache_free(kvm_vcpu_cache, vcpu_e500); } diff --git a/trunk/arch/powerpc/kvm/powerpc.c b/trunk/arch/powerpc/kvm/powerpc.c index 2f87a1627f6c..38f756f25053 100644 --- a/trunk/arch/powerpc/kvm/powerpc.c +++ b/trunk/arch/powerpc/kvm/powerpc.c @@ -617,6 +617,7 @@ long kvm_arch_vm_ioctl(struct file *filp, switch (ioctl) { case KVM_PPC_GET_PVINFO: { struct kvm_ppc_pvinfo pvinfo; + memset(&pvinfo, 0, sizeof(pvinfo)); r = kvm_vm_ioctl_get_pvinfo(&pvinfo); if (copy_to_user(argp, &pvinfo, sizeof(pvinfo))) { r = -EFAULT; diff --git a/trunk/arch/powerpc/kvm/timing.c b/trunk/arch/powerpc/kvm/timing.c index 46fa04f12a9b..a021f5827a33 100644 --- a/trunk/arch/powerpc/kvm/timing.c +++ b/trunk/arch/powerpc/kvm/timing.c @@ -35,7 +35,6 @@ void kvmppc_init_timing_stats(struct kvm_vcpu *vcpu) int i; /* pause guest execution to avoid concurrent updates */ - local_irq_disable(); mutex_lock(&vcpu->mutex); vcpu->arch.last_exit_type = 0xDEAD; @@ -51,7 +50,6 @@ void kvmppc_init_timing_stats(struct kvm_vcpu *vcpu) vcpu->arch.timing_last_enter.tv64 = 0; mutex_unlock(&vcpu->mutex); - local_irq_enable(); } static void add_exit_timing(struct kvm_vcpu *vcpu, u64 duration, int type) diff --git a/trunk/arch/sh/Kconfig b/trunk/arch/sh/Kconfig index 5c075f562eba..7f217b3a50a8 100644 --- a/trunk/arch/sh/Kconfig +++ b/trunk/arch/sh/Kconfig @@ -193,6 +193,7 @@ config CPU_SH2 config CPU_SH2A bool select CPU_SH2 + select UNCACHED_MAPPING config CPU_SH3 bool diff --git a/trunk/arch/sh/Makefile b/trunk/arch/sh/Makefile index 307b3a4a790b..9c8c6e1a2a15 100644 --- a/trunk/arch/sh/Makefile +++ b/trunk/arch/sh/Makefile @@ -133,10 +133,7 @@ machdir-$(CONFIG_SOLUTION_ENGINE) += mach-se machdir-$(CONFIG_SH_HP6XX) += mach-hp6xx machdir-$(CONFIG_SH_DREAMCAST) += mach-dreamcast machdir-$(CONFIG_SH_SH03) += mach-sh03 -machdir-$(CONFIG_SH_SECUREEDGE5410) += mach-snapgear machdir-$(CONFIG_SH_RTS7751R2D) += mach-r2d -machdir-$(CONFIG_SH_7751_SYSTEMH) += mach-systemh -machdir-$(CONFIG_SH_EDOSK7705) += mach-edosk7705 machdir-$(CONFIG_SH_HIGHLANDER) += mach-highlander machdir-$(CONFIG_SH_MIGOR) += mach-migor machdir-$(CONFIG_SH_AP325RXA) += mach-ap325rxa diff --git a/trunk/arch/sh/boards/Kconfig b/trunk/arch/sh/boards/Kconfig index 9c94711aa6ca..2018c7ea4c93 100644 --- a/trunk/arch/sh/boards/Kconfig +++ b/trunk/arch/sh/boards/Kconfig @@ -81,13 +81,6 @@ config SH_7343_SOLUTION_ENGINE Select 7343 SolutionEngine if configuring for a Hitachi SH7343 (SH-Mobile 3AS) evaluation board. -config SH_7751_SYSTEMH - bool "SystemH7751R" - depends on CPU_SUBTYPE_SH7751R - help - Select SystemH if you are configuring for a Renesas SystemH - 7751R evaluation board. - config SH_HP6XX bool "HP6XX" select SYS_SUPPORTS_APM_EMULATION diff --git a/trunk/arch/sh/boards/Makefile b/trunk/arch/sh/boards/Makefile index 38ef655cc0f0..be7d11d04b26 100644 --- a/trunk/arch/sh/boards/Makefile +++ b/trunk/arch/sh/boards/Makefile @@ -2,10 +2,12 @@ # Specific board support, not covered by a mach group. # obj-$(CONFIG_SH_MAGIC_PANEL_R2) += board-magicpanelr2.o +obj-$(CONFIG_SH_SECUREEDGE5410) += board-secureedge5410.o obj-$(CONFIG_SH_SH2007) += board-sh2007.o obj-$(CONFIG_SH_SH7785LCR) += board-sh7785lcr.o obj-$(CONFIG_SH_URQUELL) += board-urquell.o obj-$(CONFIG_SH_SHMIN) += board-shmin.o +obj-$(CONFIG_SH_EDOSK7705) += board-edosk7705.o obj-$(CONFIG_SH_EDOSK7760) += board-edosk7760.o obj-$(CONFIG_SH_ESPT) += board-espt.o obj-$(CONFIG_SH_POLARIS) += board-polaris.o diff --git a/trunk/arch/sh/boards/board-edosk7705.c b/trunk/arch/sh/boards/board-edosk7705.c new file mode 100644 index 000000000000..4cb3bb74c36f --- /dev/null +++ b/trunk/arch/sh/boards/board-edosk7705.c @@ -0,0 +1,78 @@ +/* + * arch/sh/boards/renesas/edosk7705/setup.c + * + * Copyright (C) 2000 Kazumoto Kojima + * + * Hitachi SolutionEngine Support. + * + * Modified for edosk7705 development + * board by S. Dunn, 2003. + */ +#include +#include +#include +#include +#include +#include +#include + +#define SMC_IOBASE 0xA2000000 +#define SMC_IO_OFFSET 0x300 +#define SMC_IOADDR (SMC_IOBASE + SMC_IO_OFFSET) + +#define ETHERNET_IRQ 0x09 + +static void __init sh_edosk7705_init_irq(void) +{ + make_imask_irq(ETHERNET_IRQ); +} + +/* eth initialization functions */ +static struct smc91x_platdata smc91x_info = { + .flags = SMC91X_USE_16BIT | SMC91X_IO_SHIFT_1 | IORESOURCE_IRQ_LOWLEVEL, +}; + +static struct resource smc91x_res[] = { + [0] = { + .start = SMC_IOADDR, + .end = SMC_IOADDR + SZ_32 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = ETHERNET_IRQ, + .end = ETHERNET_IRQ, + .flags = IORESOURCE_IRQ , + } +}; + +static struct platform_device smc91x_dev = { + .name = "smc91x", + .id = -1, + .num_resources = ARRAY_SIZE(smc91x_res), + .resource = smc91x_res, + + .dev = { + .platform_data = &smc91x_info, + }, +}; + +/* platform init code */ +static struct platform_device *edosk7705_devices[] __initdata = { + &smc91x_dev, +}; + +static int __init init_edosk7705_devices(void) +{ + return platform_add_devices(edosk7705_devices, + ARRAY_SIZE(edosk7705_devices)); +} +__initcall(init_edosk7705_devices); + +/* + * The Machine Vector + */ +static struct sh_machine_vector mv_edosk7705 __initmv = { + .mv_name = "EDOSK7705", + .mv_nr_irqs = 80, + .mv_init_irq = sh_edosk7705_init_irq, +}; diff --git a/trunk/arch/sh/boards/mach-snapgear/setup.c b/trunk/arch/sh/boards/board-secureedge5410.c similarity index 70% rename from trunk/arch/sh/boards/mach-snapgear/setup.c rename to trunk/arch/sh/boards/board-secureedge5410.c index 331745dee379..32f875e8493d 100644 --- a/trunk/arch/sh/boards/mach-snapgear/setup.c +++ b/trunk/arch/sh/boards/board-secureedge5410.c @@ -1,6 +1,4 @@ /* - * linux/arch/sh/boards/snapgear/setup.c - * * Copyright (C) 2002 David McCullough * Copyright (C) 2003 Paul Mundt * @@ -19,18 +17,19 @@ #include #include #include -#include +#include #include #include #include +unsigned short secureedge5410_ioport; + /* * EraseConfig handling functions */ - static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id) { - (void)__raw_readb(0xb8000000); /* dummy read */ + ctrl_delay(); /* dummy read */ printk("SnapGear: erase switch interrupt!\n"); @@ -39,21 +38,22 @@ static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id) static int __init eraseconfig_init(void) { + unsigned int irq = evt2irq(0x240); + printk("SnapGear: EraseConfig init\n"); + /* Setup "EraseConfig" switch on external IRQ 0 */ - if (request_irq(IRL0_IRQ, eraseconfig_interrupt, IRQF_DISABLED, + if (request_irq(irq, eraseconfig_interrupt, IRQF_DISABLED, "Erase Config", NULL)) printk("SnapGear: failed to register IRQ%d for Reset witch\n", - IRL0_IRQ); + irq); else printk("SnapGear: registered EraseConfig switch on IRQ%d\n", - IRL0_IRQ); - return(0); + irq); + return 0; } - module_init(eraseconfig_init); -/****************************************************************************/ /* * Initialize IRQ setting * @@ -62,7 +62,6 @@ module_init(eraseconfig_init); * IRL2 = eth1 * IRL3 = crypto */ - static void __init init_snapgear_IRQ(void) { printk("Setup SnapGear IRQ/IPR ...\n"); @@ -76,20 +75,5 @@ static void __init init_snapgear_IRQ(void) static struct sh_machine_vector mv_snapgear __initmv = { .mv_name = "SnapGear SecureEdge5410", .mv_nr_irqs = 72, - - .mv_inb = snapgear_inb, - .mv_inw = snapgear_inw, - .mv_inl = snapgear_inl, - .mv_outb = snapgear_outb, - .mv_outw = snapgear_outw, - .mv_outl = snapgear_outl, - - .mv_inb_p = snapgear_inb_p, - .mv_inw_p = snapgear_inw, - .mv_inl_p = snapgear_inl, - .mv_outb_p = snapgear_outb_p, - .mv_outw_p = snapgear_outw, - .mv_outl_p = snapgear_outl, - .mv_init_irq = init_snapgear_IRQ, }; diff --git a/trunk/arch/sh/boards/mach-edosk7705/Makefile b/trunk/arch/sh/boards/mach-edosk7705/Makefile deleted file mode 100644 index cd54acb51499..000000000000 --- a/trunk/arch/sh/boards/mach-edosk7705/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the EDOSK7705 specific parts of the kernel -# - -obj-y := setup.o io.o diff --git a/trunk/arch/sh/boards/mach-edosk7705/io.c b/trunk/arch/sh/boards/mach-edosk7705/io.c deleted file mode 100644 index 5b9c57c43241..000000000000 --- a/trunk/arch/sh/boards/mach-edosk7705/io.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * arch/sh/boards/renesas/edosk7705/io.c - * - * Copyright (C) 2001 Ian da Silva, Jeremy Siegel - * Based largely on io_se.c. - * - * I/O routines for Hitachi EDOSK7705 board. - * - */ - -#include -#include -#include -#include -#include - -#define SMC_IOADDR 0xA2000000 - -/* Map the Ethernet addresses as if it is at 0x300 - 0x320 */ -static unsigned long sh_edosk7705_isa_port2addr(unsigned long port) -{ - /* - * SMC91C96 registers are 4 byte aligned rather than the - * usual 2 byte! - */ - if (port >= 0x300 && port < 0x320) - return SMC_IOADDR + ((port - 0x300) * 2); - - maybebadio(port); - return port; -} - -/* Trying to read / write bytes on odd-byte boundaries to the Ethernet - * registers causes problems. So we bit-shift the value and read / write - * in 2 byte chunks. Setting the low byte to 0 does not cause problems - * now as odd byte writes are only made on the bit mask / interrupt - * register. This may not be the case in future Mar-2003 SJD - */ -unsigned char sh_edosk7705_inb(unsigned long port) -{ - if (port >= 0x300 && port < 0x320 && port & 0x01) - return __raw_readw(port - 1) >> 8; - - return __raw_readb(sh_edosk7705_isa_port2addr(port)); -} - -void sh_edosk7705_outb(unsigned char value, unsigned long port) -{ - if (port >= 0x300 && port < 0x320 && port & 0x01) { - __raw_writew(((unsigned short)value << 8), port - 1); - return; - } - - __raw_writeb(value, sh_edosk7705_isa_port2addr(port)); -} - -void sh_edosk7705_insb(unsigned long port, void *addr, unsigned long count) -{ - unsigned char *p = addr; - - while (count--) - *p++ = sh_edosk7705_inb(port); -} - -void sh_edosk7705_outsb(unsigned long port, const void *addr, unsigned long count) -{ - unsigned char *p = (unsigned char *)addr; - - while (count--) - sh_edosk7705_outb(*p++, port); -} diff --git a/trunk/arch/sh/boards/mach-edosk7705/setup.c b/trunk/arch/sh/boards/mach-edosk7705/setup.c deleted file mode 100644 index d59225e26fb9..000000000000 --- a/trunk/arch/sh/boards/mach-edosk7705/setup.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * arch/sh/boards/renesas/edosk7705/setup.c - * - * Copyright (C) 2000 Kazumoto Kojima - * - * Hitachi SolutionEngine Support. - * - * Modified for edosk7705 development - * board by S. Dunn, 2003. - */ -#include -#include -#include -#include - -static void __init sh_edosk7705_init_irq(void) -{ - /* This is the Ethernet interrupt */ - make_imask_irq(0x09); -} - -/* - * The Machine Vector - */ -static struct sh_machine_vector mv_edosk7705 __initmv = { - .mv_name = "EDOSK7705", - .mv_nr_irqs = 80, - - .mv_inb = sh_edosk7705_inb, - .mv_outb = sh_edosk7705_outb, - - .mv_insb = sh_edosk7705_insb, - .mv_outsb = sh_edosk7705_outsb, - - .mv_init_irq = sh_edosk7705_init_irq, -}; diff --git a/trunk/arch/sh/boards/mach-microdev/io.c b/trunk/arch/sh/boards/mach-microdev/io.c index 2960c659020e..acdafb0c6404 100644 --- a/trunk/arch/sh/boards/mach-microdev/io.c +++ b/trunk/arch/sh/boards/mach-microdev/io.c @@ -54,7 +54,7 @@ /* * map I/O ports to memory-mapped addresses */ -static unsigned long microdev_isa_port2addr(unsigned long offset) +void __iomem *microdev_ioport_map(unsigned long offset, unsigned int len) { unsigned long result; @@ -72,16 +72,6 @@ static unsigned long microdev_isa_port2addr(unsigned long offset) * Configuration Registers */ result = IO_SUPERIO_PHYS + (offset << 1); -#if 0 - } else if (offset == KBD_DATA_REG || offset == KBD_CNTL_REG || - offset == KBD_STATUS_REG) { - /* - * SMSC FDC37C93xAPM SuperIO chip - * - * PS/2 Keyboard + Mouse (ports 0x60 and 0x64). - */ - result = IO_SUPERIO_PHYS + (offset << 1); -#endif } else if (((offset >= IO_IDE1_BASE) && (offset < IO_IDE1_BASE + IO_IDE_EXTENT)) || (offset == IO_IDE1_MISC)) { @@ -131,237 +121,5 @@ static unsigned long microdev_isa_port2addr(unsigned long offset) result = PVR; } - return result; -} - -#define PORT2ADDR(x) (microdev_isa_port2addr(x)) - -static inline void delay(void) -{ -#if defined(CONFIG_PCI) - /* System board present, just make a dummy SRAM access. (CS0 will be - mapped to PCI memory, probably good to avoid it.) */ - __raw_readw(0xa6800000); -#else - /* CS0 will be mapped to flash, ROM etc so safe to access it. */ - __raw_readw(0xa0000000); -#endif -} - -unsigned char microdev_inb(unsigned long port) -{ -#ifdef CONFIG_PCI - if (port >= PCIBIOS_MIN_IO) - return microdev_pci_inb(port); -#endif - return *(volatile unsigned char*)PORT2ADDR(port); -} - -unsigned short microdev_inw(unsigned long port) -{ -#ifdef CONFIG_PCI - if (port >= PCIBIOS_MIN_IO) - return microdev_pci_inw(port); -#endif - return *(volatile unsigned short*)PORT2ADDR(port); -} - -unsigned int microdev_inl(unsigned long port) -{ -#ifdef CONFIG_PCI - if (port >= PCIBIOS_MIN_IO) - return microdev_pci_inl(port); -#endif - return *(volatile unsigned int*)PORT2ADDR(port); -} - -void microdev_outw(unsigned short b, unsigned long port) -{ -#ifdef CONFIG_PCI - if (port >= PCIBIOS_MIN_IO) { - microdev_pci_outw(b, port); - return; - } -#endif - *(volatile unsigned short*)PORT2ADDR(port) = b; -} - -void microdev_outb(unsigned char b, unsigned long port) -{ -#ifdef CONFIG_PCI - if (port >= PCIBIOS_MIN_IO) { - microdev_pci_outb(b, port); - return; - } -#endif - - /* - * There is a board feature with the current SH4-202 MicroDev in - * that the 2 byte enables (nBE0 and nBE1) are tied together (and - * to the Chip Select Line (Ethernet_CS)). Due to this connectivity, - * it is not possible to safely perform 8-bit writes to the - * Ethernet registers, as 16-bits will be consumed from the Data - * lines (corrupting the other byte). Hence, this function is - * written to implement 16-bit read/modify/write for all byte-wide - * accesses. - * - * Note: there is no problem with byte READS (even or odd). - * - * Sean McGoogan - 16th June 2003. - */ - if ((port >= IO_LAN91C111_BASE) && - (port < IO_LAN91C111_BASE + IO_LAN91C111_EXTENT)) { - /* - * Then are trying to perform a byte-write to the - * LAN91C111. This needs special care. - */ - if (port % 2 == 1) { /* is the port odd ? */ - /* unset bit-0, i.e. make even */ - const unsigned long evenPort = port-1; - unsigned short word; - - /* - * do a 16-bit read/write to write to 'port', - * preserving even byte. - * - * Even addresses are bits 0-7 - * Odd addresses are bits 8-15 - */ - word = microdev_inw(evenPort); - word = (word & 0xffu) | (b << 8); - microdev_outw(word, evenPort); - } else { - /* else, we are trying to do an even byte write */ - unsigned short word; - - /* - * do a 16-bit read/write to write to 'port', - * preserving odd byte. - * - * Even addresses are bits 0-7 - * Odd addresses are bits 8-15 - */ - word = microdev_inw(port); - word = (word & 0xff00u) | (b); - microdev_outw(word, port); - } - } else { - *(volatile unsigned char*)PORT2ADDR(port) = b; - } -} - -void microdev_outl(unsigned int b, unsigned long port) -{ -#ifdef CONFIG_PCI - if (port >= PCIBIOS_MIN_IO) { - microdev_pci_outl(b, port); - return; - } -#endif - *(volatile unsigned int*)PORT2ADDR(port) = b; -} - -unsigned char microdev_inb_p(unsigned long port) -{ - unsigned char v = microdev_inb(port); - delay(); - return v; -} - -unsigned short microdev_inw_p(unsigned long port) -{ - unsigned short v = microdev_inw(port); - delay(); - return v; -} - -unsigned int microdev_inl_p(unsigned long port) -{ - unsigned int v = microdev_inl(port); - delay(); - return v; -} - -void microdev_outb_p(unsigned char b, unsigned long port) -{ - microdev_outb(b, port); - delay(); -} - -void microdev_outw_p(unsigned short b, unsigned long port) -{ - microdev_outw(b, port); - delay(); -} - -void microdev_outl_p(unsigned int b, unsigned long port) -{ - microdev_outl(b, port); - delay(); -} - -void microdev_insb(unsigned long port, void *buffer, unsigned long count) -{ - volatile unsigned char *port_addr; - unsigned char *buf = buffer; - - port_addr = (volatile unsigned char *)PORT2ADDR(port); - - while (count--) - *buf++ = *port_addr; -} - -void microdev_insw(unsigned long port, void *buffer, unsigned long count) -{ - volatile unsigned short *port_addr; - unsigned short *buf = buffer; - - port_addr = (volatile unsigned short *)PORT2ADDR(port); - - while (count--) - *buf++ = *port_addr; -} - -void microdev_insl(unsigned long port, void *buffer, unsigned long count) -{ - volatile unsigned long *port_addr; - unsigned int *buf = buffer; - - port_addr = (volatile unsigned long *)PORT2ADDR(port); - - while (count--) - *buf++ = *port_addr; -} - -void microdev_outsb(unsigned long port, const void *buffer, unsigned long count) -{ - volatile unsigned char *port_addr; - const unsigned char *buf = buffer; - - port_addr = (volatile unsigned char *)PORT2ADDR(port); - - while (count--) - *port_addr = *buf++; -} - -void microdev_outsw(unsigned long port, const void *buffer, unsigned long count) -{ - volatile unsigned short *port_addr; - const unsigned short *buf = buffer; - - port_addr = (volatile unsigned short *)PORT2ADDR(port); - - while (count--) - *port_addr = *buf++; -} - -void microdev_outsl(unsigned long port, const void *buffer, unsigned long count) -{ - volatile unsigned long *port_addr; - const unsigned int *buf = buffer; - - port_addr = (volatile unsigned long *)PORT2ADDR(port); - - while (count--) - *port_addr = *buf++; + return (void __iomem *)result; } diff --git a/trunk/arch/sh/boards/mach-microdev/setup.c b/trunk/arch/sh/boards/mach-microdev/setup.c index d1df2a4fb9b8..d8a747291e03 100644 --- a/trunk/arch/sh/boards/mach-microdev/setup.c +++ b/trunk/arch/sh/boards/mach-microdev/setup.c @@ -195,27 +195,6 @@ device_initcall(microdev_devices_setup); static struct sh_machine_vector mv_sh4202_microdev __initmv = { .mv_name = "SH4-202 MicroDev", .mv_nr_irqs = 72, - - .mv_inb = microdev_inb, - .mv_inw = microdev_inw, - .mv_inl = microdev_inl, - .mv_outb = microdev_outb, - .mv_outw = microdev_outw, - .mv_outl = microdev_outl, - - .mv_inb_p = microdev_inb_p, - .mv_inw_p = microdev_inw_p, - .mv_inl_p = microdev_inl_p, - .mv_outb_p = microdev_outb_p, - .mv_outw_p = microdev_outw_p, - .mv_outl_p = microdev_outl_p, - - .mv_insb = microdev_insb, - .mv_insw = microdev_insw, - .mv_insl = microdev_insl, - .mv_outsb = microdev_outsb, - .mv_outsw = microdev_outsw, - .mv_outsl = microdev_outsl, - + .mv_ioport_map = microdev_ioport_map, .mv_init_irq = init_microdev_irq, }; diff --git a/trunk/arch/sh/boards/mach-se/7206/Makefile b/trunk/arch/sh/boards/mach-se/7206/Makefile index 63e7ed699f39..5c9eaa0535b9 100644 --- a/trunk/arch/sh/boards/mach-se/7206/Makefile +++ b/trunk/arch/sh/boards/mach-se/7206/Makefile @@ -2,4 +2,4 @@ # Makefile for the 7206 SolutionEngine specific parts of the kernel # -obj-y := setup.o io.o irq.o +obj-y := setup.o irq.o diff --git a/trunk/arch/sh/boards/mach-se/7206/io.c b/trunk/arch/sh/boards/mach-se/7206/io.c deleted file mode 100644 index adadc77532ee..000000000000 --- a/trunk/arch/sh/boards/mach-se/7206/io.c +++ /dev/null @@ -1,104 +0,0 @@ -/* $Id: io.c,v 1.5 2004/02/22 23:08:43 kkojima Exp $ - * - * linux/arch/sh/boards/se/7206/io.c - * - * Copyright (C) 2006 Yoshinori Sato - * - * I/O routine for Hitachi 7206 SolutionEngine. - * - */ - -#include -#include -#include -#include - - -static inline void delay(void) -{ - __raw_readw(0x20000000); /* P2 ROM Area */ -} - -/* MS7750 requires special versions of in*, out* routines, since - PC-like io ports are located at upper half byte of 16-bit word which - can be accessed only with 16-bit wide. */ - -static inline volatile __u16 * -port2adr(unsigned int port) -{ - if (port >= 0x2000 && port < 0x2020) - return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000)); - else if (port >= 0x300 && port < 0x310) - return (volatile __u16 *) (PA_SMSC + (port - 0x300)); - - return (volatile __u16 *)port; -} - -unsigned char se7206_inb(unsigned long port) -{ - return (*port2adr(port)) & 0xff; -} - -unsigned char se7206_inb_p(unsigned long port) -{ - unsigned long v; - - v = (*port2adr(port)) & 0xff; - delay(); - return v; -} - -unsigned short se7206_inw(unsigned long port) -{ - return *port2adr(port); -} - -void se7206_outb(unsigned char value, unsigned long port) -{ - *(port2adr(port)) = value; -} - -void se7206_outb_p(unsigned char value, unsigned long port) -{ - *(port2adr(port)) = value; - delay(); -} - -void se7206_outw(unsigned short value, unsigned long port) -{ - *port2adr(port) = value; -} - -void se7206_insb(unsigned long port, void *addr, unsigned long count) -{ - volatile __u16 *p = port2adr(port); - __u8 *ap = addr; - - while (count--) - *ap++ = *p; -} - -void se7206_insw(unsigned long port, void *addr, unsigned long count) -{ - volatile __u16 *p = port2adr(port); - __u16 *ap = addr; - while (count--) - *ap++ = *p; -} - -void se7206_outsb(unsigned long port, const void *addr, unsigned long count) -{ - volatile __u16 *p = port2adr(port); - const __u8 *ap = addr; - - while (count--) - *p = *ap++; -} - -void se7206_outsw(unsigned long port, const void *addr, unsigned long count) -{ - volatile __u16 *p = port2adr(port); - const __u16 *ap = addr; - while (count--) - *p = *ap++; -} diff --git a/trunk/arch/sh/boards/mach-se/7206/irq.c b/trunk/arch/sh/boards/mach-se/7206/irq.c index 883b21eacaa6..d961949600fd 100644 --- a/trunk/arch/sh/boards/mach-se/7206/irq.c +++ b/trunk/arch/sh/boards/mach-se/7206/irq.c @@ -139,11 +139,13 @@ void __init init_se7206_IRQ(void) make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */ make_se7206_irq(IRQ1_IRQ); /* ATA */ make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */ - __raw_writew(inw(INTC_ICR1) | 0x000b ,INTC_ICR1 ) ; /* ICR1 */ + + __raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR); /* ICR1 */ /* FPGA System register setup*/ __raw_writew(0x0000,INTSTS0); /* Clear INTSTS0 */ __raw_writew(0x0000,INTSTS1); /* Clear INTSTS1 */ + /* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */ __raw_writew(0x0001,INTSEL); } diff --git a/trunk/arch/sh/boards/mach-se/7206/setup.c b/trunk/arch/sh/boards/mach-se/7206/setup.c index 8f5c65d43d1d..7f4871c71a01 100644 --- a/trunk/arch/sh/boards/mach-se/7206/setup.c +++ b/trunk/arch/sh/boards/mach-se/7206/setup.c @@ -86,20 +86,5 @@ __initcall(se7206_devices_setup); static struct sh_machine_vector mv_se __initmv = { .mv_name = "SolutionEngine", .mv_nr_irqs = 256, - .mv_inb = se7206_inb, - .mv_inw = se7206_inw, - .mv_outb = se7206_outb, - .mv_outw = se7206_outw, - - .mv_inb_p = se7206_inb_p, - .mv_inw_p = se7206_inw, - .mv_outb_p = se7206_outb_p, - .mv_outw_p = se7206_outw, - - .mv_insb = se7206_insb, - .mv_insw = se7206_insw, - .mv_outsb = se7206_outsb, - .mv_outsw = se7206_outsw, - .mv_init_irq = init_se7206_IRQ, }; diff --git a/trunk/arch/sh/boards/mach-se/770x/Makefile b/trunk/arch/sh/boards/mach-se/770x/Makefile index 8e624b06d5ea..43ea14feef51 100644 --- a/trunk/arch/sh/boards/mach-se/770x/Makefile +++ b/trunk/arch/sh/boards/mach-se/770x/Makefile @@ -2,4 +2,4 @@ # Makefile for the 770x SolutionEngine specific parts of the kernel # -obj-y := setup.o io.o irq.o +obj-y := setup.o irq.o diff --git a/trunk/arch/sh/boards/mach-se/770x/io.c b/trunk/arch/sh/boards/mach-se/770x/io.c deleted file mode 100644 index 28833c8786ea..000000000000 --- a/trunk/arch/sh/boards/mach-se/770x/io.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2000 Kazumoto Kojima - * - * I/O routine for Hitachi SolutionEngine. - */ -#include -#include -#include -#include - -/* MS7750 requires special versions of in*, out* routines, since - PC-like io ports are located at upper half byte of 16-bit word which - can be accessed only with 16-bit wide. */ - -static inline volatile __u16 * -port2adr(unsigned int port) -{ - if (port & 0xff000000) - return ( volatile __u16 *) port; - if (port >= 0x2000) - return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000)); - else if (port >= 0x1000) - return (volatile __u16 *) (PA_83902 + (port << 1)); - else - return (volatile __u16 *) (PA_SUPERIO + (port << 1)); -} - -static inline int -shifted_port(unsigned long port) -{ - /* For IDE registers, value is not shifted */ - if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6) - return 0; - else - return 1; -} - -unsigned char se_inb(unsigned long port) -{ - if (shifted_port(port)) - return (*port2adr(port) >> 8); - else - return (*port2adr(port))&0xff; -} - -unsigned char se_inb_p(unsigned long port) -{ - unsigned long v; - - if (shifted_port(port)) - v = (*port2adr(port) >> 8); - else - v = (*port2adr(port))&0xff; - ctrl_delay(); - return v; -} - -unsigned short se_inw(unsigned long port) -{ - if (port >= 0x2000) - return *port2adr(port); - else - maybebadio(port); - return 0; -} - -unsigned int se_inl(unsigned long port) -{ - maybebadio(port); - return 0; -} - -void se_outb(unsigned char value, unsigned long port) -{ - if (shifted_port(port)) - *(port2adr(port)) = value << 8; - else - *(port2adr(port)) = value; -} - -void se_outb_p(unsigned char value, unsigned long port) -{ - if (shifted_port(port)) - *(port2adr(port)) = value << 8; - else - *(port2adr(port)) = value; - ctrl_delay(); -} - -void se_outw(unsigned short value, unsigned long port) -{ - if (port >= 0x2000) - *port2adr(port) = value; - else - maybebadio(port); -} - -void se_outl(unsigned int value, unsigned long port) -{ - maybebadio(port); -} - -void se_insb(unsigned long port, void *addr, unsigned long count) -{ - volatile __u16 *p = port2adr(port); - __u8 *ap = addr; - - if (shifted_port(port)) { - while (count--) - *ap++ = *p >> 8; - } else { - while (count--) - *ap++ = *p; - } -} - -void se_insw(unsigned long port, void *addr, unsigned long count) -{ - volatile __u16 *p = port2adr(port); - __u16 *ap = addr; - while (count--) - *ap++ = *p; -} - -void se_insl(unsigned long port, void *addr, unsigned long count) -{ - maybebadio(port); -} - -void se_outsb(unsigned long port, const void *addr, unsigned long count) -{ - volatile __u16 *p = port2adr(port); - const __u8 *ap = addr; - - if (shifted_port(port)) { - while (count--) - *p = *ap++ << 8; - } else { - while (count--) - *p = *ap++; - } -} - -void se_outsw(unsigned long port, const void *addr, unsigned long count) -{ - volatile __u16 *p = port2adr(port); - const __u16 *ap = addr; - - while (count--) - *p = *ap++; -} - -void se_outsl(unsigned long port, const void *addr, unsigned long count) -{ - maybebadio(port); -} diff --git a/trunk/arch/sh/boards/mach-se/770x/setup.c b/trunk/arch/sh/boards/mach-se/770x/setup.c index 66d39d1b0901..31330c65c0ce 100644 --- a/trunk/arch/sh/boards/mach-se/770x/setup.c +++ b/trunk/arch/sh/boards/mach-se/770x/setup.c @@ -195,27 +195,5 @@ static struct sh_machine_vector mv_se __initmv = { #elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) .mv_nr_irqs = 104, #endif - - .mv_inb = se_inb, - .mv_inw = se_inw, - .mv_inl = se_inl, - .mv_outb = se_outb, - .mv_outw = se_outw, - .mv_outl = se_outl, - - .mv_inb_p = se_inb_p, - .mv_inw_p = se_inw, - .mv_inl_p = se_inl, - .mv_outb_p = se_outb_p, - .mv_outw_p = se_outw, - .mv_outl_p = se_outl, - - .mv_insb = se_insb, - .mv_insw = se_insw, - .mv_insl = se_insl, - .mv_outsb = se_outsb, - .mv_outsw = se_outsw, - .mv_outsl = se_outsl, - .mv_init_irq = init_se_IRQ, }; diff --git a/trunk/arch/sh/boards/mach-se/7751/Makefile b/trunk/arch/sh/boards/mach-se/7751/Makefile index e6f4341bfe6e..a338fd9d5039 100644 --- a/trunk/arch/sh/boards/mach-se/7751/Makefile +++ b/trunk/arch/sh/boards/mach-se/7751/Makefile @@ -2,4 +2,4 @@ # Makefile for the 7751 SolutionEngine specific parts of the kernel # -obj-y := setup.o io.o irq.o +obj-y := setup.o irq.o diff --git a/trunk/arch/sh/boards/mach-se/7751/io.c b/trunk/arch/sh/boards/mach-se/7751/io.c deleted file mode 100644 index 6e75bd4459e5..000000000000 --- a/trunk/arch/sh/boards/mach-se/7751/io.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2001 Ian da Silva, Jeremy Siegel - * Based largely on io_se.c. - * - * I/O routine for Hitachi 7751 SolutionEngine. - * - * Initial version only to support LAN access; some - * placeholder code from io_se.c left in with the - * expectation of later SuperIO and PCMCIA access. - */ -#include -#include -#include -#include -#include -#include - -static inline volatile u16 *port2adr(unsigned int port) -{ - if (port >= 0x2000) - return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000)); - maybebadio((unsigned long)port); - return (volatile __u16*)port; -} - -/* - * General outline: remap really low stuff [eventually] to SuperIO, - * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO) - * is mapped through the PCI IO window. Stuff with high bits (PXSEG) - * should be way beyond the window, and is used w/o translation for - * compatibility. - */ -unsigned char sh7751se_inb(unsigned long port) -{ - if (PXSEG(port)) - return *(volatile unsigned char *)port; - else - return (*port2adr(port)) & 0xff; -} - -unsigned char sh7751se_inb_p(unsigned long port) -{ - unsigned char v; - - if (PXSEG(port)) - v = *(volatile unsigned char *)port; - else - v = (*port2adr(port)) & 0xff; - ctrl_delay(); - return v; -} - -unsigned short sh7751se_inw(unsigned long port) -{ - if (PXSEG(port)) - return *(volatile unsigned short *)port; - else if (port >= 0x2000) - return *port2adr(port); - else - maybebadio(port); - return 0; -} - -unsigned int sh7751se_inl(unsigned long port) -{ - if (PXSEG(port)) - return *(volatile unsigned long *)port; - else if (port >= 0x2000) - return *port2adr(port); - else - maybebadio(port); - return 0; -} - -void sh7751se_outb(unsigned char value, unsigned long port) -{ - - if (PXSEG(port)) - *(volatile unsigned char *)port = value; - else - *(port2adr(port)) = value; -} - -void sh7751se_outb_p(unsigned char value, unsigned long port) -{ - if (PXSEG(port)) - *(volatile unsigned char *)port = value; - else - *(port2adr(port)) = value; - ctrl_delay(); -} - -void sh7751se_outw(unsigned short value, unsigned long port) -{ - if (PXSEG(port)) - *(volatile unsigned short *)port = value; - else if (port >= 0x2000) - *port2adr(port) = value; - else - maybebadio(port); -} - -void sh7751se_outl(unsigned int value, unsigned long port) -{ - if (PXSEG(port)) - *(volatile unsigned long *)port = value; - else - maybebadio(port); -} - -void sh7751se_insl(unsigned long port, void *addr, unsigned long count) -{ - maybebadio(port); -} - -void sh7751se_outsl(unsigned long port, const void *addr, unsigned long count) -{ - maybebadio(port); -} diff --git a/trunk/arch/sh/boards/mach-se/7751/setup.c b/trunk/arch/sh/boards/mach-se/7751/setup.c index 50572512e3e8..9fbc51beb181 100644 --- a/trunk/arch/sh/boards/mach-se/7751/setup.c +++ b/trunk/arch/sh/boards/mach-se/7751/setup.c @@ -56,23 +56,5 @@ __initcall(se7751_devices_setup); static struct sh_machine_vector mv_7751se __initmv = { .mv_name = "7751 SolutionEngine", .mv_nr_irqs = 72, - - .mv_inb = sh7751se_inb, - .mv_inw = sh7751se_inw, - .mv_inl = sh7751se_inl, - .mv_outb = sh7751se_outb, - .mv_outw = sh7751se_outw, - .mv_outl = sh7751se_outl, - - .mv_inb_p = sh7751se_inb_p, - .mv_inw_p = sh7751se_inw, - .mv_inl_p = sh7751se_inl, - .mv_outb_p = sh7751se_outb_p, - .mv_outw_p = sh7751se_outw, - .mv_outl_p = sh7751se_outl, - - .mv_insl = sh7751se_insl, - .mv_outsl = sh7751se_outsl, - .mv_init_irq = init_7751se_IRQ, }; diff --git a/trunk/arch/sh/boards/mach-snapgear/Makefile b/trunk/arch/sh/boards/mach-snapgear/Makefile deleted file mode 100644 index d2d2f4b6a502..000000000000 --- a/trunk/arch/sh/boards/mach-snapgear/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the SnapGear specific parts of the kernel -# - -obj-y := setup.o io.o diff --git a/trunk/arch/sh/boards/mach-snapgear/io.c b/trunk/arch/sh/boards/mach-snapgear/io.c deleted file mode 100644 index 476650e42dbc..000000000000 --- a/trunk/arch/sh/boards/mach-snapgear/io.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2002 David McCullough - * Copyright (C) 2001 Ian da Silva, Jeremy Siegel - * Based largely on io_se.c. - * - * I/O routine for Hitachi 7751 SolutionEngine. - * - * Initial version only to support LAN access; some - * placeholder code from io_se.c left in with the - * expectation of later SuperIO and PCMCIA access. - */ -#include -#include -#include -#include -#include - -#ifdef CONFIG_SH_SECUREEDGE5410 -unsigned short secureedge5410_ioport; -#endif - -static inline volatile __u16 *port2adr(unsigned int port) -{ - maybebadio((unsigned long)port); - return (volatile __u16*)port; -} - -/* - * General outline: remap really low stuff [eventually] to SuperIO, - * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO) - * is mapped through the PCI IO window. Stuff with high bits (PXSEG) - * should be way beyond the window, and is used w/o translation for - * compatibility. - */ -unsigned char snapgear_inb(unsigned long port) -{ - if (PXSEG(port)) - return *(volatile unsigned char *)port; - else - return (*port2adr(port)) & 0xff; -} - -unsigned char snapgear_inb_p(unsigned long port) -{ - unsigned char v; - - if (PXSEG(port)) - v = *(volatile unsigned char *)port; - else - v = (*port2adr(port))&0xff; - ctrl_delay(); - return v; -} - -unsigned short snapgear_inw(unsigned long port) -{ - if (PXSEG(port)) - return *(volatile unsigned short *)port; - else if (port >= 0x2000) - return *port2adr(port); - else - maybebadio(port); - return 0; -} - -unsigned int snapgear_inl(unsigned long port) -{ - if (PXSEG(port)) - return *(volatile unsigned long *)port; - else if (port >= 0x2000) - return *port2adr(port); - else - maybebadio(port); - return 0; -} - -void snapgear_outb(unsigned char value, unsigned long port) -{ - - if (PXSEG(port)) - *(volatile unsigned char *)port = value; - else - *(port2adr(port)) = value; -} - -void snapgear_outb_p(unsigned char value, unsigned long port) -{ - if (PXSEG(port)) - *(volatile unsigned char *)port = value; - else - *(port2adr(port)) = value; - ctrl_delay(); -} - -void snapgear_outw(unsigned short value, unsigned long port) -{ - if (PXSEG(port)) - *(volatile unsigned short *)port = value; - else if (port >= 0x2000) - *port2adr(port) = value; - else - maybebadio(port); -} - -void snapgear_outl(unsigned int value, unsigned long port) -{ - if (PXSEG(port)) - *(volatile unsigned long *)port = value; - else - maybebadio(port); -} - -void snapgear_insl(unsigned long port, void *addr, unsigned long count) -{ - maybebadio(port); -} - -void snapgear_outsl(unsigned long port, const void *addr, unsigned long count) -{ - maybebadio(port); -} diff --git a/trunk/arch/sh/boards/mach-systemh/Makefile b/trunk/arch/sh/boards/mach-systemh/Makefile deleted file mode 100644 index 2cc6a23d9d39..000000000000 --- a/trunk/arch/sh/boards/mach-systemh/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# -# Makefile for the SystemH specific parts of the kernel -# - -obj-y := setup.o irq.o io.o - -# XXX: This wants to be consolidated in arch/sh/drivers/pci, and more -# importantly, with the generic sh7751_pcic_init() code. For now, we'll -# just abuse the hell out of kbuild, because we can.. - -obj-$(CONFIG_PCI) += pci.o -pci-y := ../../se/7751/pci.o - diff --git a/trunk/arch/sh/boards/mach-systemh/io.c b/trunk/arch/sh/boards/mach-systemh/io.c deleted file mode 100644 index 15577ff1f715..000000000000 --- a/trunk/arch/sh/boards/mach-systemh/io.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * linux/arch/sh/boards/renesas/systemh/io.c - * - * Copyright (C) 2001 Ian da Silva, Jeremy Siegel - * Based largely on io_se.c. - * - * I/O routine for Hitachi 7751 Systemh. - */ -#include -#include -#include -#include -#include -#include - -#define ETHER_IOMAP(adr) (0xB3000000 + (adr)) /*map to 16bits access area - of smc lan chip*/ -static inline volatile __u16 * -port2adr(unsigned int port) -{ - if (port >= 0x2000) - return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000)); - maybebadio((unsigned long)port); - return (volatile __u16*)port; -} - -/* - * General outline: remap really low stuff [eventually] to SuperIO, - * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO) - * is mapped through the PCI IO window. Stuff with high bits (PXSEG) - * should be way beyond the window, and is used w/o translation for - * compatibility. - */ -unsigned char sh7751systemh_inb(unsigned long port) -{ - if (PXSEG(port)) - return *(volatile unsigned char *)port; - else if (port <= 0x3F1) - return *(volatile unsigned char *)ETHER_IOMAP(port); - else - return (*port2adr(port))&0xff; -} - -unsigned char sh7751systemh_inb_p(unsigned long port) -{ - unsigned char v; - - if (PXSEG(port)) - v = *(volatile unsigned char *)port; - else if (port <= 0x3F1) - v = *(volatile unsigned char *)ETHER_IOMAP(port); - else - v = (*port2adr(port))&0xff; - ctrl_delay(); - return v; -} - -unsigned short sh7751systemh_inw(unsigned long port) -{ - if (PXSEG(port)) - return *(volatile unsigned short *)port; - else if (port >= 0x2000) - return *port2adr(port); - else if (port <= 0x3F1) - return *(volatile unsigned int *)ETHER_IOMAP(port); - else - maybebadio(port); - return 0; -} - -unsigned int sh7751systemh_inl(unsigned long port) -{ - if (PXSEG(port)) - return *(volatile unsigned long *)port; - else if (port >= 0x2000) - return *port2adr(port); - else if (port <= 0x3F1) - return *(volatile unsigned int *)ETHER_IOMAP(port); - else - maybebadio(port); - return 0; -} - -void sh7751systemh_outb(unsigned char value, unsigned long port) -{ - - if (PXSEG(port)) - *(volatile unsigned char *)port = value; - else if (port <= 0x3F1) - *(volatile unsigned char *)ETHER_IOMAP(port) = value; - else - *(port2adr(port)) = value; -} - -void sh7751systemh_outb_p(unsigned char value, unsigned long port) -{ - if (PXSEG(port)) - *(volatile unsigned char *)port = value; - else if (port <= 0x3F1) - *(volatile unsigned char *)ETHER_IOMAP(port) = value; - else - *(port2adr(port)) = value; - ctrl_delay(); -} - -void sh7751systemh_outw(unsigned short value, unsigned long port) -{ - if (PXSEG(port)) - *(volatile unsigned short *)port = value; - else if (port >= 0x2000) - *port2adr(port) = value; - else if (port <= 0x3F1) - *(volatile unsigned short *)ETHER_IOMAP(port) = value; - else - maybebadio(port); -} - -void sh7751systemh_outl(unsigned int value, unsigned long port) -{ - if (PXSEG(port)) - *(volatile unsigned long *)port = value; - else - maybebadio(port); -} - -void sh7751systemh_insb(unsigned long port, void *addr, unsigned long count) -{ - unsigned char *p = addr; - while (count--) *p++ = sh7751systemh_inb(port); -} - -void sh7751systemh_insw(unsigned long port, void *addr, unsigned long count) -{ - unsigned short *p = addr; - while (count--) *p++ = sh7751systemh_inw(port); -} - -void sh7751systemh_insl(unsigned long port, void *addr, unsigned long count) -{ - maybebadio(port); -} - -void sh7751systemh_outsb(unsigned long port, const void *addr, unsigned long count) -{ - unsigned char *p = (unsigned char*)addr; - while (count--) sh7751systemh_outb(*p++, port); -} - -void sh7751systemh_outsw(unsigned long port, const void *addr, unsigned long count) -{ - unsigned short *p = (unsigned short*)addr; - while (count--) sh7751systemh_outw(*p++, port); -} - -void sh7751systemh_outsl(unsigned long port, const void *addr, unsigned long count) -{ - maybebadio(port); -} diff --git a/trunk/arch/sh/boards/mach-systemh/irq.c b/trunk/arch/sh/boards/mach-systemh/irq.c deleted file mode 100644 index e5ee13adeff4..000000000000 --- a/trunk/arch/sh/boards/mach-systemh/irq.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * linux/arch/sh/boards/renesas/systemh/irq.c - * - * Copyright (C) 2000 Kazumoto Kojima - * - * Hitachi SystemH Support. - * - * Modified for 7751 SystemH by - * Jonathan Short. - */ - -#include -#include -#include -#include - -#include -#include - -/* address of external interrupt mask register - * address must be set prior to use these (maybe in init_XXX_irq()) - * XXX : is it better to use .config than specifying it in code? */ -static unsigned long *systemh_irq_mask_register = (unsigned long *)0xB3F10004; -static unsigned long *systemh_irq_request_register = (unsigned long *)0xB3F10000; - -static void disable_systemh_irq(struct irq_data *data) -{ - unsigned long val, mask = 0x01 << 1; - - /* Clear the "irq"th bit in the mask and set it in the request */ - val = __raw_readl((unsigned long)systemh_irq_mask_register); - val &= ~mask; - __raw_writel(val, (unsigned long)systemh_irq_mask_register); - - val = __raw_readl((unsigned long)systemh_irq_request_register); - val |= mask; - __raw_writel(val, (unsigned long)systemh_irq_request_register); -} - -static void enable_systemh_irq(struct irq_data *data) -{ - unsigned long val, mask = 0x01 << 1; - - /* Set "irq"th bit in the mask register */ - val = __raw_readl((unsigned long)systemh_irq_mask_register); - val |= mask; - __raw_writel(val, (unsigned long)systemh_irq_mask_register); -} - -static struct irq_chip systemh_irq_type = { - .name = "SystemH Register", - .irq_unmask = enable_systemh_irq, - .irq_mask = disable_systemh_irq, -}; - -void make_systemh_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - set_irq_chip_and_handler(irq, &systemh_irq_type, handle_level_irq); - disable_systemh_irq(irq_get_irq_data(irq)); -} diff --git a/trunk/arch/sh/boards/mach-systemh/setup.c b/trunk/arch/sh/boards/mach-systemh/setup.c deleted file mode 100644 index 219fd800a43f..000000000000 --- a/trunk/arch/sh/boards/mach-systemh/setup.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * linux/arch/sh/boards/renesas/systemh/setup.c - * - * Copyright (C) 2000 Kazumoto Kojima - * Copyright (C) 2003 Paul Mundt - * - * Hitachi SystemH Support. - * - * Modified for 7751 SystemH by Jonathan Short. - * - * Rewritten for 2.6 by Paul Mundt. - * - * 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. - */ -#include -#include -#include - -extern void make_systemh_irq(unsigned int irq); - -/* - * Initialize IRQ setting - */ -static void __init sh7751systemh_init_irq(void) -{ - make_systemh_irq(0xb); /* Ethernet interrupt */ -} - -static struct sh_machine_vector mv_7751systemh __initmv = { - .mv_name = "7751 SystemH", - .mv_nr_irqs = 72, - - .mv_inb = sh7751systemh_inb, - .mv_inw = sh7751systemh_inw, - .mv_inl = sh7751systemh_inl, - .mv_outb = sh7751systemh_outb, - .mv_outw = sh7751systemh_outw, - .mv_outl = sh7751systemh_outl, - - .mv_inb_p = sh7751systemh_inb_p, - .mv_inw_p = sh7751systemh_inw, - .mv_inl_p = sh7751systemh_inl, - .mv_outb_p = sh7751systemh_outb_p, - .mv_outw_p = sh7751systemh_outw, - .mv_outl_p = sh7751systemh_outl, - - .mv_insb = sh7751systemh_insb, - .mv_insw = sh7751systemh_insw, - .mv_insl = sh7751systemh_insl, - .mv_outsb = sh7751systemh_outsb, - .mv_outsw = sh7751systemh_outsw, - .mv_outsl = sh7751systemh_outsl, - - .mv_init_irq = sh7751systemh_init_irq, -}; diff --git a/trunk/arch/sh/configs/snapgear_defconfig b/trunk/arch/sh/configs/secureedge5410_defconfig similarity index 100% rename from trunk/arch/sh/configs/snapgear_defconfig rename to trunk/arch/sh/configs/secureedge5410_defconfig diff --git a/trunk/arch/sh/configs/systemh_defconfig b/trunk/arch/sh/configs/systemh_defconfig deleted file mode 100644 index b58dfc505efe..000000000000 --- a/trunk/arch/sh/configs/systemh_defconfig +++ /dev/null @@ -1,28 +0,0 @@ -CONFIG_EXPERIMENTAL=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_BLK_DEV_INITRD=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -# CONFIG_SYSCTL_SYSCALL is not set -# CONFIG_HOTPLUG is not set -CONFIG_SLAB=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set -CONFIG_CPU_SUBTYPE_SH7751R=y -CONFIG_MEMORY_START=0x0c000000 -CONFIG_MEMORY_SIZE=0x00400000 -CONFIG_FLATMEM_MANUAL=y -CONFIG_SH_7751_SYSTEMH=y -CONFIG_PREEMPT=y -# CONFIG_STANDALONE is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=1024 -# CONFIG_INPUT is not set -# CONFIG_SERIO_SERPORT is not set -# CONFIG_VT is not set -CONFIG_HW_RANDOM=y -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_CRAMFS=y -CONFIG_ROMFS_FS=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set diff --git a/trunk/arch/sh/include/asm/addrspace.h b/trunk/arch/sh/include/asm/addrspace.h index 446b3831c214..3d1ae2bfaa6f 100644 --- a/trunk/arch/sh/include/asm/addrspace.h +++ b/trunk/arch/sh/include/asm/addrspace.h @@ -44,10 +44,10 @@ /* * These will never work in 32-bit, don't even bother. */ -#define P1SEGADDR(a) __futile_remapping_attempt -#define P2SEGADDR(a) __futile_remapping_attempt -#define P3SEGADDR(a) __futile_remapping_attempt -#define P4SEGADDR(a) __futile_remapping_attempt +#define P1SEGADDR(a) ({ (void)(a); BUG(); NULL; }) +#define P2SEGADDR(a) ({ (void)(a); BUG(); NULL; }) +#define P3SEGADDR(a) ({ (void)(a); BUG(); NULL; }) +#define P4SEGADDR(a) ({ (void)(a); BUG(); NULL; }) #endif #endif /* P1SEG */ diff --git a/trunk/arch/sh/include/asm/pgtable.h b/trunk/arch/sh/include/asm/pgtable.h index a15f1058bbf4..083ea068e819 100644 --- a/trunk/arch/sh/include/asm/pgtable.h +++ b/trunk/arch/sh/include/asm/pgtable.h @@ -66,7 +66,6 @@ static inline unsigned long long neff_sign_extend(unsigned long val) #define PHYS_ADDR_MASK29 0x1fffffff #define PHYS_ADDR_MASK32 0xffffffff -#ifdef CONFIG_PMB static inline unsigned long phys_addr_mask(void) { /* Is the MMU in 29bit mode? */ @@ -75,17 +74,6 @@ static inline unsigned long phys_addr_mask(void) return PHYS_ADDR_MASK32; } -#elif defined(CONFIG_32BIT) -static inline unsigned long phys_addr_mask(void) -{ - return PHYS_ADDR_MASK32; -} -#else -static inline unsigned long phys_addr_mask(void) -{ - return PHYS_ADDR_MASK29; -} -#endif #define PTE_PHYS_MASK (phys_addr_mask() & PAGE_MASK) #define PTE_FLAGS_MASK (~(PTE_PHYS_MASK) << PAGE_SHIFT) diff --git a/trunk/arch/sh/include/asm/system.h b/trunk/arch/sh/include/asm/system.h index 1f1af5afff03..10c8b1823a18 100644 --- a/trunk/arch/sh/include/asm/system.h +++ b/trunk/arch/sh/include/asm/system.h @@ -10,6 +10,7 @@ #include #include #include +#include #define AT_VECTOR_SIZE_ARCH 5 /* entries in ARCH_DLINFO */ @@ -137,9 +138,6 @@ extern unsigned int instruction_size(unsigned int insn); #define instruction_size(insn) (4) #endif -extern unsigned long cached_to_uncached; -extern unsigned long uncached_size; - void per_cpu_trap_init(void); void default_idle(void); void cpu_idle_wait(void); diff --git a/trunk/arch/sh/include/asm/system_32.h b/trunk/arch/sh/include/asm/system_32.h index c941b2739405..a4ad1cd9bc4d 100644 --- a/trunk/arch/sh/include/asm/system_32.h +++ b/trunk/arch/sh/include/asm/system_32.h @@ -145,42 +145,6 @@ do { \ __restore_dsp(prev); \ } while (0) -/* - * Jump to uncached area. - * When handling TLB or caches, we need to do it from an uncached area. - */ -#define jump_to_uncached() \ -do { \ - unsigned long __dummy; \ - \ - __asm__ __volatile__( \ - "mova 1f, %0\n\t" \ - "add %1, %0\n\t" \ - "jmp @%0\n\t" \ - " nop\n\t" \ - ".balign 4\n" \ - "1:" \ - : "=&z" (__dummy) \ - : "r" (cached_to_uncached)); \ -} while (0) - -/* - * Back to cached area. - */ -#define back_to_cached() \ -do { \ - unsigned long __dummy; \ - ctrl_barrier(); \ - __asm__ __volatile__( \ - "mov.l 1f, %0\n\t" \ - "jmp @%0\n\t" \ - " nop\n\t" \ - ".balign 4\n" \ - "1: .long 2f\n" \ - "2:" \ - : "=&r" (__dummy)); \ -} while (0) - #ifdef CONFIG_CPU_HAS_SR_RB #define lookup_exception_vector() \ ({ \ diff --git a/trunk/arch/sh/include/asm/system_64.h b/trunk/arch/sh/include/asm/system_64.h index 36338646dfc8..8593bc8d1a4e 100644 --- a/trunk/arch/sh/include/asm/system_64.h +++ b/trunk/arch/sh/include/asm/system_64.h @@ -34,9 +34,6 @@ do { \ &next->thread); \ } while (0) -#define jump_to_uncached() do { } while (0) -#define back_to_cached() do { } while (0) - #define __icbi(addr) __asm__ __volatile__ ( "icbi %0, 0\n\t" : : "r" (addr)) #define __ocbp(addr) __asm__ __volatile__ ( "ocbp %0, 0\n\t" : : "r" (addr)) #define __ocbi(addr) __asm__ __volatile__ ( "ocbi %0, 0\n\t" : : "r" (addr)) diff --git a/trunk/arch/sh/include/asm/uncached.h b/trunk/arch/sh/include/asm/uncached.h index e3419f96626a..6f8816b79cf1 100644 --- a/trunk/arch/sh/include/asm/uncached.h +++ b/trunk/arch/sh/include/asm/uncached.h @@ -4,15 +4,55 @@ #include #ifdef CONFIG_UNCACHED_MAPPING +extern unsigned long cached_to_uncached; +extern unsigned long uncached_size; extern unsigned long uncached_start, uncached_end; extern int virt_addr_uncached(unsigned long kaddr); extern void uncached_init(void); extern void uncached_resize(unsigned long size); + +/* + * Jump to uncached area. + * When handling TLB or caches, we need to do it from an uncached area. + */ +#define jump_to_uncached() \ +do { \ + unsigned long __dummy; \ + \ + __asm__ __volatile__( \ + "mova 1f, %0\n\t" \ + "add %1, %0\n\t" \ + "jmp @%0\n\t" \ + " nop\n\t" \ + ".balign 4\n" \ + "1:" \ + : "=&z" (__dummy) \ + : "r" (cached_to_uncached)); \ +} while (0) + +/* + * Back to cached area. + */ +#define back_to_cached() \ +do { \ + unsigned long __dummy; \ + ctrl_barrier(); \ + __asm__ __volatile__( \ + "mov.l 1f, %0\n\t" \ + "jmp @%0\n\t" \ + " nop\n\t" \ + ".balign 4\n" \ + "1: .long 2f\n" \ + "2:" \ + : "=&r" (__dummy)); \ +} while (0) #else #define virt_addr_uncached(kaddr) (0) #define uncached_init() do { } while (0) #define uncached_resize(size) BUG() +#define jump_to_uncached() do { } while (0) +#define back_to_cached() do { } while (0) #endif #endif /* __ASM_SH_UNCACHED_H */ diff --git a/trunk/arch/sh/include/mach-common/mach/edosk7705.h b/trunk/arch/sh/include/mach-common/mach/edosk7705.h deleted file mode 100644 index efc43b323466..000000000000 --- a/trunk/arch/sh/include/mach-common/mach/edosk7705.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __ASM_SH_EDOSK7705_H -#define __ASM_SH_EDOSK7705_H - -#define __IO_PREFIX sh_edosk7705 -#include - -#endif /* __ASM_SH_EDOSK7705_H */ diff --git a/trunk/arch/sh/include/mach-common/mach/microdev.h b/trunk/arch/sh/include/mach-common/mach/microdev.h index 1aed15856e11..dcb05fa8c164 100644 --- a/trunk/arch/sh/include/mach-common/mach/microdev.h +++ b/trunk/arch/sh/include/mach-common/mach/microdev.h @@ -68,13 +68,4 @@ extern void microdev_print_fpga_intc_status(void); #define __IO_PREFIX microdev #include -#if defined(CONFIG_PCI) -unsigned char microdev_pci_inb(unsigned long port); -unsigned short microdev_pci_inw(unsigned long port); -unsigned long microdev_pci_inl(unsigned long port); -void microdev_pci_outb(unsigned char data, unsigned long port); -void microdev_pci_outw(unsigned short data, unsigned long port); -void microdev_pci_outl(unsigned long data, unsigned long port); -#endif - #endif /* __ASM_SH_MICRODEV_H */ diff --git a/trunk/arch/sh/include/mach-common/mach/snapgear.h b/trunk/arch/sh/include/mach-common/mach/secureedge5410.h similarity index 79% rename from trunk/arch/sh/include/mach-common/mach/snapgear.h rename to trunk/arch/sh/include/mach-common/mach/secureedge5410.h index 042d95f51c4d..3653b9a4bacc 100644 --- a/trunk/arch/sh/include/mach-common/mach/snapgear.h +++ b/trunk/arch/sh/include/mach-common/mach/secureedge5410.h @@ -12,30 +12,9 @@ #ifndef _ASM_SH_IO_SNAPGEAR_H #define _ASM_SH_IO_SNAPGEAR_H -#if defined(CONFIG_CPU_SH4) -/* - * The external interrupt lines, these take up ints 0 - 15 inclusive - * depending on the priority for the interrupt. In fact the priority - * is the interrupt :-) - */ - -#define IRL0_IRQ 2 -#define IRL0_PRIORITY 13 - -#define IRL1_IRQ 5 -#define IRL1_PRIORITY 10 - -#define IRL2_IRQ 8 -#define IRL2_PRIORITY 7 - -#define IRL3_IRQ 11 -#define IRL3_PRIORITY 4 -#endif - #define __IO_PREFIX snapgear #include -#ifdef CONFIG_SH_SECUREEDGE5410 /* * We need to remember what was written to the ioport as some bits * are shared with other functions and you cannot read back what was @@ -66,6 +45,5 @@ extern unsigned short secureedge5410_ioport; ((secureedge5410_ioport & ~(mask)) | ((val) & (mask))))) #define SECUREEDGE_READ_IOPORT() \ ((*SECUREEDGE_IOPORT_ADDR&0x0817) | (secureedge5410_ioport&~0x0817)) -#endif #endif /* _ASM_SH_IO_SNAPGEAR_H */ diff --git a/trunk/arch/sh/include/mach-common/mach/systemh7751.h b/trunk/arch/sh/include/mach-common/mach/systemh7751.h deleted file mode 100644 index 4161122c84ef..000000000000 --- a/trunk/arch/sh/include/mach-common/mach/systemh7751.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef __ASM_SH_SYSTEMH_7751SYSTEMH_H -#define __ASM_SH_SYSTEMH_7751SYSTEMH_H - -/* - * linux/include/asm-sh/systemh/7751systemh.h - * - * Copyright (C) 2000 Kazumoto Kojima - * - * Hitachi SystemH support - - * Modified for 7751 SystemH by - * Jonathan Short, 2002. - */ - -/* Box specific addresses. */ - -#define PA_ROM 0x00000000 /* EPROM */ -#define PA_ROM_SIZE 0x00400000 /* EPROM size 4M byte */ -#define PA_FROM 0x01000000 /* EPROM */ -#define PA_FROM_SIZE 0x00400000 /* EPROM size 4M byte */ -#define PA_EXT1 0x04000000 -#define PA_EXT1_SIZE 0x04000000 -#define PA_EXT2 0x08000000 -#define PA_EXT2_SIZE 0x04000000 -#define PA_SDRAM 0x0c000000 -#define PA_SDRAM_SIZE 0x04000000 - -#define PA_EXT4 0x12000000 -#define PA_EXT4_SIZE 0x02000000 -#define PA_EXT5 0x14000000 -#define PA_EXT5_SIZE 0x04000000 -#define PA_PCIC 0x18000000 /* MR-SHPC-01 PCMCIA */ - -#define PA_DIPSW0 0xb9000000 /* Dip switch 5,6 */ -#define PA_DIPSW1 0xb9000002 /* Dip switch 7,8 */ -#define PA_LED 0xba000000 /* LED */ -#define PA_BCR 0xbb000000 /* FPGA on the MS7751SE01 */ - -#define PA_MRSHPC 0xb83fffe0 /* MR-SHPC-01 PCMCIA controller */ -#define PA_MRSHPC_MW1 0xb8400000 /* MR-SHPC-01 memory window base */ -#define PA_MRSHPC_MW2 0xb8500000 /* MR-SHPC-01 attribute window base */ -#define PA_MRSHPC_IO 0xb8600000 /* MR-SHPC-01 I/O window base */ -#define MRSHPC_MODE (PA_MRSHPC + 4) -#define MRSHPC_OPTION (PA_MRSHPC + 6) -#define MRSHPC_CSR (PA_MRSHPC + 8) -#define MRSHPC_ISR (PA_MRSHPC + 10) -#define MRSHPC_ICR (PA_MRSHPC + 12) -#define MRSHPC_CPWCR (PA_MRSHPC + 14) -#define MRSHPC_MW0CR1 (PA_MRSHPC + 16) -#define MRSHPC_MW1CR1 (PA_MRSHPC + 18) -#define MRSHPC_IOWCR1 (PA_MRSHPC + 20) -#define MRSHPC_MW0CR2 (PA_MRSHPC + 22) -#define MRSHPC_MW1CR2 (PA_MRSHPC + 24) -#define MRSHPC_IOWCR2 (PA_MRSHPC + 26) -#define MRSHPC_CDCR (PA_MRSHPC + 28) -#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30) - -#define BCR_ILCRA (PA_BCR + 0) -#define BCR_ILCRB (PA_BCR + 2) -#define BCR_ILCRC (PA_BCR + 4) -#define BCR_ILCRD (PA_BCR + 6) -#define BCR_ILCRE (PA_BCR + 8) -#define BCR_ILCRF (PA_BCR + 10) -#define BCR_ILCRG (PA_BCR + 12) - -#define IRQ_79C973 13 - -#define __IO_PREFIX sh7751systemh -#include - -#endif /* __ASM_SH_SYSTEMH_7751SYSTEMH_H */ diff --git a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index 2d9700c6b53a..0fe2e9329cb2 100644 --- a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -48,7 +48,7 @@ static struct clk r_clk = { * Default rate for the root input clock, reset this with clk_set_rate() * from the platform code. */ -struct clk extal_clk = { +static struct clk extal_clk = { .rate = 33333333, }; @@ -111,7 +111,7 @@ static struct clk div3_clk = { .parent = &pll_clk, }; -struct clk *main_clks[] = { +static struct clk *main_clks[] = { &r_clk, &extal_clk, &fll_clk, @@ -156,7 +156,7 @@ struct clk div4_clks[DIV4_NR] = { enum { DIV6_V, DIV6_FA, DIV6_FB, DIV6_I, DIV6_S, DIV6_NR }; -struct clk div6_clks[DIV6_NR] = { +static struct clk div6_clks[DIV6_NR] = { [DIV6_V] = SH_CLK_DIV6(&div3_clk, VCLKCR, 0), [DIV6_FA] = SH_CLK_DIV6(&div3_clk, FCLKACR, 0), [DIV6_FB] = SH_CLK_DIV6(&div3_clk, FCLKBCR, 0), diff --git a/trunk/arch/sh/mm/Kconfig b/trunk/arch/sh/mm/Kconfig index 09370392aff1..c3e61b366493 100644 --- a/trunk/arch/sh/mm/Kconfig +++ b/trunk/arch/sh/mm/Kconfig @@ -79,7 +79,7 @@ config 29BIT config 32BIT bool - default y if CPU_SH5 + default y if CPU_SH5 || !MMU config PMB bool "Support 32-bit physical addressing through PMB" diff --git a/trunk/arch/sh/mm/consistent.c b/trunk/arch/sh/mm/consistent.c index 038793286990..40733a952402 100644 --- a/trunk/arch/sh/mm/consistent.c +++ b/trunk/arch/sh/mm/consistent.c @@ -79,21 +79,20 @@ void dma_generic_free_coherent(struct device *dev, size_t size, void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { -#if defined(CONFIG_CPU_SH5) || defined(CONFIG_PMB) - void *p1addr = vaddr; -#else - void *p1addr = (void*) P1SEGADDR((unsigned long)vaddr); -#endif + void *addr; + + addr = __in_29bit_mode() ? + (void *)P1SEGADDR((unsigned long)vaddr) : vaddr; switch (direction) { case DMA_FROM_DEVICE: /* invalidate only */ - __flush_invalidate_region(p1addr, size); + __flush_invalidate_region(addr, size); break; case DMA_TO_DEVICE: /* writeback only */ - __flush_wback_region(p1addr, size); + __flush_wback_region(addr, size); break; case DMA_BIDIRECTIONAL: /* writeback and invalidate */ - __flush_purge_region(p1addr, size); + __flush_purge_region(addr, size); break; default: BUG(); diff --git a/trunk/arch/sh/mm/uncached.c b/trunk/arch/sh/mm/uncached.c index 8a4eca551fc0..a7767da815e9 100644 --- a/trunk/arch/sh/mm/uncached.c +++ b/trunk/arch/sh/mm/uncached.c @@ -28,7 +28,7 @@ EXPORT_SYMBOL(virt_addr_uncached); void __init uncached_init(void) { -#ifdef CONFIG_29BIT +#if defined(CONFIG_29BIT) || !defined(CONFIG_MMU) uncached_start = P2SEG; #else uncached_start = memory_end; diff --git a/trunk/arch/sh/tools/mach-types b/trunk/arch/sh/tools/mach-types index 9f56eb978024..0e68465e7b50 100644 --- a/trunk/arch/sh/tools/mach-types +++ b/trunk/arch/sh/tools/mach-types @@ -26,7 +26,6 @@ HD64461 HD64461 7724SE SH_7724_SOLUTION_ENGINE 7751SE SH_7751_SOLUTION_ENGINE 7780SE SH_7780_SOLUTION_ENGINE -7751SYSTEMH SH_7751_SYSTEMH HP6XX SH_HP6XX DREAMCAST SH_DREAMCAST SNAPGEAR SH_SECUREEDGE5410 diff --git a/trunk/arch/tile/include/asm/highmem.h b/trunk/arch/tile/include/asm/highmem.h index e0f7ee186721..b2a6c5de79ab 100644 --- a/trunk/arch/tile/include/asm/highmem.h +++ b/trunk/arch/tile/include/asm/highmem.h @@ -23,7 +23,6 @@ #include #include -#include #include #include diff --git a/trunk/arch/tile/include/asm/kmap_types.h b/trunk/arch/tile/include/asm/kmap_types.h index 1480106d1c05..3d0f20246260 100644 --- a/trunk/arch/tile/include/asm/kmap_types.h +++ b/trunk/arch/tile/include/asm/kmap_types.h @@ -16,28 +16,42 @@ #define _ASM_TILE_KMAP_TYPES_H /* - * In TILE Linux each set of four of these uses another 16MB chunk of - * address space, given 64 tiles and 64KB pages, so we only enable - * ones that are required by the kernel configuration. + * In 32-bit TILE Linux we have to balance the desire to have a lot of + * nested atomic mappings with the fact that large page sizes and many + * processors chew up address space quickly. In a typical + * 64-processor, 64KB-page layout build, making KM_TYPE_NR one larger + * adds 4MB of required address-space. For now we leave KM_TYPE_NR + * set to depth 8. */ enum km_type { + KM_TYPE_NR = 8 +}; + +/* + * We provide dummy definitions of all the stray values that used to be + * required for kmap_atomic() and no longer are. + */ +enum { KM_BOUNCE_READ, KM_SKB_SUNRPC_DATA, KM_SKB_DATA_SOFTIRQ, KM_USER0, KM_USER1, KM_BIO_SRC_IRQ, + KM_BIO_DST_IRQ, + KM_PTE0, + KM_PTE1, KM_IRQ0, KM_IRQ1, KM_SOFTIRQ0, KM_SOFTIRQ1, - KM_MEMCPY0, - KM_MEMCPY1, -#if defined(CONFIG_HIGHPTE) - KM_PTE0, - KM_PTE1, -#endif - KM_TYPE_NR + KM_SYNC_ICACHE, + KM_SYNC_DCACHE, + KM_UML_USERCOPY, + KM_IRQ_PTE, + KM_NMI, + KM_NMI_PTE, + KM_KDB }; #endif /* _ASM_TILE_KMAP_TYPES_H */ diff --git a/trunk/arch/tile/include/asm/pgtable.h b/trunk/arch/tile/include/asm/pgtable.h index dc4ccdd855bc..a6604e9485da 100644 --- a/trunk/arch/tile/include/asm/pgtable.h +++ b/trunk/arch/tile/include/asm/pgtable.h @@ -344,10 +344,8 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) #define pgd_offset_k(address) pgd_offset(&init_mm, address) #if defined(CONFIG_HIGHPTE) -extern pte_t *_pte_offset_map(pmd_t *, unsigned long address, enum km_type); -#define pte_offset_map(dir, address) \ - _pte_offset_map(dir, address, KM_PTE0) -#define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0) +extern pte_t *pte_offset_map(pmd_t *, unsigned long address); +#define pte_unmap(pte) kunmap_atomic(pte) #else #define pte_offset_map(dir, address) pte_offset_kernel(dir, address) #define pte_unmap(pte) do { } while (0) diff --git a/trunk/arch/tile/include/asm/stat.h b/trunk/arch/tile/include/asm/stat.h index 3dc90fa92c70..b16e5db8f0e7 100644 --- a/trunk/arch/tile/include/asm/stat.h +++ b/trunk/arch/tile/include/asm/stat.h @@ -1 +1,4 @@ +#ifdef CONFIG_COMPAT +#define __ARCH_WANT_STAT64 /* Used for compat_sys_stat64() etc. */ +#endif #include diff --git a/trunk/arch/tile/include/asm/unistd.h b/trunk/arch/tile/include/asm/unistd.h index f2e3ff485333..b35c2db71199 100644 --- a/trunk/arch/tile/include/asm/unistd.h +++ b/trunk/arch/tile/include/asm/unistd.h @@ -41,6 +41,7 @@ __SYSCALL(__NR_cmpxchg_badaddr, sys_cmpxchg_badaddr) #ifdef CONFIG_COMPAT #define __ARCH_WANT_SYS_LLSEEK #endif +#define __ARCH_WANT_SYS_NEWFSTATAT #endif #endif /* _ASM_TILE_UNISTD_H */ diff --git a/trunk/arch/tile/kernel/compat.c b/trunk/arch/tile/kernel/compat.c index 77739cdd9462..67617a05e602 100644 --- a/trunk/arch/tile/kernel/compat.c +++ b/trunk/arch/tile/kernel/compat.c @@ -148,11 +148,11 @@ long tile_compat_sys_msgrcv(int msqid, #define compat_sys_readahead sys32_readahead #define compat_sys_sync_file_range compat_sys_sync_file_range2 -/* The native 64-bit "struct stat" matches the 32-bit "struct stat64". */ -#define compat_sys_stat64 sys_newstat -#define compat_sys_lstat64 sys_newlstat -#define compat_sys_fstat64 sys_newfstat -#define compat_sys_fstatat64 sys_newfstatat +/* We leverage the "struct stat64" type for 32-bit time_t/nsec. */ +#define compat_sys_stat64 sys_stat64 +#define compat_sys_lstat64 sys_lstat64 +#define compat_sys_fstat64 sys_fstat64 +#define compat_sys_fstatat64 sys_fstatat64 /* The native sys_ptrace dynamically handles compat binaries. */ #define compat_sys_ptrace sys_ptrace diff --git a/trunk/arch/tile/kernel/early_printk.c b/trunk/arch/tile/kernel/early_printk.c index 2c54fd43a8a0..493a0e66d916 100644 --- a/trunk/arch/tile/kernel/early_printk.c +++ b/trunk/arch/tile/kernel/early_printk.c @@ -54,7 +54,7 @@ void early_printk(const char *fmt, ...) void early_panic(const char *fmt, ...) { va_list ap; - raw_local_irq_disable_all(); + arch_local_irq_disable_all(); va_start(ap, fmt); early_printk("Kernel panic - not syncing: "); early_vprintk(fmt, ap); diff --git a/trunk/arch/tile/kernel/hardwall.c b/trunk/arch/tile/kernel/hardwall.c index 1e54a7843410..e910530436e6 100644 --- a/trunk/arch/tile/kernel/hardwall.c +++ b/trunk/arch/tile/kernel/hardwall.c @@ -151,12 +151,12 @@ enum direction_protect { static void enable_firewall_interrupts(void) { - raw_local_irq_unmask_now(INT_UDN_FIREWALL); + arch_local_irq_unmask_now(INT_UDN_FIREWALL); } static void disable_firewall_interrupts(void) { - raw_local_irq_mask_now(INT_UDN_FIREWALL); + arch_local_irq_mask_now(INT_UDN_FIREWALL); } /* Set up hardwall on this cpu based on the passed hardwall_info. */ @@ -768,13 +768,13 @@ static int hardwall_release(struct inode *inode, struct file *file) } static const struct file_operations dev_hardwall_fops = { + .open = nonseekable_open, .unlocked_ioctl = hardwall_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = hardwall_compat_ioctl, #endif .flush = hardwall_flush, .release = hardwall_release, - .llseek = noop_llseek, }; static struct cdev hardwall_dev; diff --git a/trunk/arch/tile/kernel/irq.c b/trunk/arch/tile/kernel/irq.c index e63917687e99..128805ef8f2c 100644 --- a/trunk/arch/tile/kernel/irq.c +++ b/trunk/arch/tile/kernel/irq.c @@ -26,7 +26,7 @@ #define IS_HW_CLEARED 1 /* - * The set of interrupts we enable for raw_local_irq_enable(). + * The set of interrupts we enable for arch_local_irq_enable(). * This is initialized to have just a single interrupt that the kernel * doesn't actually use as a sentinel. During kernel init, * interrupts are added as the kernel gets prepared to support them. @@ -225,7 +225,7 @@ void __cpuinit setup_irq_regs(void) /* Enable interrupt delivery. */ unmask_irqs(~0UL); #if CHIP_HAS_IPI() - raw_local_irq_unmask(INT_IPI_K); + arch_local_irq_unmask(INT_IPI_K); #endif } diff --git a/trunk/arch/tile/kernel/machine_kexec.c b/trunk/arch/tile/kernel/machine_kexec.c index ba7a265d6179..0d8b9e933487 100644 --- a/trunk/arch/tile/kernel/machine_kexec.c +++ b/trunk/arch/tile/kernel/machine_kexec.c @@ -182,13 +182,13 @@ static void kexec_find_and_set_command_line(struct kimage *image) if ((entry & IND_SOURCE)) { void *va = - kmap_atomic_pfn(entry >> PAGE_SHIFT, KM_USER0); + kmap_atomic_pfn(entry >> PAGE_SHIFT); r = kexec_bn2cl(va); if (r) { command_line = r; break; } - kunmap_atomic(va, KM_USER0); + kunmap_atomic(va); } } @@ -198,7 +198,7 @@ static void kexec_find_and_set_command_line(struct kimage *image) hverr = hv_set_command_line( (HV_VirtAddr) command_line, strlen(command_line)); - kunmap_atomic(command_line, KM_USER0); + kunmap_atomic(command_line); } else { pr_info("%s: no command line found; making empty\n", __func__); diff --git a/trunk/arch/tile/kernel/messaging.c b/trunk/arch/tile/kernel/messaging.c index 997e3933f726..0858ee6b520f 100644 --- a/trunk/arch/tile/kernel/messaging.c +++ b/trunk/arch/tile/kernel/messaging.c @@ -34,7 +34,7 @@ void __cpuinit init_messaging(void) panic("hv_register_message_state: error %d", rc); /* Make sure downcall interrupts will be enabled. */ - raw_local_irq_unmask(INT_INTCTRL_K); + arch_local_irq_unmask(INT_INTCTRL_K); } void hv_message_intr(struct pt_regs *regs, int intnum) diff --git a/trunk/arch/tile/kernel/ptrace.c b/trunk/arch/tile/kernel/ptrace.c index 9cd29884c09f..e92e40527d6d 100644 --- a/trunk/arch/tile/kernel/ptrace.c +++ b/trunk/arch/tile/kernel/ptrace.c @@ -50,10 +50,10 @@ long arch_ptrace(struct task_struct *child, long request, { unsigned long __user *datap = (long __user __force *)data; unsigned long tmp; - int i; long ret = -EIO; - unsigned long *childregs; char *childreg; + struct pt_regs copyregs; + int ex1_offset; switch (request) { @@ -80,6 +80,16 @@ long arch_ptrace(struct task_struct *child, long request, if (addr >= PTREGS_SIZE) break; childreg = (char *)task_pt_regs(child) + addr; + + /* Guard against overwrites of the privilege level. */ + ex1_offset = PTREGS_OFFSET_EX1; +#if defined(CONFIG_COMPAT) && defined(__BIG_ENDIAN) + if (is_compat_task()) /* point at low word */ + ex1_offset += sizeof(compat_long_t); +#endif + if (addr == ex1_offset) + data = PL_ICS_EX1(USER_PL, EX1_ICS(data)); + #ifdef CONFIG_COMPAT if (is_compat_task()) { if (addr & (sizeof(compat_long_t)-1)) @@ -96,26 +106,19 @@ long arch_ptrace(struct task_struct *child, long request, break; case PTRACE_GETREGS: /* Get all registers from the child. */ - if (!access_ok(VERIFY_WRITE, datap, PTREGS_SIZE)) - break; - childregs = (long *)task_pt_regs(child); - for (i = 0; i < sizeof(struct pt_regs)/sizeof(unsigned long); - ++i) { - ret = __put_user(childregs[i], &datap[i]); - if (ret != 0) - break; + if (copy_to_user(datap, task_pt_regs(child), + sizeof(struct pt_regs)) == 0) { + ret = 0; } break; case PTRACE_SETREGS: /* Set all registers in the child. */ - if (!access_ok(VERIFY_READ, datap, PTREGS_SIZE)) - break; - childregs = (long *)task_pt_regs(child); - for (i = 0; i < sizeof(struct pt_regs)/sizeof(unsigned long); - ++i) { - ret = __get_user(childregs[i], &datap[i]); - if (ret != 0) - break; + if (copy_from_user(©regs, datap, + sizeof(struct pt_regs)) == 0) { + copyregs.ex1 = + PL_ICS_EX1(USER_PL, EX1_ICS(copyregs.ex1)); + *task_pt_regs(child) = copyregs; + ret = 0; } break; diff --git a/trunk/arch/tile/kernel/reboot.c b/trunk/arch/tile/kernel/reboot.c index acd86d20beba..baa3d905fee2 100644 --- a/trunk/arch/tile/kernel/reboot.c +++ b/trunk/arch/tile/kernel/reboot.c @@ -27,7 +27,7 @@ void machine_halt(void) { warn_early_printk(); - raw_local_irq_disable_all(); + arch_local_irq_disable_all(); smp_send_stop(); hv_halt(); } @@ -35,14 +35,14 @@ void machine_halt(void) void machine_power_off(void) { warn_early_printk(); - raw_local_irq_disable_all(); + arch_local_irq_disable_all(); smp_send_stop(); hv_power_off(); } void machine_restart(char *cmd) { - raw_local_irq_disable_all(); + arch_local_irq_disable_all(); smp_send_stop(); hv_restart((HV_VirtAddr) "vmlinux", (HV_VirtAddr) cmd); } diff --git a/trunk/arch/tile/kernel/setup.c b/trunk/arch/tile/kernel/setup.c index ae51cad12da0..fb0b3cbeae14 100644 --- a/trunk/arch/tile/kernel/setup.c +++ b/trunk/arch/tile/kernel/setup.c @@ -868,14 +868,14 @@ void __cpuinit setup_cpu(int boot) /* Allow asynchronous TLB interrupts. */ #if CHIP_HAS_TILE_DMA() - raw_local_irq_unmask(INT_DMATLB_MISS); - raw_local_irq_unmask(INT_DMATLB_ACCESS); + arch_local_irq_unmask(INT_DMATLB_MISS); + arch_local_irq_unmask(INT_DMATLB_ACCESS); #endif #if CHIP_HAS_SN_PROC() - raw_local_irq_unmask(INT_SNITLB_MISS); + arch_local_irq_unmask(INT_SNITLB_MISS); #endif #ifdef __tilegx__ - raw_local_irq_unmask(INT_SINGLE_STEP_K); + arch_local_irq_unmask(INT_SINGLE_STEP_K); #endif /* diff --git a/trunk/arch/tile/kernel/signal.c b/trunk/arch/tile/kernel/signal.c index fb28e85ae3ae..687719d4abd1 100644 --- a/trunk/arch/tile/kernel/signal.c +++ b/trunk/arch/tile/kernel/signal.c @@ -71,6 +71,9 @@ int restore_sigcontext(struct pt_regs *regs, for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) err |= __get_user(regs->regs[i], &sc->gregs[i]); + /* Ensure that the PL is always set to USER_PL. */ + regs->ex1 = PL_ICS_EX1(USER_PL, EX1_ICS(regs->ex1)); + regs->faultnum = INT_SWINT_1_SIGRETURN; err |= __get_user(*pr0, &sc->gregs[0]); @@ -330,7 +333,7 @@ void do_signal(struct pt_regs *regs) current_thread_info()->status &= ~TS_RESTORE_SIGMASK; } - return; + goto done; } /* Did we come from a system call? */ @@ -358,4 +361,8 @@ void do_signal(struct pt_regs *regs) current_thread_info()->status &= ~TS_RESTORE_SIGMASK; sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } + +done: + /* Avoid double syscall restart if there are nested signals. */ + regs->faultnum = INT_SWINT_1_SIGRETURN; } diff --git a/trunk/arch/tile/kernel/smp.c b/trunk/arch/tile/kernel/smp.c index 75255d90aff3..9575b37a8b75 100644 --- a/trunk/arch/tile/kernel/smp.c +++ b/trunk/arch/tile/kernel/smp.c @@ -115,7 +115,7 @@ static void smp_start_cpu_interrupt(void) static void smp_stop_cpu_interrupt(void) { set_cpu_online(smp_processor_id(), 0); - raw_local_irq_disable_all(); + arch_local_irq_disable_all(); for (;;) asm("nap"); } diff --git a/trunk/arch/tile/kernel/time.c b/trunk/arch/tile/kernel/time.c index 6bed820e1421..f2e156e44692 100644 --- a/trunk/arch/tile/kernel/time.c +++ b/trunk/arch/tile/kernel/time.c @@ -132,7 +132,7 @@ static int tile_timer_set_next_event(unsigned long ticks, { BUG_ON(ticks > MAX_TICK); __insn_mtspr(SPR_TILE_TIMER_CONTROL, ticks); - raw_local_irq_unmask_now(INT_TILE_TIMER); + arch_local_irq_unmask_now(INT_TILE_TIMER); return 0; } @@ -143,7 +143,7 @@ static int tile_timer_set_next_event(unsigned long ticks, static void tile_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { - raw_local_irq_mask_now(INT_TILE_TIMER); + arch_local_irq_mask_now(INT_TILE_TIMER); } /* @@ -172,7 +172,7 @@ void __cpuinit setup_tile_timer(void) evt->cpumask = cpumask_of(smp_processor_id()); /* Start out with timer not firing. */ - raw_local_irq_mask_now(INT_TILE_TIMER); + arch_local_irq_mask_now(INT_TILE_TIMER); /* Register tile timer. */ clockevents_register_device(evt); @@ -188,7 +188,7 @@ void do_timer_interrupt(struct pt_regs *regs, int fault_num) * Mask the timer interrupt here, since we are a oneshot timer * and there are now by definition no events pending. */ - raw_local_irq_mask(INT_TILE_TIMER); + arch_local_irq_mask(INT_TILE_TIMER); /* Track time spent here in an interrupt context */ irq_enter(); diff --git a/trunk/arch/tile/lib/memcpy_tile64.c b/trunk/arch/tile/lib/memcpy_tile64.c index dfedea7b266b..f7d4a6ad61e8 100644 --- a/trunk/arch/tile/lib/memcpy_tile64.c +++ b/trunk/arch/tile/lib/memcpy_tile64.c @@ -54,7 +54,7 @@ typedef unsigned long (*memcpy_t)(void *, const void *, unsigned long); * we must run with interrupts disabled to avoid the risk of some * other code seeing the incoherent data in our cache. (Recall that * our cache is indexed by PA, so even if the other code doesn't use - * our KM_MEMCPY virtual addresses, they'll still hit in cache using + * our kmap_atomic virtual addresses, they'll still hit in cache using * the normal VAs that aren't supposed to hit in cache.) */ static void memcpy_multicache(void *dest, const void *source, @@ -64,6 +64,7 @@ static void memcpy_multicache(void *dest, const void *source, unsigned long flags, newsrc, newdst; pmd_t *pmdp; pte_t *ptep; + int type0, type1; int cpu = get_cpu(); /* @@ -77,7 +78,8 @@ static void memcpy_multicache(void *dest, const void *source, sim_allow_multiple_caching(1); /* Set up the new dest mapping */ - idx = FIX_KMAP_BEGIN + (KM_TYPE_NR * cpu) + KM_MEMCPY0; + type0 = kmap_atomic_idx_push(); + idx = FIX_KMAP_BEGIN + (KM_TYPE_NR * cpu) + type0; newdst = __fix_to_virt(idx) + ((unsigned long)dest & (PAGE_SIZE-1)); pmdp = pmd_offset(pud_offset(pgd_offset_k(newdst), newdst), newdst); ptep = pte_offset_kernel(pmdp, newdst); @@ -87,7 +89,8 @@ static void memcpy_multicache(void *dest, const void *source, } /* Set up the new source mapping */ - idx += (KM_MEMCPY0 - KM_MEMCPY1); + type1 = kmap_atomic_idx_push(); + idx += (type0 - type1); src_pte = hv_pte_set_nc(src_pte); src_pte = hv_pte_clear_writable(src_pte); /* be paranoid */ newsrc = __fix_to_virt(idx) + ((unsigned long)source & (PAGE_SIZE-1)); @@ -119,6 +122,8 @@ static void memcpy_multicache(void *dest, const void *source, * We're done: notify the simulator that all is back to normal, * and re-enable interrupts and pre-emption. */ + kmap_atomic_idx_pop(); + kmap_atomic_idx_pop(); sim_allow_multiple_caching(0); local_irq_restore(flags); put_cpu(); diff --git a/trunk/arch/tile/mm/highmem.c b/trunk/arch/tile/mm/highmem.c index abb57331cf6e..31dbbd9afe47 100644 --- a/trunk/arch/tile/mm/highmem.c +++ b/trunk/arch/tile/mm/highmem.c @@ -227,7 +227,7 @@ EXPORT_SYMBOL(kmap_atomic_prot); void *__kmap_atomic(struct page *page) { /* PAGE_NONE is a magic value that tells us to check immutability. */ - return kmap_atomic_prot(page, type, PAGE_NONE); + return kmap_atomic_prot(page, PAGE_NONE); } EXPORT_SYMBOL(__kmap_atomic); diff --git a/trunk/arch/tile/mm/init.c b/trunk/arch/tile/mm/init.c index 78e1982cb6c9..0b9ce69b0ee5 100644 --- a/trunk/arch/tile/mm/init.c +++ b/trunk/arch/tile/mm/init.c @@ -988,8 +988,12 @@ static long __write_once initfree = 1; /* Select whether to free (1) or mark unusable (0) the __init pages. */ static int __init set_initfree(char *str) { - strict_strtol(str, 0, &initfree); - pr_info("initfree: %s free init pages\n", initfree ? "will" : "won't"); + long val; + if (strict_strtol(str, 0, &val)) { + initfree = val; + pr_info("initfree: %s free init pages\n", + initfree ? "will" : "won't"); + } return 1; } __setup("initfree=", set_initfree); diff --git a/trunk/arch/tile/mm/pgtable.c b/trunk/arch/tile/mm/pgtable.c index 335c24621c41..1f5430c53d0d 100644 --- a/trunk/arch/tile/mm/pgtable.c +++ b/trunk/arch/tile/mm/pgtable.c @@ -134,9 +134,9 @@ void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t flags) } #if defined(CONFIG_HIGHPTE) -pte_t *_pte_offset_map(pmd_t *dir, unsigned long address, enum km_type type) +pte_t *_pte_offset_map(pmd_t *dir, unsigned long address) { - pte_t *pte = kmap_atomic(pmd_page(*dir), type) + + pte_t *pte = kmap_atomic(pmd_page(*dir)) + (pmd_ptfn(*dir) << HV_LOG2_PAGE_TABLE_ALIGN) & ~PAGE_MASK; return &pte[pte_index(address)]; } diff --git a/trunk/arch/x86/kvm/mmu.c b/trunk/arch/x86/kvm/mmu.c index 908ea5464a51..fb8b376bf28c 100644 --- a/trunk/arch/x86/kvm/mmu.c +++ b/trunk/arch/x86/kvm/mmu.c @@ -720,7 +720,7 @@ static void rmap_remove(struct kvm *kvm, u64 *spte) } } -static void set_spte_track_bits(u64 *sptep, u64 new_spte) +static int set_spte_track_bits(u64 *sptep, u64 new_spte) { pfn_t pfn; u64 old_spte = *sptep; @@ -731,19 +731,20 @@ static void set_spte_track_bits(u64 *sptep, u64 new_spte) old_spte = __xchg_spte(sptep, new_spte); if (!is_rmap_spte(old_spte)) - return; + return 0; pfn = spte_to_pfn(old_spte); if (!shadow_accessed_mask || old_spte & shadow_accessed_mask) kvm_set_pfn_accessed(pfn); if (!shadow_dirty_mask || (old_spte & shadow_dirty_mask)) kvm_set_pfn_dirty(pfn); + return 1; } static void drop_spte(struct kvm *kvm, u64 *sptep, u64 new_spte) { - set_spte_track_bits(sptep, new_spte); - rmap_remove(kvm, sptep); + if (set_spte_track_bits(sptep, new_spte)) + rmap_remove(kvm, sptep); } static u64 *rmap_next(struct kvm *kvm, unsigned long *rmapp, u64 *spte) diff --git a/trunk/arch/x86/kvm/x86.c b/trunk/arch/x86/kvm/x86.c index 2288ad829b32..cdac9e592aa5 100644 --- a/trunk/arch/x86/kvm/x86.c +++ b/trunk/arch/x86/kvm/x86.c @@ -2560,6 +2560,7 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu, !kvm_exception_is_soft(vcpu->arch.exception.nr); events->exception.nr = vcpu->arch.exception.nr; events->exception.has_error_code = vcpu->arch.exception.has_error_code; + events->exception.pad = 0; events->exception.error_code = vcpu->arch.exception.error_code; events->interrupt.injected = @@ -2573,12 +2574,14 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu, events->nmi.injected = vcpu->arch.nmi_injected; events->nmi.pending = vcpu->arch.nmi_pending; events->nmi.masked = kvm_x86_ops->get_nmi_mask(vcpu); + events->nmi.pad = 0; events->sipi_vector = vcpu->arch.sipi_vector; events->flags = (KVM_VCPUEVENT_VALID_NMI_PENDING | KVM_VCPUEVENT_VALID_SIPI_VECTOR | KVM_VCPUEVENT_VALID_SHADOW); + memset(&events->reserved, 0, sizeof(events->reserved)); } static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu, @@ -2623,6 +2626,7 @@ static void kvm_vcpu_ioctl_x86_get_debugregs(struct kvm_vcpu *vcpu, dbgregs->dr6 = vcpu->arch.dr6; dbgregs->dr7 = vcpu->arch.dr7; dbgregs->flags = 0; + memset(&dbgregs->reserved, 0, sizeof(dbgregs->reserved)); } static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu, @@ -3106,6 +3110,7 @@ static int kvm_vm_ioctl_get_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps) sizeof(ps->channels)); ps->flags = kvm->arch.vpit->pit_state.flags; mutex_unlock(&kvm->arch.vpit->pit_state.lock); + memset(&ps->reserved, 0, sizeof(ps->reserved)); return r; } @@ -3169,10 +3174,6 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_memslots *slots, *old_slots; unsigned long *dirty_bitmap; - spin_lock(&kvm->mmu_lock); - kvm_mmu_slot_remove_write_access(kvm, log->slot); - spin_unlock(&kvm->mmu_lock); - r = -ENOMEM; dirty_bitmap = vmalloc(n); if (!dirty_bitmap) @@ -3194,6 +3195,10 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, dirty_bitmap = old_slots->memslots[log->slot].dirty_bitmap; kfree(old_slots); + spin_lock(&kvm->mmu_lock); + kvm_mmu_slot_remove_write_access(kvm, log->slot); + spin_unlock(&kvm->mmu_lock); + r = -EFAULT; if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n)) { vfree(dirty_bitmap); @@ -3486,6 +3491,7 @@ long kvm_arch_vm_ioctl(struct file *filp, user_ns.clock = kvm->arch.kvmclock_offset + now_ns; local_irq_enable(); user_ns.flags = 0; + memset(&user_ns.pad, 0, sizeof(user_ns.pad)); r = -EFAULT; if (copy_to_user(argp, &user_ns, sizeof(user_ns))) @@ -3972,8 +3978,10 @@ int kvm_emulate_wbinvd(struct kvm_vcpu *vcpu) return X86EMUL_CONTINUE; if (kvm_x86_ops->has_wbinvd_exit()) { + preempt_disable(); smp_call_function_many(vcpu->arch.wbinvd_dirty_mask, wbinvd_ipi, NULL, 1); + preempt_enable(); cpumask_clear(vcpu->arch.wbinvd_dirty_mask); } wbinvd(); diff --git a/trunk/drivers/Makefile b/trunk/drivers/Makefile index 14cf9077bb2b..f3ebb30f1b7f 100644 --- a/trunk/drivers/Makefile +++ b/trunk/drivers/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_REGULATOR) += regulator/ # char/ comes before serial/ etc so that the VT console is the boot-time # default. +obj-y += tty/ obj-y += char/ # gpu/ comes after char for AGP vs DRM startup diff --git a/trunk/drivers/block/floppy.c b/trunk/drivers/block/floppy.c index 767107cce982..3951020e494a 100644 --- a/trunk/drivers/block/floppy.c +++ b/trunk/drivers/block/floppy.c @@ -4363,9 +4363,9 @@ static int __init floppy_init(void) out_put_disk: while (dr--) { del_timer(&motor_off_timer[dr]); - put_disk(disks[dr]); if (disks[dr]->queue) blk_cleanup_queue(disks[dr]->queue); + put_disk(disks[dr]); } return err; } @@ -4573,8 +4573,8 @@ static void __exit floppy_module_exit(void) device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos); platform_device_unregister(&floppy_device[drive]); } - put_disk(disks[drive]); blk_cleanup_queue(disks[drive]->queue); + put_disk(disks[drive]); } del_timer_sync(&fd_timeout); diff --git a/trunk/drivers/char/Makefile b/trunk/drivers/char/Makefile index 3a9c01416839..ba53ec956c95 100644 --- a/trunk/drivers/char/Makefile +++ b/trunk/drivers/char/Makefile @@ -2,24 +2,10 @@ # Makefile for the kernel character device drivers. # -# -# This file contains the font map for the default (hardware) font -# -FONTMAPFILE = cp437.uni - -obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o - -obj-y += tty_mutex.o -obj-$(CONFIG_LEGACY_PTYS) += pty.o -obj-$(CONFIG_UNIX98_PTYS) += pty.o +obj-y += mem.o random.o obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o obj-y += misc.o -obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o obj-$(CONFIG_BFIN_JTAG_COMM) += bfin_jtag_comm.o -obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o -obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o -obj-$(CONFIG_AUDIT) += tty_audit.o -obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o @@ -41,8 +27,6 @@ obj-$(CONFIG_ISI) += isicom.o obj-$(CONFIG_SYNCLINK) += synclink.o obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o -obj-$(CONFIG_N_HDLC) += n_hdlc.o -obj-$(CONFIG_N_GSM) += n_gsm.o obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o obj-$(CONFIG_SX) += sx.o generic_serial.o obj-$(CONFIG_RIO) += rio/ generic_serial.o @@ -74,7 +58,6 @@ obj-$(CONFIG_PRINTER) += lp.o obj-$(CONFIG_APM_EMULATION) += apm-emulation.o obj-$(CONFIG_DTLK) += dtlk.o -obj-$(CONFIG_R3964) += n_r3964.o obj-$(CONFIG_APPLICOM) += applicom.o obj-$(CONFIG_SONYPI) += sonypi.o obj-$(CONFIG_RTC) += rtc.o @@ -115,28 +98,3 @@ obj-$(CONFIG_RAMOOPS) += ramoops.o obj-$(CONFIG_JS_RTC) += js-rtc.o js-rtc-y = rtc.o - -# Files generated that shall be removed upon make clean -clean-files := consolemap_deftbl.c defkeymap.c - -quiet_cmd_conmk = CONMK $@ - cmd_conmk = scripts/conmakehash $< > $@ - -$(obj)/consolemap_deftbl.c: $(src)/$(FONTMAPFILE) - $(call cmd,conmk) - -$(obj)/defkeymap.o: $(obj)/defkeymap.c - -# Uncomment if you're changing the keymap and have an appropriate -# loadkeys version for the map. By default, we'll use the shipped -# versions. -# GENERATE_KEYMAP := 1 - -ifdef GENERATE_KEYMAP - -$(obj)/defkeymap.c: $(obj)/%.c: $(src)/%.map - loadkeys --mktable $< > $@.tmp - sed -e 's/^static *//' $@.tmp > $@ - rm $@.tmp - -endif diff --git a/trunk/drivers/clocksource/sh_cmt.c b/trunk/drivers/clocksource/sh_cmt.c index a44611652282..d68d3aa1814b 100644 --- a/trunk/drivers/clocksource/sh_cmt.c +++ b/trunk/drivers/clocksource/sh_cmt.c @@ -616,13 +616,9 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) /* get hold of clock */ p->clk = clk_get(&p->pdev->dev, "cmt_fck"); if (IS_ERR(p->clk)) { - dev_warn(&p->pdev->dev, "using deprecated clock lookup\n"); - p->clk = clk_get(&p->pdev->dev, cfg->clk); - if (IS_ERR(p->clk)) { - dev_err(&p->pdev->dev, "cannot get clock\n"); - ret = PTR_ERR(p->clk); - goto err1; - } + dev_err(&p->pdev->dev, "cannot get clock\n"); + ret = PTR_ERR(p->clk); + goto err1; } if (resource_size(res) == 6) { diff --git a/trunk/drivers/clocksource/sh_mtu2.c b/trunk/drivers/clocksource/sh_mtu2.c index ef7a5be8a09f..40630cb98237 100644 --- a/trunk/drivers/clocksource/sh_mtu2.c +++ b/trunk/drivers/clocksource/sh_mtu2.c @@ -287,13 +287,9 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) /* get hold of clock */ p->clk = clk_get(&p->pdev->dev, "mtu2_fck"); if (IS_ERR(p->clk)) { - dev_warn(&p->pdev->dev, "using deprecated clock lookup\n"); - p->clk = clk_get(&p->pdev->dev, cfg->clk); - if (IS_ERR(p->clk)) { - dev_err(&p->pdev->dev, "cannot get clock\n"); - ret = PTR_ERR(p->clk); - goto err1; - } + dev_err(&p->pdev->dev, "cannot get clock\n"); + ret = PTR_ERR(p->clk); + goto err1; } return sh_mtu2_register(p, (char *)dev_name(&p->pdev->dev), diff --git a/trunk/drivers/clocksource/sh_tmu.c b/trunk/drivers/clocksource/sh_tmu.c index de715901b82a..36aba9923060 100644 --- a/trunk/drivers/clocksource/sh_tmu.c +++ b/trunk/drivers/clocksource/sh_tmu.c @@ -393,13 +393,9 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev) /* get hold of clock */ p->clk = clk_get(&p->pdev->dev, "tmu_fck"); if (IS_ERR(p->clk)) { - dev_warn(&p->pdev->dev, "using deprecated clock lookup\n"); - p->clk = clk_get(&p->pdev->dev, cfg->clk); - if (IS_ERR(p->clk)) { - dev_err(&p->pdev->dev, "cannot get clock\n"); - ret = PTR_ERR(p->clk); - goto err1; - } + dev_err(&p->pdev->dev, "cannot get clock\n"); + ret = PTR_ERR(p->clk); + goto err1; } return sh_tmu_register(p, (char *)dev_name(&p->pdev->dev), diff --git a/trunk/drivers/firewire/ohci.c b/trunk/drivers/firewire/ohci.c index 9dcb17d51aee..84eb607d6c03 100644 --- a/trunk/drivers/firewire/ohci.c +++ b/trunk/drivers/firewire/ohci.c @@ -577,17 +577,11 @@ static int ohci_update_phy_reg(struct fw_card *card, int addr, return ret; } -static int ar_context_add_page(struct ar_context *ctx) +static void ar_context_link_page(struct ar_context *ctx, + struct ar_buffer *ab, dma_addr_t ab_bus) { - struct device *dev = ctx->ohci->card.device; - struct ar_buffer *ab; - dma_addr_t uninitialized_var(ab_bus); size_t offset; - ab = dma_alloc_coherent(dev, PAGE_SIZE, &ab_bus, GFP_ATOMIC); - if (ab == NULL) - return -ENOMEM; - ab->next = NULL; memset(&ab->descriptor, 0, sizeof(ab->descriptor)); ab->descriptor.control = cpu_to_le16(DESCRIPTOR_INPUT_MORE | @@ -606,6 +600,19 @@ static int ar_context_add_page(struct ar_context *ctx) reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); flush_writes(ctx->ohci); +} + +static int ar_context_add_page(struct ar_context *ctx) +{ + struct device *dev = ctx->ohci->card.device; + struct ar_buffer *ab; + dma_addr_t uninitialized_var(ab_bus); + + ab = dma_alloc_coherent(dev, PAGE_SIZE, &ab_bus, GFP_ATOMIC); + if (ab == NULL) + return -ENOMEM; + + ar_context_link_page(ctx, ab, ab_bus); return 0; } @@ -730,16 +737,17 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer) static void ar_context_tasklet(unsigned long data) { struct ar_context *ctx = (struct ar_context *)data; - struct fw_ohci *ohci = ctx->ohci; struct ar_buffer *ab; struct descriptor *d; void *buffer, *end; + __le16 res_count; ab = ctx->current_buffer; d = &ab->descriptor; - if (d->res_count == 0) { - size_t size, rest, offset; + res_count = ACCESS_ONCE(d->res_count); + if (res_count == 0) { + size_t size, size2, rest, pktsize, size3, offset; dma_addr_t start_bus; void *start; @@ -750,29 +758,63 @@ static void ar_context_tasklet(unsigned long data) */ offset = offsetof(struct ar_buffer, data); - start = buffer = ab; + start = ab; start_bus = le32_to_cpu(ab->descriptor.data_address) - offset; + buffer = ab->data; ab = ab->next; d = &ab->descriptor; - size = buffer + PAGE_SIZE - ctx->pointer; + size = start + PAGE_SIZE - ctx->pointer; + /* valid buffer data in the next page */ rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count); + /* what actually fits in this page */ + size2 = min(rest, (size_t)PAGE_SIZE - offset - size); memmove(buffer, ctx->pointer, size); - memcpy(buffer + size, ab->data, rest); - ctx->current_buffer = ab; - ctx->pointer = (void *) ab->data + rest; - end = buffer + size + rest; + memcpy(buffer + size, ab->data, size2); + + while (size > 0) { + void *next = handle_ar_packet(ctx, buffer); + pktsize = next - buffer; + if (pktsize >= size) { + /* + * We have handled all the data that was + * originally in this page, so we can now + * continue in the next page. + */ + buffer = next; + break; + } + /* move the next packet to the start of the buffer */ + memmove(buffer, next, size + size2 - pktsize); + size -= pktsize; + /* fill up this page again */ + size3 = min(rest - size2, + (size_t)PAGE_SIZE - offset - size - size2); + memcpy(buffer + size + size2, + (void *) ab->data + size2, size3); + size2 += size3; + } - while (buffer < end) - buffer = handle_ar_packet(ctx, buffer); + if (rest > 0) { + /* handle the packets that are fully in the next page */ + buffer = (void *) ab->data + + (buffer - (start + offset + size)); + end = (void *) ab->data + rest; + + while (buffer < end) + buffer = handle_ar_packet(ctx, buffer); - dma_free_coherent(ohci->card.device, PAGE_SIZE, - start, start_bus); - ar_context_add_page(ctx); + ctx->current_buffer = ab; + ctx->pointer = end; + + ar_context_link_page(ctx, start, start_bus); + } else { + ctx->pointer = start + PAGE_SIZE; + } } else { buffer = ctx->pointer; ctx->pointer = end = - (void *) ab + PAGE_SIZE - le16_to_cpu(d->res_count); + (void *) ab + PAGE_SIZE - le16_to_cpu(res_count); while (buffer < end) buffer = handle_ar_packet(ctx, buffer); diff --git a/trunk/drivers/hwmon/ltc4261.c b/trunk/drivers/hwmon/ltc4261.c index 267626178678..4b50601027d3 100644 --- a/trunk/drivers/hwmon/ltc4261.c +++ b/trunk/drivers/hwmon/ltc4261.c @@ -82,7 +82,7 @@ static struct ltc4261_data *ltc4261_update_device(struct device *dev) val = i2c_smbus_read_byte_data(client, i); if (unlikely(val < 0)) { dev_dbg(dev, - "Failed to read ADC value: error %d", + "Failed to read ADC value: error %d\n", val); ret = ERR_PTR(val); goto abort; @@ -230,8 +230,7 @@ static int ltc4261_probe(struct i2c_client *client, return -ENODEV; if (i2c_smbus_read_byte_data(client, LTC4261_STATUS) < 0) { - dev_err(&client->dev, "Failed to read register %d:%02x:%02x\n", - adapter->id, client->addr, LTC4261_STATUS); + dev_err(&client->dev, "Failed to read status register\n"); return -ENODEV; } diff --git a/trunk/drivers/isdn/hisax/isar.c b/trunk/drivers/isdn/hisax/isar.c index 40b914bded8c..2e72227bd071 100644 --- a/trunk/drivers/isdn/hisax/isar.c +++ b/trunk/drivers/isdn/hisax/isar.c @@ -1427,8 +1427,8 @@ modeisar(struct BCState *bcs, int mode, int bc) &bcs->hw.isar.reg->Flags)) bcs->hw.isar.dpath = 1; else { - printk(KERN_WARNING"isar modeisar analog funktions only with DP1\n"); - debugl1(cs, "isar modeisar analog funktions only with DP1"); + printk(KERN_WARNING"isar modeisar analog functions only with DP1\n"); + debugl1(cs, "isar modeisar analog functions only with DP1"); return(1); } break; diff --git a/trunk/drivers/leds/leds-net5501.c b/trunk/drivers/leds/leds-net5501.c index 3063f591f0dc..1739557a9038 100644 --- a/trunk/drivers/leds/leds-net5501.c +++ b/trunk/drivers/leds/leds-net5501.c @@ -92,3 +92,5 @@ static int __init soekris_init(void) } arch_initcall(soekris_init); + +MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/net/atlx/atl1.c b/trunk/drivers/net/atlx/atl1.c index 43579b3b24ac..53363108994e 100644 --- a/trunk/drivers/net/atlx/atl1.c +++ b/trunk/drivers/net/atlx/atl1.c @@ -3043,7 +3043,6 @@ static int __devinit atl1_probe(struct pci_dev *pdev, atl1_pcie_patch(adapter); /* assume we have no link for now */ netif_carrier_off(netdev); - netif_stop_queue(netdev); setup_timer(&adapter->phy_config_timer, atl1_phy_config, (unsigned long)adapter); diff --git a/trunk/drivers/net/bnx2x/bnx2x.h b/trunk/drivers/net/bnx2x/bnx2x.h index 9eea225decaf..863e73a85fbe 100644 --- a/trunk/drivers/net/bnx2x/bnx2x.h +++ b/trunk/drivers/net/bnx2x/bnx2x.h @@ -20,8 +20,8 @@ * (you will need to reboot afterwards) */ /* #define BNX2X_STOP_ON_ERROR */ -#define DRV_MODULE_VERSION "1.60.00-3" -#define DRV_MODULE_RELDATE "2010/10/19" +#define DRV_MODULE_VERSION "1.60.00-4" +#define DRV_MODULE_RELDATE "2010/11/01" #define BNX2X_BC_VER 0x040200 #define BNX2X_MULTI_QUEUE diff --git a/trunk/drivers/net/bnx2x/bnx2x_hsi.h b/trunk/drivers/net/bnx2x/bnx2x_hsi.h index 18c8e23a0e82..4cfd4e9b5586 100644 --- a/trunk/drivers/net/bnx2x/bnx2x_hsi.h +++ b/trunk/drivers/net/bnx2x/bnx2x_hsi.h @@ -244,7 +244,14 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */ u16 xgxs_config_tx[4]; /* 0x1A0 */ - u32 Reserved1[57]; /* 0x1A8 */ + u32 Reserved1[56]; /* 0x1A8 */ + u32 default_cfg; /* 0x288 */ + /* Enable BAM on KR */ +#define PORT_HW_CFG_ENABLE_BAM_ON_KR_MASK 0x00100000 +#define PORT_HW_CFG_ENABLE_BAM_ON_KR_SHIFT 20 +#define PORT_HW_CFG_ENABLE_BAM_ON_KR_DISABLED 0x00000000 +#define PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED 0x00100000 + u32 speed_capability_mask2; /* 0x28C */ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_MASK 0x0000FFFF #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_SHIFT 0 diff --git a/trunk/drivers/net/bnx2x/bnx2x_link.c b/trunk/drivers/net/bnx2x/bnx2x_link.c index 2326774df843..580919619252 100644 --- a/trunk/drivers/net/bnx2x/bnx2x_link.c +++ b/trunk/drivers/net/bnx2x/bnx2x_link.c @@ -610,7 +610,7 @@ static u8 bnx2x_bmac_enable(struct link_params *params, /* reset and unreset the BigMac */ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); - udelay(10); + msleep(1); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); @@ -3525,13 +3525,19 @@ static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy, DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1): 0x%x\n", tmp1); /* Enable CL37 BAM */ - bnx2x_cl45_read(bp, phy, - MDIO_AN_DEVAD, - MDIO_AN_REG_8073_BAM, &val); - bnx2x_cl45_write(bp, phy, - MDIO_AN_DEVAD, - MDIO_AN_REG_8073_BAM, val | 1); + if (REG_RD(bp, params->shmem_base + + offsetof(struct shmem_region, dev_info. + port_hw_config[params->port].default_cfg)) & + PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED) { + bnx2x_cl45_read(bp, phy, + MDIO_AN_DEVAD, + MDIO_AN_REG_8073_BAM, &val); + bnx2x_cl45_write(bp, phy, + MDIO_AN_DEVAD, + MDIO_AN_REG_8073_BAM, val | 1); + DP(NETIF_MSG_LINK, "Enable CL37 BAM on KR\n"); + } if (params->loopback_mode == LOOPBACK_EXT) { bnx2x_807x_force_10G(bp, phy); DP(NETIF_MSG_LINK, "Forced speed 10G on 807X\n"); @@ -5302,7 +5308,7 @@ static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy, { struct bnx2x *bp = params->bp; u16 autoneg_val, an_1000_val, an_10_100_val; - bnx2x_wait_reset_complete(bp, phy); + bnx2x_bits_en(bp, NIG_REG_LATCH_BC_0 + params->port*4, 1 << NIG_LATCH_BC_ENABLE_MI_INT); @@ -5431,6 +5437,7 @@ static u8 bnx2x_8481_config_init(struct bnx2x_phy *phy, /* HW reset */ bnx2x_ext_phy_hw_reset(bp, params->port); + bnx2x_wait_reset_complete(bp, phy); bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15); return bnx2x_848xx_cmn_config_init(phy, params, vars); @@ -5441,7 +5448,7 @@ static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy, struct link_vars *vars) { struct bnx2x *bp = params->bp; - u8 port = params->port, initialize = 1; + u8 port, initialize = 1; u16 val; u16 temp; u32 actual_phy_selection; @@ -5450,11 +5457,16 @@ static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy, /* This is just for MDIO_CTL_REG_84823_MEDIA register. */ msleep(1); + if (CHIP_IS_E2(bp)) + port = BP_PATH(bp); + else + port = params->port; bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3, MISC_REGISTERS_GPIO_OUTPUT_HIGH, port); - msleep(200); /* 100 is not enough */ - + bnx2x_wait_reset_complete(bp, phy); + /* Wait for GPHY to come out of reset */ + msleep(50); /* BCM84823 requires that XGXS links up first @ 10G for normal behavior */ temp = vars->line_speed; @@ -5625,7 +5637,11 @@ static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy, struct link_params *params) { struct bnx2x *bp = params->bp; - u8 port = params->port; + u8 port; + if (CHIP_IS_E2(bp)) + port = BP_PATH(bp); + else + port = params->port; bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3, MISC_REGISTERS_GPIO_OUTPUT_LOW, port); @@ -6928,7 +6944,7 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars, u8 reset_ext_phy) { struct bnx2x *bp = params->bp; - u8 phy_index, port = params->port; + u8 phy_index, port = params->port, clear_latch_ind = 0; DP(NETIF_MSG_LINK, "Resetting the link of port %d\n", port); /* disable attentions */ vars->link_status = 0; @@ -6966,9 +6982,18 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars, params->phy[phy_index].link_reset( ¶ms->phy[phy_index], params); + if (params->phy[phy_index].flags & + FLAGS_REARM_LATCH_SIGNAL) + clear_latch_ind = 1; } } + if (clear_latch_ind) { + /* Clear latching indication */ + bnx2x_rearm_latch_signal(bp, port, 0); + bnx2x_bits_dis(bp, NIG_REG_LATCH_BC_0 + port*4, + 1 << NIG_LATCH_BC_ENABLE_MI_INT); + } if (params->phy[INT_PHY].link_reset) params->phy[INT_PHY].link_reset( ¶ms->phy[INT_PHY], params); @@ -6999,6 +7024,7 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, s8 port; s8 port_of_path = 0; + bnx2x_ext_phy_hw_reset(bp, 0); /* PART1 - Reset both phys */ for (port = PORT_MAX - 1; port >= PORT_0; port--) { u32 shmem_base, shmem2_base; @@ -7021,7 +7047,8 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, return -EINVAL; } /* disable attentions */ - bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, + bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + + port_of_path*4, (NIG_MASK_XGXS0_LINK_STATUS | NIG_MASK_XGXS0_LINK10G | NIG_MASK_SERDES0_LINK_STATUS | @@ -7132,7 +7159,7 @@ static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, (1<<(MISC_REGISTERS_GPIO_3 + MISC_REGISTERS_GPIO_PORT_SHIFT))); REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val); - bnx2x_ext_phy_hw_reset(bp, 1); + bnx2x_ext_phy_hw_reset(bp, 0); msleep(5); for (port = 0; port < PORT_MAX; port++) { u32 shmem_base, shmem2_base; diff --git a/trunk/drivers/net/caif/caif_spi.c b/trunk/drivers/net/caif/caif_spi.c index 8427533fe313..8b4cea57a6c5 100644 --- a/trunk/drivers/net/caif/caif_spi.c +++ b/trunk/drivers/net/caif/caif_spi.c @@ -33,6 +33,9 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Daniel Martensson"); MODULE_DESCRIPTION("CAIF SPI driver"); +/* Returns the number of padding bytes for alignment. */ +#define PAD_POW2(x, pow) ((((x)&((pow)-1))==0) ? 0 : (((pow)-((x)&((pow)-1))))) + static int spi_loop; module_param(spi_loop, bool, S_IRUGO); MODULE_PARM_DESC(spi_loop, "SPI running in loopback mode."); @@ -41,7 +44,10 @@ MODULE_PARM_DESC(spi_loop, "SPI running in loopback mode."); module_param(spi_frm_align, int, S_IRUGO); MODULE_PARM_DESC(spi_frm_align, "SPI frame alignment."); -/* SPI padding options. */ +/* + * SPI padding options. + * Warning: must be a base of 2 (& operation used) and can not be zero ! + */ module_param(spi_up_head_align, int, S_IRUGO); MODULE_PARM_DESC(spi_up_head_align, "SPI uplink head alignment."); @@ -240,15 +246,13 @@ static ssize_t dbgfs_frame(struct file *file, char __user *user_buf, static const struct file_operations dbgfs_state_fops = { .open = dbgfs_open, .read = dbgfs_state, - .owner = THIS_MODULE, - .llseek = default_llseek, + .owner = THIS_MODULE }; static const struct file_operations dbgfs_frame_fops = { .open = dbgfs_open, .read = dbgfs_frame, - .owner = THIS_MODULE, - .llseek = default_llseek, + .owner = THIS_MODULE }; static inline void dev_debugfs_add(struct cfspi *cfspi) @@ -337,6 +341,9 @@ int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len) u8 *dst = buf; caif_assert(buf); + if (cfspi->slave && !cfspi->slave_talked) + cfspi->slave_talked = true; + do { struct sk_buff *skb; struct caif_payload_info *info; @@ -357,8 +364,8 @@ int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len) * Compute head offset i.e. number of bytes to add to * get the start of the payload aligned. */ - if (spi_up_head_align) { - spad = 1 + ((info->hdr_len + 1) & spi_up_head_align); + if (spi_up_head_align > 1) { + spad = 1 + PAD_POW2((info->hdr_len + 1), spi_up_head_align); *dst = (u8)(spad - 1); dst += spad; } @@ -373,7 +380,7 @@ int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len) * Compute tail offset i.e. number of bytes to add to * get the complete CAIF frame aligned. */ - epad = (skb->len + spad) & spi_up_tail_align; + epad = PAD_POW2((skb->len + spad), spi_up_tail_align); dst += epad; dev_kfree_skb(skb); @@ -417,14 +424,14 @@ int cfspi_xmitlen(struct cfspi *cfspi) * Compute head offset i.e. number of bytes to add to * get the start of the payload aligned. */ - if (spi_up_head_align) - spad = 1 + ((info->hdr_len + 1) & spi_up_head_align); + if (spi_up_head_align > 1) + spad = 1 + PAD_POW2((info->hdr_len + 1), spi_up_head_align); /* * Compute tail offset i.e. number of bytes to add to * get the complete CAIF frame aligned. */ - epad = (skb->len + spad) & spi_up_tail_align; + epad = PAD_POW2((skb->len + spad), spi_up_tail_align); if ((skb->len + spad + epad + frm_len) <= CAIF_MAX_SPI_FRAME) { skb_queue_tail(&cfspi->chead, skb); @@ -433,6 +440,7 @@ int cfspi_xmitlen(struct cfspi *cfspi) } else { /* Put back packet. */ skb_queue_head(&cfspi->qhead, skb); + break; } } while (pkts <= CAIF_MAX_SPI_PKTS); @@ -453,6 +461,15 @@ static void cfspi_ss_cb(bool assert, struct cfspi_ifc *ifc) { struct cfspi *cfspi = (struct cfspi *)ifc->priv; + /* + * The slave device is the master on the link. Interrupts before the + * slave has transmitted are considered spurious. + */ + if (cfspi->slave && !cfspi->slave_talked) { + printk(KERN_WARNING "CFSPI: Spurious SS interrupt.\n"); + return; + } + if (!in_interrupt()) spin_lock(&cfspi->lock); if (assert) { @@ -465,7 +482,8 @@ static void cfspi_ss_cb(bool assert, struct cfspi_ifc *ifc) spin_unlock(&cfspi->lock); /* Wake up the xfer thread. */ - wake_up_interruptible(&cfspi->wait); + if (assert) + wake_up_interruptible(&cfspi->wait); } static void cfspi_xfer_done_cb(struct cfspi_ifc *ifc) @@ -523,7 +541,7 @@ int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len) * Compute head offset i.e. number of bytes added to * get the start of the payload aligned. */ - if (spi_down_head_align) { + if (spi_down_head_align > 1) { spad = 1 + *src; src += spad; } @@ -564,7 +582,7 @@ int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len) * Compute tail offset i.e. number of bytes added to * get the complete CAIF frame aligned. */ - epad = (pkt_len + spad) & spi_down_tail_align; + epad = PAD_POW2((pkt_len + spad), spi_down_tail_align); src += epad; } while ((src - buf) < len); @@ -625,11 +643,20 @@ int cfspi_spi_probe(struct platform_device *pdev) cfspi->ndev = ndev; cfspi->pdev = pdev; - /* Set flow info */ + /* Set flow info. */ cfspi->flow_off_sent = 0; cfspi->qd_low_mark = LOW_WATER_MARK; cfspi->qd_high_mark = HIGH_WATER_MARK; + /* Set slave info. */ + if (!strncmp(cfspi_spi_driver.driver.name, "cfspi_sspi", 10)) { + cfspi->slave = true; + cfspi->slave_talked = false; + } else { + cfspi->slave = false; + cfspi->slave_talked = false; + } + /* Assign the SPI device. */ cfspi->dev = dev; /* Assign the device ifc to this SPI interface. */ diff --git a/trunk/drivers/net/caif/caif_spi_slave.c b/trunk/drivers/net/caif/caif_spi_slave.c index 2111dbfea6fe..1b9943a4edab 100644 --- a/trunk/drivers/net/caif/caif_spi_slave.c +++ b/trunk/drivers/net/caif/caif_spi_slave.c @@ -36,10 +36,15 @@ static inline int forward_to_spi_cmd(struct cfspi *cfspi) #endif int spi_frm_align = 2; -int spi_up_head_align = 1; -int spi_up_tail_align; -int spi_down_head_align = 3; -int spi_down_tail_align = 1; + +/* + * SPI padding options. + * Warning: must be a base of 2 (& operation used) and can not be zero ! + */ +int spi_up_head_align = 1 << 1; +int spi_up_tail_align = 1 << 0; +int spi_down_head_align = 1 << 2; +int spi_down_tail_align = 1 << 1; #ifdef CONFIG_DEBUG_FS static inline void debugfs_store_prev(struct cfspi *cfspi) diff --git a/trunk/drivers/net/cxgb3/cxgb3_main.c b/trunk/drivers/net/cxgb3/cxgb3_main.c index 407d4e272075..046d846c652d 100644 --- a/trunk/drivers/net/cxgb3/cxgb3_main.c +++ b/trunk/drivers/net/cxgb3/cxgb3_main.c @@ -3341,7 +3341,6 @@ static int __devinit init_one(struct pci_dev *pdev, adapter->name = adapter->port[i]->name; __set_bit(i, &adapter->registered_device_map); - netif_tx_stop_all_queues(adapter->port[i]); } } if (!adapter->registered_device_map) { diff --git a/trunk/drivers/net/cxgb4/cxgb4_main.c b/trunk/drivers/net/cxgb4/cxgb4_main.c index f17703f410b3..f50bc98310f8 100644 --- a/trunk/drivers/net/cxgb4/cxgb4_main.c +++ b/trunk/drivers/net/cxgb4/cxgb4_main.c @@ -3736,7 +3736,6 @@ static int __devinit init_one(struct pci_dev *pdev, __set_bit(i, &adapter->registered_device_map); adapter->chan_map[adap2pinfo(adapter, i)->tx_chan] = i; - netif_tx_stop_all_queues(adapter->port[i]); } } if (!adapter->registered_device_map) { diff --git a/trunk/drivers/net/cxgb4vf/cxgb4vf_main.c b/trunk/drivers/net/cxgb4vf/cxgb4vf_main.c index 555ecc5a2e93..6de5e2e448a5 100644 --- a/trunk/drivers/net/cxgb4vf/cxgb4vf_main.c +++ b/trunk/drivers/net/cxgb4vf/cxgb4vf_main.c @@ -2600,7 +2600,6 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev, pi->xact_addr_filt = -1; pi->rx_offload = RX_CSO; netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); netdev->irq = pdev->irq; netdev->features = (NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | diff --git a/trunk/drivers/net/ibm_newemac/core.c b/trunk/drivers/net/ibm_newemac/core.c index 385dc3204cb7..06bb9b799458 100644 --- a/trunk/drivers/net/ibm_newemac/core.c +++ b/trunk/drivers/net/ibm_newemac/core.c @@ -2871,7 +2871,6 @@ static int __devinit emac_probe(struct platform_device *ofdev, SET_ETHTOOL_OPS(ndev, &emac_ethtool_ops); netif_carrier_off(ndev); - netif_stop_queue(ndev); err = register_netdev(ndev); if (err) { diff --git a/trunk/drivers/net/jme.c b/trunk/drivers/net/jme.c index d85edf3119c2..c57d9a43ceca 100644 --- a/trunk/drivers/net/jme.c +++ b/trunk/drivers/net/jme.c @@ -2955,11 +2955,7 @@ jme_init_one(struct pci_dev *pdev, * Tell stack that we are not ready to work until open() */ netif_carrier_off(netdev); - netif_stop_queue(netdev); - /* - * Register netdev - */ rc = register_netdev(netdev); if (rc) { pr_err("Cannot register net device\n"); diff --git a/trunk/drivers/net/netxen/netxen_nic_main.c b/trunk/drivers/net/netxen/netxen_nic_main.c index a75ba9517404..e1d30d7f2071 100644 --- a/trunk/drivers/net/netxen/netxen_nic_main.c +++ b/trunk/drivers/net/netxen/netxen_nic_main.c @@ -41,9 +41,6 @@ MODULE_DESCRIPTION("QLogic/NetXen (1/10) GbE Converged Ethernet Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID); -MODULE_FIRMWARE(NX_P2_MN_ROMIMAGE_NAME); -MODULE_FIRMWARE(NX_P3_CT_ROMIMAGE_NAME); -MODULE_FIRMWARE(NX_P3_MN_ROMIMAGE_NAME); MODULE_FIRMWARE(NX_UNIFIED_ROMIMAGE_NAME); char netxen_nic_driver_name[] = "netxen_nic"; diff --git a/trunk/drivers/net/qlcnic/qlcnic_main.c b/trunk/drivers/net/qlcnic/qlcnic_main.c index 7a298cdf9ab3..a3dcd04be22f 100644 --- a/trunk/drivers/net/qlcnic/qlcnic_main.c +++ b/trunk/drivers/net/qlcnic/qlcnic_main.c @@ -1450,7 +1450,6 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, netdev->irq = adapter->msix_entries[0].vector; netif_carrier_off(netdev); - netif_stop_queue(netdev); err = register_netdev(netdev); if (err) { diff --git a/trunk/drivers/net/smsc911x.h b/trunk/drivers/net/smsc911x.h index 52f38e12a879..50f712e99e96 100644 --- a/trunk/drivers/net/smsc911x.h +++ b/trunk/drivers/net/smsc911x.h @@ -22,7 +22,7 @@ #define __SMSC911X_H__ #define TX_FIFO_LOW_THRESHOLD ((u32)1600) -#define SMSC911X_EEPROM_SIZE ((u32)7) +#define SMSC911X_EEPROM_SIZE ((u32)128) #define USE_DEBUG 0 /* This is the maximum number of packets to be received every diff --git a/trunk/drivers/net/tulip/de2104x.c b/trunk/drivers/net/tulip/de2104x.c index 28e1ffb13db9..c78a50586c1d 100644 --- a/trunk/drivers/net/tulip/de2104x.c +++ b/trunk/drivers/net/tulip/de2104x.c @@ -2021,7 +2021,6 @@ static int __devinit de_init_one (struct pci_dev *pdev, de->media_timer.data = (unsigned long) de; netif_carrier_off(dev); - netif_stop_queue(dev); /* wake up device, assign resources */ rc = pci_enable_device(pdev); diff --git a/trunk/drivers/net/usb/usbnet.c b/trunk/drivers/net/usb/usbnet.c index ca7fc9df1ccf..c04d49e31f81 100644 --- a/trunk/drivers/net/usb/usbnet.c +++ b/trunk/drivers/net/usb/usbnet.c @@ -45,6 +45,7 @@ #include #include #include +#include #define DRIVER_VERSION "22-Aug-2005" @@ -1273,6 +1274,16 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) struct usb_device *xdev; int status; const char *name; + struct usb_driver *driver = to_usb_driver(udev->dev.driver); + + /* usbnet already took usb runtime pm, so have to enable the feature + * for usb interface, otherwise usb_autopm_get_interface may return + * failure if USB_SUSPEND(RUNTIME_PM) is enabled. + */ + if (!driver->supports_autosuspend) { + driver->supports_autosuspend = 1; + pm_runtime_enable(&udev->dev); + } name = udev->dev.driver->name; info = (struct driver_info *) prod->driver_info; diff --git a/trunk/drivers/net/wireless/ipw2x00/libipw_module.c b/trunk/drivers/net/wireless/ipw2x00/libipw_module.c index 32dee2ce5d31..d5ef696298ee 100644 --- a/trunk/drivers/net/wireless/ipw2x00/libipw_module.c +++ b/trunk/drivers/net/wireless/ipw2x00/libipw_module.c @@ -54,6 +54,7 @@ #define DRV_DESCRIPTION "802.11 data/management/control stack" #define DRV_NAME "libipw" +#define DRV_PROCNAME "ieee80211" #define DRV_VERSION LIBIPW_VERSION #define DRV_COPYRIGHT "Copyright (C) 2004-2005 Intel Corporation " @@ -293,16 +294,16 @@ static int __init libipw_init(void) struct proc_dir_entry *e; libipw_debug_level = debug; - libipw_proc = proc_mkdir("ieee80211", init_net.proc_net); + libipw_proc = proc_mkdir(DRV_PROCNAME, init_net.proc_net); if (libipw_proc == NULL) { - LIBIPW_ERROR("Unable to create " DRV_NAME + LIBIPW_ERROR("Unable to create " DRV_PROCNAME " proc directory\n"); return -EIO; } e = proc_create("debug_level", S_IRUGO | S_IWUSR, libipw_proc, &debug_level_proc_fops); if (!e) { - remove_proc_entry(DRV_NAME, init_net.proc_net); + remove_proc_entry(DRV_PROCNAME, init_net.proc_net); libipw_proc = NULL; return -EIO; } @@ -319,7 +320,7 @@ static void __exit libipw_exit(void) #ifdef CONFIG_LIBIPW_DEBUG if (libipw_proc) { remove_proc_entry("debug_level", libipw_proc); - remove_proc_entry(DRV_NAME, init_net.proc_net); + remove_proc_entry(DRV_PROCNAME, init_net.proc_net); libipw_proc = NULL; } #endif /* CONFIG_LIBIPW_DEBUG */ diff --git a/trunk/drivers/rtc/rtc-ds1302.c b/trunk/drivers/rtc/rtc-ds1302.c index 359d1e04626c..f0d638922644 100644 --- a/trunk/drivers/rtc/rtc-ds1302.c +++ b/trunk/drivers/rtc/rtc-ds1302.c @@ -35,7 +35,7 @@ #ifdef CONFIG_SH_SECUREEDGE5410 #include -#include +#include #define RTC_RESET 0x1000 #define RTC_IODATA 0x0800 diff --git a/trunk/drivers/sh/clk/core.c b/trunk/drivers/sh/clk/core.c index fd0d1b98901c..09615b51d591 100644 --- a/trunk/drivers/sh/clk/core.c +++ b/trunk/drivers/sh/clk/core.c @@ -90,8 +90,8 @@ struct clk_rate_round_data { static long clk_rate_round_helper(struct clk_rate_round_data *rounder) { unsigned long rate_error, rate_error_prev = ~0UL; - unsigned long rate_best_fit = rounder->rate; unsigned long highest, lowest, freq; + long rate_best_fit = -ENOENT; int i; highest = 0; @@ -146,7 +146,7 @@ long clk_rate_table_round(struct clk *clk, }; if (clk->nr_freqs < 1) - return 0; + return -ENOSYS; return clk_rate_round_helper(&table_round); } @@ -541,6 +541,98 @@ long clk_round_rate(struct clk *clk, unsigned long rate) } EXPORT_SYMBOL_GPL(clk_round_rate); +long clk_round_parent(struct clk *clk, unsigned long target, + unsigned long *best_freq, unsigned long *parent_freq, + unsigned int div_min, unsigned int div_max) +{ + struct cpufreq_frequency_table *freq, *best = NULL; + unsigned long error = ULONG_MAX, freq_high, freq_low, div; + struct clk *parent = clk_get_parent(clk); + + if (!parent) { + *parent_freq = 0; + *best_freq = clk_round_rate(clk, target); + return abs(target - *best_freq); + } + + for (freq = parent->freq_table; freq->frequency != CPUFREQ_TABLE_END; + freq++) { + if (freq->frequency == CPUFREQ_ENTRY_INVALID) + continue; + + if (unlikely(freq->frequency / target <= div_min - 1)) { + unsigned long freq_max; + + freq_max = (freq->frequency + div_min / 2) / div_min; + if (error > target - freq_max) { + error = target - freq_max; + best = freq; + if (best_freq) + *best_freq = freq_max; + } + + pr_debug("too low freq %lu, error %lu\n", freq->frequency, + target - freq_max); + + if (!error) + break; + + continue; + } + + if (unlikely(freq->frequency / target >= div_max)) { + unsigned long freq_min; + + freq_min = (freq->frequency + div_max / 2) / div_max; + if (error > freq_min - target) { + error = freq_min - target; + best = freq; + if (best_freq) + *best_freq = freq_min; + } + + pr_debug("too high freq %lu, error %lu\n", freq->frequency, + freq_min - target); + + if (!error) + break; + + continue; + } + + div = freq->frequency / target; + freq_high = freq->frequency / div; + freq_low = freq->frequency / (div + 1); + + if (freq_high - target < error) { + error = freq_high - target; + best = freq; + if (best_freq) + *best_freq = freq_high; + } + + if (target - freq_low < error) { + error = target - freq_low; + best = freq; + if (best_freq) + *best_freq = freq_low; + } + + pr_debug("%u / %lu = %lu, / %lu = %lu, best %lu, parent %u\n", + freq->frequency, div, freq_high, div + 1, freq_low, + *best_freq, best->frequency); + + if (!error) + break; + } + + if (parent_freq) + *parent_freq = best->frequency; + + return error; +} +EXPORT_SYMBOL_GPL(clk_round_parent); + #ifdef CONFIG_PM static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state) { diff --git a/trunk/drivers/sh/intc/core.c b/trunk/drivers/sh/intc/core.c index 873a99ff8f64..e5e9e6735f7d 100644 --- a/trunk/drivers/sh/intc/core.c +++ b/trunk/drivers/sh/intc/core.c @@ -79,7 +79,7 @@ static void __init intc_register_irq(struct intc_desc *desc, * Register the IRQ position with the global IRQ map, then insert * it in to the radix tree. */ - irq_reserve_irqs(irq, 1); + irq_reserve_irq(irq); raw_spin_lock_irqsave(&intc_big_lock, flags); radix_tree_insert(&d->tree, enum_id, intc_irq_xlate_get(irq)); diff --git a/trunk/drivers/sh/intc/dynamic.c b/trunk/drivers/sh/intc/dynamic.c index 4187cce20ffd..a3677c9dfe36 100644 --- a/trunk/drivers/sh/intc/dynamic.c +++ b/trunk/drivers/sh/intc/dynamic.c @@ -60,5 +60,5 @@ void reserve_intc_vectors(struct intc_vect *vectors, unsigned int nr_vecs) int i; for (i = 0; i < nr_vecs; i++) - irq_reserve_irqs(evt2irq(vectors[i].vect), 1); + irq_reserve_irq(evt2irq(vectors[i].vect)); } diff --git a/trunk/drivers/staging/Kconfig b/trunk/drivers/staging/Kconfig index 5eafdf435550..49aee27b296d 100644 --- a/trunk/drivers/staging/Kconfig +++ b/trunk/drivers/staging/Kconfig @@ -175,5 +175,9 @@ source "drivers/staging/intel_sst/Kconfig" source "drivers/staging/speakup/Kconfig" +source "drivers/staging/cptm1217/Kconfig" + +source "drivers/staging/ste_rmi4/Kconfig" + endif # !STAGING_EXCLUDE_BUILD endif # STAGING diff --git a/trunk/drivers/staging/Makefile b/trunk/drivers/staging/Makefile index a97a955c094b..20c5641b6cd7 100644 --- a/trunk/drivers/staging/Makefile +++ b/trunk/drivers/staging/Makefile @@ -68,3 +68,5 @@ obj-$(CONFIG_BCM_WIMAX) += bcm/ obj-$(CONFIG_FT1000) += ft1000/ obj-$(CONFIG_SND_INTEL_SST) += intel_sst/ obj-$(CONFIG_SPEAKUP) += speakup/ +obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/ +obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/ diff --git a/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c b/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c index 22c6c6659f5b..ee8b47746a15 100644 --- a/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c +++ b/trunk/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c @@ -285,9 +285,9 @@ A_STATUS SetupHIFScatterSupport(HIF_DEVICE *device, HIF_DEVICE_SCATTER_SUPPORT_I do { /* check if host supports scatter requests and it meets our requirements */ - if (device->func->card->host->max_hw_segs < MAX_SCATTER_ENTRIES_PER_REQ) { + if (device->func->card->host->max_segs < MAX_SCATTER_ENTRIES_PER_REQ) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HIF-SCATTER : host only supports scatter of : %d entries, need: %d \n", - device->func->card->host->max_hw_segs, MAX_SCATTER_ENTRIES_PER_REQ)); + device->func->card->host->max_segs, MAX_SCATTER_ENTRIES_PER_REQ)); status = A_ENOTSUP; break; } diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/athendpack_linux.h b/trunk/drivers/staging/ath6kl/os/linux/include/athendpack_linux.h deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/trunk/drivers/staging/ath6kl/os/linux/include/athstartpack_linux.h b/trunk/drivers/staging/ath6kl/os/linux/include/athstartpack_linux.h deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/trunk/drivers/staging/batman-adv/main.c b/trunk/drivers/staging/batman-adv/main.c index 0587940d2723..6ea64200ad16 100644 --- a/trunk/drivers/staging/batman-adv/main.c +++ b/trunk/drivers/staging/batman-adv/main.c @@ -149,7 +149,7 @@ void dec_module_count(void) int compare_orig(void *data1, void *data2) { - return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); + return (compare_ether_addr(data1, data2) == 0 ? 1 : 0); } /* hashfunction to choose an entry in a hash table of given size */ @@ -192,16 +192,6 @@ int is_my_mac(uint8_t *addr) } -int is_bcast(uint8_t *addr) -{ - return (addr[0] == (uint8_t)0xff) && (addr[1] == (uint8_t)0xff); -} - -int is_mcast(uint8_t *addr) -{ - return *addr & 0x01; -} - module_init(batman_init); module_exit(batman_exit); diff --git a/trunk/drivers/staging/batman-adv/main.h b/trunk/drivers/staging/batman-adv/main.h index 5e3f51681f5e..14d567d4911a 100644 --- a/trunk/drivers/staging/batman-adv/main.h +++ b/trunk/drivers/staging/batman-adv/main.h @@ -109,6 +109,7 @@ #include /* mutex */ #include /* needed by all modules */ #include /* netdevice */ +#include #include /* ethernet header */ #include /* poll_table */ #include /* kernel threads */ @@ -138,8 +139,6 @@ void dec_module_count(void); int compare_orig(void *data1, void *data2); int choose_orig(void *data, int32_t size); int is_my_mac(uint8_t *addr); -int is_bcast(uint8_t *addr); -int is_mcast(uint8_t *addr); #ifdef CONFIG_BATMAN_ADV_DEBUG int debug_log(struct bat_priv *bat_priv, char *fmt, ...); diff --git a/trunk/drivers/staging/batman-adv/routing.c b/trunk/drivers/staging/batman-adv/routing.c index 90102631330b..d42c16559dff 100644 --- a/trunk/drivers/staging/batman-adv/routing.c +++ b/trunk/drivers/staging/batman-adv/routing.c @@ -756,11 +756,11 @@ int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if) ethhdr = (struct ethhdr *)skb_mac_header(skb); /* packet with broadcast indication but unicast recipient */ - if (!is_bcast(ethhdr->h_dest)) + if (!is_broadcast_ether_addr(ethhdr->h_dest)) return NET_RX_DROP; /* packet with broadcast sender address */ - if (is_bcast(ethhdr->h_source)) + if (is_broadcast_ether_addr(ethhdr->h_source)) return NET_RX_DROP; /* create a copy of the skb, if needed, to modify it. */ @@ -933,11 +933,11 @@ int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if) ethhdr = (struct ethhdr *)skb_mac_header(skb); /* packet with unicast indication but broadcast recipient */ - if (is_bcast(ethhdr->h_dest)) + if (is_broadcast_ether_addr(ethhdr->h_dest)) return NET_RX_DROP; /* packet with broadcast sender address */ - if (is_bcast(ethhdr->h_source)) + if (is_broadcast_ether_addr(ethhdr->h_source)) return NET_RX_DROP; /* not for me */ @@ -1107,11 +1107,11 @@ static int check_unicast_packet(struct sk_buff *skb, int hdr_size) ethhdr = (struct ethhdr *)skb_mac_header(skb); /* packet with unicast indication but broadcast recipient */ - if (is_bcast(ethhdr->h_dest)) + if (is_broadcast_ether_addr(ethhdr->h_dest)) return -1; /* packet with broadcast sender address */ - if (is_bcast(ethhdr->h_source)) + if (is_broadcast_ether_addr(ethhdr->h_source)) return -1; /* not for me */ @@ -1283,11 +1283,11 @@ int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if) ethhdr = (struct ethhdr *)skb_mac_header(skb); /* packet with broadcast indication but unicast recipient */ - if (!is_bcast(ethhdr->h_dest)) + if (!is_broadcast_ether_addr(ethhdr->h_dest)) return NET_RX_DROP; /* packet with broadcast sender address */ - if (is_bcast(ethhdr->h_source)) + if (is_broadcast_ether_addr(ethhdr->h_source)) return NET_RX_DROP; /* ignore broadcasts sent by myself */ diff --git a/trunk/drivers/staging/batman-adv/soft-interface.c b/trunk/drivers/staging/batman-adv/soft-interface.c index 3904db9ce7b1..820e14159dd3 100644 --- a/trunk/drivers/staging/batman-adv/soft-interface.c +++ b/trunk/drivers/staging/batman-adv/soft-interface.c @@ -140,7 +140,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) hna_local_add(soft_iface, ethhdr->h_source); /* ethernet packet should be broadcasted */ - if (is_bcast(ethhdr->h_dest) || is_mcast(ethhdr->h_dest)) { + if (is_multicast_ether_addr(ethhdr->h_dest)) { if (!bat_priv->primary_if) goto dropped; diff --git a/trunk/drivers/staging/batman-adv/vis.c b/trunk/drivers/staging/batman-adv/vis.c index 3d2c1bccf2e6..395f1109d606 100644 --- a/trunk/drivers/staging/batman-adv/vis.c +++ b/trunk/drivers/staging/batman-adv/vis.c @@ -135,9 +135,8 @@ static ssize_t vis_data_read_prim_sec(char *buff, struct hlist_head *if_list) hlist_for_each_entry(entry, pos, if_list, list) { if (entry->primary) len += sprintf(buff + len, "PRIMARY, "); - else { + else len += sprintf(buff + len, "SEC %pM, ", entry->addr); - } } return len; @@ -470,7 +469,7 @@ void receive_client_update_packet(struct bat_priv *bat_priv, int are_target = 0; /* clients shall not broadcast. */ - if (is_bcast(vis_packet->target_orig)) + if (is_broadcast_ether_addr(vis_packet->target_orig)) return; /* Are we the target for this VIS packet? */ @@ -747,7 +746,7 @@ static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) ETH_ALEN); packet->ttl--; - if (is_bcast(packet->target_orig)) + if (is_broadcast_ether_addr(packet->target_orig)) broadcast_vis_packet(bat_priv, info); else unicast_vis_packet(bat_priv, info); diff --git a/trunk/drivers/staging/bcm/Adapter.h b/trunk/drivers/staging/bcm/Adapter.h index 748460e898d8..62f9135d4d40 100644 --- a/trunk/drivers/staging/bcm/Adapter.h +++ b/trunk/drivers/staging/bcm/Adapter.h @@ -7,53 +7,6 @@ #define MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES 256 #include "Debug.h" -typedef struct _LIST_ENTRY{ - struct _LIST_ENTRY *next; - struct _LIST_ENTRY *prev; -} LIST_ENTRY, *PLIST_ENTRY; - -typedef struct _BCM_LIST_ENTRY { - - LIST_ENTRY Link; - -} BCM_LIST_ENTRY, *PBCM_LIST_ENTRY; - -typedef enum _RCB_STATUS -{ - DRIVER_PROCESSED=1, - APPLICATION_PROCESSED -} RCB_STATUS, *PRCB_STATUS; - -#define fFILLED 1 -#define fEMPTY 0 - -struct _BCM_CB -{ - // The network packet that this RCB is receiving - PVOID pv_packet; - // Describes the length of the packet . - UINT ui_packet_length; - // Pointer to the first buffer in the packet (only one buffer for Rx) - PUCHAR buffer; - atomic_t status; - UINT filled; -} __attribute__((packed)); -typedef struct _BCM_CB BCM_CB,*PBCM_CB; - -typedef BCM_CB BCM_RCB, *PBCM_RCB; -typedef BCM_CB BCM_TCB, *PBCM_TCB; - -/* This is to be stored in the "pvOsDepData" of ADAPTER */ -typedef struct LINUX_DEP_DATA -{ - struct net_device *virtualdev; /* Our Interface (veth0) */ - struct net_device *actualdev; /* True Interface (eth0) */ - struct net_device_stats netstats; /* Net statistics */ - struct fasync_struct *async_queue; /* For asynchronus notification */ - -} LINUX_DEP_DATA, *PLINUX_DEP_DATA; - - struct _LEADER { USHORT Vcid; @@ -429,26 +382,28 @@ Driver adapter data structure struct _MINI_ADAPTER { struct _MINI_ADAPTER *next; - PVOID pvOsDepData; + struct net_device *dev; + u32 msg_enable; + CHAR *caDsxReqResp; - atomic_t ApplicationRunning; + atomic_t ApplicationRunning; volatile INT CtrlQueueLen; - atomic_t AppCtrlQueueLen; - BOOLEAN AppCtrlQueueOverFlow; - atomic_t CurrentApplicationCount; - atomic_t RegisteredApplicationCount; - BOOLEAN TimerActive; - ULONG StatisticsPointer; + atomic_t AppCtrlQueueLen; + BOOLEAN AppCtrlQueueOverFlow; + atomic_t CurrentApplicationCount; + atomic_t RegisteredApplicationCount; + BOOLEAN LinkUpStatus; + BOOLEAN TimerActive; + u32 StatisticsPointer; struct sk_buff *RxControlHead; struct sk_buff *RxControlTail; -// spinlock_t RxControlQueuelock; + struct semaphore RxAppControlQueuelock; struct semaphore fw_download_sema; PPER_TARANG_DATA pTarangs; spinlock_t control_queue_lock; wait_queue_head_t process_read_wait_queue; - ULONG bcm_jiffies; /* Store Jiffies value */ // the pointer to the first packet we have queued in send // deserialized miniport support variables @@ -458,24 +413,15 @@ struct _MINI_ADAPTER // this to keep track of the Tx and Rx MailBox Registers. atomic_t CurrNumFreeTxDesc; // to keep track the no of byte recieved - atomic_t RxRollOverCount; USHORT PrevNumRecvDescs; USHORT CurrNumRecvDescs; - atomic_t GoodRxByteCount; - atomic_t GoodRxPktCount; - atomic_t BadRxByteCount; - atomic_t RxPacketDroppedCount; - atomic_t GoodTxByteCount; - atomic_t TxTotalPacketCount; - atomic_t TxDroppedPacketCount; - ULONG LinkUpStatus; - BOOLEAN TransferMode; UINT u32TotalDSD; PacketInfo PackInfo[NO_OF_QUEUES]; S_CLASSIFIER_RULE astClassifierTable[MAX_CLASSIFIERS]; + BOOLEAN TransferMode; /*************** qos ******************/ - UINT bETHCSEnabled; + BOOLEAN bETHCSEnabled; ULONG BEBucketSize; ULONG rtPSBucketSize; @@ -483,7 +429,6 @@ struct _MINI_ADAPTER BOOLEAN AutoLinkUp; BOOLEAN AutoSyncup; - struct net_device *dev; int major; int minor; wait_queue_head_t tx_packet_wait_queue; @@ -491,8 +436,6 @@ struct _MINI_ADAPTER atomic_t process_waiting; BOOLEAN fw_download_done; - unsigned int ctrlpkt_present; - BOOLEAN packets_given_to_all; char *txctlpacket[MAX_CNTRL_PKTS]; atomic_t cntrlpktCnt ; atomic_t index_app_read_cntrlpkt; @@ -502,34 +445,30 @@ struct _MINI_ADAPTER struct semaphore rdmwrmsync; STTARGETDSXBUFFER astTargetDsxBuffer[MAX_TARGET_DSX_BUFFERS]; - ULONG ulFreeTargetBufferCnt; + ULONG ulFreeTargetBufferCnt; ULONG ulCurrentTargetBuffer; ULONG ulTotalTargetBuffersAvailable; - unsigned int timeout; - int irq; + unsigned long chip_id; - unsigned int bFlashBoot; - unsigned int if_up; -// spinlock_t sleeper_lock; - atomic_t rdm_wrm_access; - atomic_t tx_rx_access; + wait_queue_head_t lowpower_mode_wait_queue; - atomic_t bAbortedByHost; - BOOLEAN bBinDownloaded; - BOOLEAN bCfgDownloaded; - USHORT usBestEffortQueueIndex; - BOOLEAN bSyncUpRequestSent; -// struct semaphore data_packet_queue_lock; + + BOOLEAN bFlashBoot; + BOOLEAN bBinDownloaded; + BOOLEAN bCfgDownloaded; + BOOLEAN bSyncUpRequestSent; + USHORT usBestEffortQueueIndex; + wait_queue_head_t ioctl_fw_dnld_wait_queue; BOOLEAN waiting_to_fw_download_done; pid_t fw_download_process_pid; PSTARGETPARAMS pstargetparams; BOOLEAN device_removed; BOOLEAN DeviceAccess; - INT DDRSetting; + BOOLEAN bIsAutoCorrectEnabled; BOOLEAN bDDRInitDone; + INT DDRSetting; ULONG ulPowerSaveMode; - BOOLEAN bIsAutoCorrectEnabled; spinlock_t txtransmitlock; B_UINT8 txtransmit_running; /* Thread for control packet handling */ @@ -567,13 +506,13 @@ struct _MINI_ADAPTER unsigned int usIdleModePattern; //BOOLEAN bTriedToWakeUpFromShutdown; BOOLEAN bLinkDownRequested; - unsigned int check_for_hang; + int downloadDDR; PHS_DEVICE_EXTENSION stBCMPhsContext; S_HDR_SUPRESSION_CONTEXTINFO stPhsTxContextInfo; uint8_t ucaPHSPktRestoreBuf[2048]; uint8_t bPHSEnabled; - int AutoFirmDld; + BOOLEAN AutoFirmDld; BOOLEAN bMipsConfig; BOOLEAN bDPLLConfig; UINT32 aTxPktSizeHist[MIBS_MAX_HIST_ENTRIES]; @@ -599,10 +538,9 @@ struct _MINI_ADAPTER struct semaphore NVMRdmWrmLock; - BOOLEAN bNetworkInterfaceRegistered; - BOOLEAN bNetdeviceNotifierRegistered; + struct device *pstCreatedClassDevice; - BOOLEAN bUsbClassDriverRegistered; + // BOOLEAN InterfaceUpStatus; PFLASH2X_CS_INFO psFlash2xCSInfo; PFLASH_CS_INFO psFlashCSInfo ; @@ -630,17 +568,13 @@ struct _MINI_ADAPTER struct semaphore LowPowerModeSync; ULONG liDrainCalculated; UINT gpioBitMap; + S_BCM_DEBUG_STATE stDebugState; }; typedef struct _MINI_ADAPTER MINI_ADAPTER, *PMINI_ADAPTER; - -typedef struct _DEVICE_EXTENSION -{ - PMINI_ADAPTER pAdapt; -}DEVICE_EXTENSION,*PDEVICE_EXTENSION; - +#define GET_BCM_ADAPTER(net_dev) netdev_priv(net_dev) struct _ETH_HEADER_STRUC { UCHAR au8DestinationAddress[6]; diff --git a/trunk/drivers/staging/bcm/Arp.c b/trunk/drivers/staging/bcm/Arp.c deleted file mode 100644 index d60d8593d2ef..000000000000 --- a/trunk/drivers/staging/bcm/Arp.c +++ /dev/null @@ -1,94 +0,0 @@ - -/* - * File Name: Arp.c - * Abstract: This file contains the routines for handling ARP PACKETS - */ -#include "headers.h" -#define ARP_PKT_SIZE 60 - -/* ========================================================================= - * Function - reply_to_arp_request() - * - * Description - When this host tries to broadcast ARP request packet through - * the virtual interface (veth0), reply directly to upper layer. - * This function allocates a new skb for ARP reply packet, - * fills in the fields of the packet and then sends it to - * upper layer. - * - * Parameters - skb: Pointer to sk_buff structure of the ARP request pkt. - * - * Returns - None - * =========================================================================*/ - -VOID -reply_to_arp_request(struct sk_buff *skb) -{ - PMINI_ADAPTER Adapter; - struct ArpHeader *pArpHdr = NULL; - struct ethhdr *pethhdr = NULL; - UCHAR uiIPHdr[4]; - /* Check for valid skb */ - if(skb == NULL) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Invalid skb: Cannot reply to ARP request\n"); - return; - } - - - Adapter = GET_BCM_ADAPTER(skb->dev); - /* Print the ARP Request Packet */ - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, "ARP Packet Dump :"); - BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, (PUCHAR)(skb->data), skb->len); - - /* - * Extract the Ethernet Header and Arp Payload including Header - */ - pethhdr = (struct ethhdr *)skb->data; - pArpHdr = (struct ArpHeader *)(skb->data+ETH_HLEN); - - if(Adapter->bETHCSEnabled) - { - if(memcmp(pethhdr->h_source, Adapter->dev->dev_addr, ETH_ALEN)) - { - bcm_kfree_skb(skb); - return; - } - } - - // Set the Ethernet Header First. - memcpy(pethhdr->h_dest, pethhdr->h_source, ETH_ALEN); - if(!memcmp(pethhdr->h_source, Adapter->dev->dev_addr, ETH_ALEN)) - { - pethhdr->h_source[5]++; - } - - /* Set the reply to ARP Reply */ - pArpHdr->arp.ar_op = ntohs(ARPOP_REPLY); - - /* Set the HW Address properly */ - memcpy(pArpHdr->ar_sha, pethhdr->h_source, ETH_ALEN); - memcpy(pArpHdr->ar_tha, pethhdr->h_dest, ETH_ALEN); - - // Swapping the IP Adddress - memcpy(uiIPHdr,pArpHdr->ar_sip,4); - memcpy(pArpHdr->ar_sip,pArpHdr->ar_tip,4); - memcpy(pArpHdr->ar_tip,uiIPHdr,4); - - /* Print the ARP Reply Packet */ - - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, "ARP REPLY PACKET: "); - - /* Send the Packet to upper layer */ - BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, (PUCHAR)(skb->data), skb->len); - - skb->protocol = eth_type_trans(skb,skb->dev); - skb->pkt_type = PACKET_HOST; - -// skb->mac.raw=skb->data+LEADER_SIZE; - skb_set_mac_header (skb, LEADER_SIZE); - netif_rx(skb); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, "<=============\n"); - return; -} - - diff --git a/trunk/drivers/staging/bcm/Bcmchar.c b/trunk/drivers/staging/bcm/Bcmchar.c index 77fdfe24d999..8089d19e6c1b 100644 --- a/trunk/drivers/staging/bcm/Bcmchar.c +++ b/trunk/drivers/staging/bcm/Bcmchar.c @@ -12,7 +12,7 @@ * * Returns - Zero(Success) ****************************************************************/ -static struct class *bcm_class = NULL; + static int bcm_char_open(struct inode *inode, struct file * filp) { PMINI_ADAPTER Adapter = NULL; @@ -93,7 +93,7 @@ static int bcm_char_release(struct inode *inode, struct file *filp) /*Stop Queuing the control response Packets*/ atomic_dec(&Adapter->ApplicationRunning); - bcm_kfree(pTarang); + kfree(pTarang); /* remove this filp from the asynchronously notified filp's */ filp->private_data = NULL; @@ -102,11 +102,11 @@ static int bcm_char_release(struct inode *inode, struct file *filp) static ssize_t bcm_char_read(struct file *filp, char __user *buf, size_t size, loff_t *f_pos) { - PPER_TARANG_DATA pTarang = (PPER_TARANG_DATA)filp->private_data; + PPER_TARANG_DATA pTarang = filp->private_data; PMINI_ADAPTER Adapter = pTarang->Adapter; - struct sk_buff* Packet = NULL; - UINT PktLen = 0; - int wait_ret_val=0; + struct sk_buff* Packet = NULL; + ssize_t PktLen = 0; + int wait_ret_val=0; wait_ret_val = wait_event_interruptible(Adapter->process_read_wait_queue, (pTarang->RxAppControlHead || Adapter->device_removed)); @@ -139,14 +139,16 @@ static ssize_t bcm_char_read(struct file *filp, char __user *buf, size_t size, l if(Packet) { PktLen = Packet->len; - if(copy_to_user(buf, Packet->data, PktLen)) + if(copy_to_user(buf, Packet->data, min_t(size_t, PktLen, size))) { - bcm_kfree_skb(Packet); + dev_kfree_skb(Packet); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "\nReturning from copy to user failure \n"); return -EFAULT; } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Read %d Bytes From Adapter packet = 0x%p by process %d!\n", PktLen, Packet, current->pid); - bcm_kfree_skb(Packet); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, + "Read %zd Bytes From Adapter packet = %p by process %d!\n", + PktLen, Packet, current->pid); + dev_kfree_skb(Packet); } BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "<====\n"); @@ -155,15 +157,12 @@ static ssize_t bcm_char_read(struct file *filp, char __user *buf, size_t size, l static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) { - PPER_TARANG_DATA pTarang = (PPER_TARANG_DATA)filp->private_data; - void __user *argp = (void __user *)argp; + PPER_TARANG_DATA pTarang = filp->private_data; + void __user *argp = (void __user *)arg; PMINI_ADAPTER Adapter = pTarang->Adapter; INT Status = STATUS_FAILURE; - IOCTL_BUFFER IoBuffer={}; -#ifndef BCM_SHM_INTERFACE - int timeout = 0; -#endif - + int timeout = 0; + IOCTL_BUFFER IoBuffer; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", cmd, arg); @@ -204,50 +203,41 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) Status = vendorextnIoctl(Adapter, cmd, arg); if(Status != CONTINUE_COMMON_PATH ) - { return Status; - } switch(cmd){ // Rdms for Swin Idle... case IOCTL_BCM_REGISTER_READ_PRIVATE: { RDM_BUFFER sRdmBuffer = {0}; - PCHAR temp_buff = NULL; - UINT Bufflen = 0; + PCHAR temp_buff; + UINT Bufflen; + /* Copy Ioctl Buffer structure */ - if(copy_from_user((PCHAR)&IoBuffer, argp, - sizeof(IOCTL_BUFFER))) - { - Status = -EFAULT; - break; - } + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + + if (IoBuffer.InputLength > sizeof(sRdmBuffer)) + return -EINVAL; + if(copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; + + /* FIXME: need to restrict BuffLen */ Bufflen = IoBuffer.OutputLength + (4 - IoBuffer.OutputLength%4)%4; - temp_buff = (PCHAR)kmalloc(Bufflen, GFP_KERNEL); + temp_buff = kmalloc(Bufflen, GFP_KERNEL); if(!temp_buff) - { - return STATUS_FAILURE; - } - if(copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, - IoBuffer.InputLength)) - { - Status = -EFAULT; - break; - } + return -ENOMEM; + Status = rdmalt(Adapter, (UINT)sRdmBuffer.Register, (PUINT)temp_buff, Bufflen); - if(Status != STATUS_SUCCESS) - { - bcm_kfree(temp_buff); - return Status; - } - if(copy_to_user(IoBuffer.OutputBuffer, - (PCHAR)temp_buff, (UINT)IoBuffer.OutputLength)) + if(Status == STATUS_SUCCESS) { - Status = -EFAULT; + if(copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength)) + Status = -EFAULT; } - bcm_kfree(temp_buff); + + kfree(temp_buff); break; } case IOCTL_BCM_REGISTER_WRITE_PRIVATE: @@ -256,19 +246,16 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) UINT uiTempVar=0; /* Copy Ioctl Buffer structure */ - if(copy_from_user(&IoBuffer, argp, - sizeof(IOCTL_BUFFER))) - { - Status = -EFAULT; - break; - } + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + + if (IoBuffer.InputLength > sizeof(sWrmBuffer)) + return -EINVAL; + /* Get WrmBuffer structure */ - if(copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, - IoBuffer.InputLength)) - { - Status = -EFAULT; - break; - } + if(copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; + uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK; if(!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) && ((uiTempVar == EEPROM_REJECT_REG_1)|| @@ -277,8 +264,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) (uiTempVar == EEPROM_REJECT_REG_4))) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n"); - Status = -EFAULT; - break; + return -EFAULT; } Status = wrmalt(Adapter, (UINT)sWrmBuffer.Register, (PUINT)sWrmBuffer.Data, sizeof(ULONG)); @@ -305,56 +291,39 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) (Adapter->bPreparingForLowPowerMode ==TRUE)) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Rdms\n"); - Status = -EACCES; - break; + return -EACCES; } /* Copy Ioctl Buffer structure */ - if(copy_from_user(&IoBuffer, argp, - sizeof(IOCTL_BUFFER))) - { - Status = -EFAULT; - break; - } + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + + if (IoBuffer.InputLength > sizeof(sRdmBuffer)) + return -EINVAL; - temp_buff = (PCHAR)kmalloc(IoBuffer.OutputLength, GFP_KERNEL); + if(copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; + + /* FIXME: don't trust user supplied length */ + temp_buff = kmalloc(IoBuffer.OutputLength, GFP_KERNEL); if(!temp_buff) - { return STATUS_FAILURE; - } - if(copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, - IoBuffer.InputLength)) - { - Status = -EFAULT; - break; - } - if( -#if !defined(BCM_SHM_INTERFACE) - (((ULONG)sRdmBuffer.Register & 0x0F000000) != 0x0F000000) || -#endif - ((ULONG)sRdmBuffer.Register & 0x3) - ) + if((((ULONG)sRdmBuffer.Register & 0x0F000000) != 0x0F000000) || + ((ULONG)sRdmBuffer.Register & 0x3)) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "RDM Done On invalid Address : %x Access Denied.\n", (int)sRdmBuffer.Register); - Status = -EINVAL; - break; + return -EINVAL; } uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK; Status = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register, (PUINT)temp_buff, IoBuffer.OutputLength); - if(Status != STATUS_SUCCESS) - { - bcm_kfree(temp_buff); - return Status; - } - if(copy_to_user(IoBuffer.OutputBuffer, - (PCHAR)temp_buff, (UINT)IoBuffer.OutputLength)) - { - Status = -EFAULT; - } - bcm_kfree(temp_buff); + if(Status == STATUS_SUCCESS) + if(copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength)) + Status = -EFAULT; + + kfree(temp_buff); break; } case IOCTL_BCM_REGISTER_WRITE: @@ -367,36 +336,28 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) (Adapter->bPreparingForLowPowerMode ==TRUE)) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Wrms\n"); - Status = -EACCES; - break; + return -EACCES; } + /* Copy Ioctl Buffer structure */ - if(copy_from_user((PCHAR)&IoBuffer, argp, - sizeof(IOCTL_BUFFER))) - { - Status = -EFAULT; - break; - } + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + + if (IoBuffer.InputLength > sizeof(sWrmBuffer)) + return -EINVAL; + /* Get WrmBuffer structure */ - if(copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, - IoBuffer.InputLength)) - { - Status = -EFAULT; - break; - } - if( -#if !defined(BCM_SHM_INTERFACE) + if(copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; - (((ULONG)sWrmBuffer.Register & 0x0F000000) != 0x0F000000) || -#endif - ((ULONG)sWrmBuffer.Register & 0x3) - ) + if( (((ULONG)sWrmBuffer.Register & 0x0F000000) != 0x0F000000) || + ((ULONG)sWrmBuffer.Register & 0x3) ) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", (int)sWrmBuffer.Register); - Status = -EINVAL; - break; + return -EINVAL; } + uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK; if(!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) && ((uiTempVar == EEPROM_REJECT_REG_1)|| @@ -406,8 +367,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) (cmd == IOCTL_BCM_REGISTER_WRITE)) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n"); - Status = -EFAULT; - break; + return -EFAULT; } Status = wrmaltWithLock(Adapter, (UINT)sWrmBuffer.Register, @@ -436,19 +396,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) (Adapter->bPreparingForLowPowerMode ==TRUE)) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO Can't be set/clear in Low power Mode"); - Status = -EACCES; - break; + return -EACCES; } if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - { - Status = -EFAULT; - break; - } + return -EFAULT; + if (IoBuffer.InputLength > sizeof(gpio_info)) + return -EINVAL; if(copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength)) - { - Status = -EFAULT; - break; - } + return -EFAULT; uiBit = gpio_info.uiGpioNumber; uiOperation = gpio_info.uiGpioValue; @@ -517,8 +472,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) break; case BCM_LED_THREAD_STATE_CHANGE_REQ: { - - USER_THREAD_REQ threadReq = {0}; + USER_THREAD_REQ threadReq = { 0 }; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"User made LED thread InActive"); if((Adapter->IdleMode == TRUE) || @@ -529,21 +483,16 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) Status = -EACCES; break; } - Status =copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying the IOBufer from user space err:%d",Status); - Status = -EFAULT; - break; - } - Status= copy_from_user(&threadReq, IoBuffer.InputBuffer, IoBuffer.InputLength); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying the InputBuffer from user space err:%d",Status); - Status = -EFAULT; - break; - } + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + + if (IoBuffer.InputLength > sizeof(threadReq)) + return -EINVAL; + + if (copy_from_user(&threadReq, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; + //if LED thread is running(Actively or Inactively) set it state to make inactive if(Adapter->LEDInfo.led_thread_running) { @@ -572,19 +521,13 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if((Adapter->IdleMode == TRUE) || (Adapter->bShutStatus ==TRUE) || (Adapter->bPreparingForLowPowerMode ==TRUE)) - { - Status = -EACCES; - break; - } - if(copy_from_user((PCHAR)&IoBuffer, argp, sizeof(IOCTL_BUFFER))) { - Status = -EFAULT; - break; - } - if(copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength)) - { - Status = -EFAULT; - break; - } + return -EACCES; + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + if (IoBuffer.InputLength > sizeof(gpio_info)) + return -EINVAL; + if(copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; uiBit = gpio_info.uiGpioNumber; //Set the gpio output register Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, @@ -608,25 +551,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if((Adapter->IdleMode == TRUE) || (Adapter->bShutStatus ==TRUE) || (Adapter->bPreparingForLowPowerMode ==TRUE)) - { - Status = -EINVAL; - break; - } - Status = copy_from_user( (PCHAR)&IoBuffer, argp, sizeof( IOCTL_BUFFER)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying the IOBufer from user space err:%d",Status); - Status = -EFAULT; - break; - } + return -EINVAL; + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + if (IoBuffer.InputLength > sizeof(gpio_multi_info)) + return -EINVAL; + if (copy_from_user(&gpio_multi_info, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; - Status = copy_from_user( &gpio_multi_info, IoBuffer.InputBuffer, IoBuffer.InputLength); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying the IOBufer Contents from user space err:%d",Status); - Status = -EFAULT; - break; - } if(IsReqGpioIsLedInNVM(Adapter,pgpio_multi_info[WIMAX_IDX].uiGPIOMask)== FALSE) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",pgpio_multi_info[WIMAX_IDX].uiGPIOMask,Adapter->gpioBitMap); @@ -686,7 +618,6 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if(Status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying Content to IOBufer for user space err:%d",Status); - Status = -EFAULT; break; } } @@ -700,25 +631,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if((Adapter->IdleMode == TRUE) || (Adapter->bShutStatus ==TRUE) || (Adapter->bPreparingForLowPowerMode ==TRUE)) - { - Status = -EINVAL; - break; - } - Status = copy_from_user(&IoBuffer, argp, sizeof( IOCTL_BUFFER)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying the IOBufer from user space err:%d",Status); - Status = -EFAULT; - break; - } + return -EINVAL; - Status = copy_from_user( &gpio_multi_mode, IoBuffer.InputBuffer, IoBuffer.InputLength); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying the IOBufer Contents from user space err:%d",Status); - Status = -EFAULT; - break; - } + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + if (IoBuffer.InputLength > sizeof(gpio_multi_mode)) + return -EINVAL; + if (copy_from_user(&gpio_multi_mode, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; Status = rdmaltWithLock( Adapter, ( UINT) GPIO_MODE_REGISTER, ( PUINT) ucResetValue, sizeof( UINT)); if( STATUS_SUCCESS != Status) @@ -769,7 +689,6 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if(Status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying Content to IOBufer for user space err:%d",Status); - Status = -EFAULT; break; } } @@ -783,24 +702,20 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) case IOCTL_IDLE_REQ: { PVOID pvBuffer=NULL; + /* Copy Ioctl Buffer structure */ - if(copy_from_user(&IoBuffer, argp, - sizeof(IOCTL_BUFFER))) - { - Status = -EFAULT; - break; - } - pvBuffer=kmalloc(IoBuffer.InputLength, GFP_KERNEL); + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + + /* FIXME: don't accept any length from user */ + pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL); if(!pvBuffer) - { return -ENOMEM; - } - if(copy_from_user(pvBuffer, IoBuffer.InputBuffer, - IoBuffer.InputLength)) + if(copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) { Status = -EFAULT; - bcm_kfree(pvBuffer); + kfree(pvBuffer); break; } @@ -820,10 +735,9 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) Status = CopyBufferToControlPacket(Adapter, (PVOID)pvBuffer); cntrlEnd: up(&Adapter->LowPowerModeSync); - bcm_kfree(pvBuffer); + kfree(pvBuffer); break; } -#ifndef BCM_SHM_INTERFACE case IOCTL_BCM_BUFFER_DOWNLOAD_START: { INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock) ; @@ -844,7 +758,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) Status = reset_card_proc(Adapter); if(Status) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "reset_card_proc Failed!\n"); + pr_err(PFX "%s: reset_card_proc Failed!\n", Adapter->dev->name); up(&Adapter->fw_download_sema); up(&Adapter->NVMRdmWrmLock); break; @@ -862,7 +776,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) } case IOCTL_BCM_BUFFER_DOWNLOAD: { - FIRMWARE_INFO *psFwInfo=NULL; + FIRMWARE_INFO *psFwInfo = NULL; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid); do{ if(!down_trylock(&Adapter->fw_download_sema)) @@ -871,29 +785,23 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) Status=-EINVAL; break; } + /* Copy Ioctl Buffer structure */ if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n"); - Status = -EFAULT; - break; - } + return -EFAULT; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Length for FW DLD is : %lx\n", IoBuffer.InputLength); - psFwInfo=kmalloc(sizeof(*psFwInfo), GFP_KERNEL); + + if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO)) + return -EINVAL; + + psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL); if(!psFwInfo) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Failed to allocate buffer!!!!\n"); - Status = -ENOMEM; - break; - } - if(copy_from_user(psFwInfo, IoBuffer.InputBuffer, - IoBuffer.InputLength)) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy_from_user 2 failed\n"); - Status = -EFAULT; - break; - } + return -ENOMEM; + + if(copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; if(!psFwInfo->pvMappedFirmwareAddress || (psFwInfo->u32FirmwareLength == 0)) @@ -929,7 +837,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if(Status != STATUS_SUCCESS) up(&Adapter->fw_download_sema); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "IOCTL: Firmware File Uploaded\n"); - bcm_kfree(psFwInfo); + kfree(psFwInfo); break; } case IOCTL_BCM_BUFFER_DOWNLOAD_STOP: @@ -946,7 +854,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) Adapter->bBinDownloaded=TRUE; Adapter->bCfgDownloaded=TRUE; atomic_set(&Adapter->CurrNumFreeTxDesc, 0); - atomic_set(&Adapter->RxRollOverCount, 0); + Adapter->CurrNumRecvDescs=0; Adapter->downloadDDR = 0; @@ -999,7 +907,6 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) up(&Adapter->NVMRdmWrmLock); break; } -#endif case IOCTL_BE_BUCKET_SIZE: Adapter->BEBucketSize = *(PULONG)arg; Status = STATUS_SUCCESS; @@ -1044,22 +951,16 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) break; case IOCTL_GET_PACK_INFO: - if(copy_to_user(argp, &Adapter->PackInfo, - sizeof(PacketInfo)*NO_OF_QUEUES)) - { - Status = -EFAULT; - break; - } + if(copy_to_user(argp, &Adapter->PackInfo, sizeof(PacketInfo)*NO_OF_QUEUES)) + return -EFAULT; Status = STATUS_SUCCESS; break; case IOCTL_BCM_SWITCH_TRANSFER_MODE: { UINT uiData = 0; if(copy_from_user(&uiData, argp, sizeof(UINT))) - { - Status = -EFAULT; - break; - } + return -EFAULT; + if(uiData) /* Allow All Packets */ { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: ETH_PACKET_TUNNELING_MODE\n"); @@ -1078,22 +979,17 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) { /* Copy Ioctl Buffer structure */ if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - { - Status = -EFAULT; - break; - } - if(copy_to_user(IoBuffer.OutputBuffer, - VER_FILEVERSION_STR, (UINT)IoBuffer.OutputLength)) - { - Status = -EFAULT; - break; - } + return -EFAULT; + + if(copy_to_user(IoBuffer.OutputBuffer, VER_FILEVERSION_STR, IoBuffer.OutputLength)) + return -EFAULT; Status = STATUS_SUCCESS; break; } case IOCTL_BCM_GET_CURRENT_STATUS: { - LINK_STATE *plink_state = NULL; + LINK_STATE link_state; + /* Copy Ioctl Buffer structure */ if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) { @@ -1101,12 +997,15 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) Status = -EFAULT; break; } - plink_state = (LINK_STATE*)arg; - plink_state->bIdleMode = (UCHAR)Adapter->IdleMode; - plink_state->bShutdownMode = Adapter->bShutStatus; - plink_state->ucLinkStatus = (UCHAR)Adapter->LinkStatus; - if(copy_to_user(IoBuffer.OutputBuffer, - (PUCHAR)plink_state, (UINT)IoBuffer.OutputLength)) + + + memset(&link_state, 0, sizeof(link_state)); + link_state.bIdleMode = Adapter->IdleMode; + link_state.bShutdownMode = Adapter->bShutStatus; + link_state.ucLinkStatus = Adapter->LinkStatus; + + if (copy_to_user(IoBuffer.OutputBuffer, &link_state, + min_t(size_t, sizeof(link_state), IoBuffer.OutputLength))) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy_to_user Failed..\n"); Status = -EFAULT; @@ -1118,17 +1017,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) case IOCTL_BCM_SET_MAC_TRACING: { UINT tracing_flag; + /* copy ioctl Buffer structure */ - if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - { - Status = -EFAULT; - break; - } - if(copy_from_user(&tracing_flag, IoBuffer.InputBuffer,sizeof(UINT))) - { - Status = -EFAULT; - break; - } + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + + if(copy_from_user(&tracing_flag,IoBuffer.InputBuffer,sizeof(UINT))) + return -EFAULT; + if (tracing_flag) Adapter->pTarangs->MacTracingEnabled = TRUE; else @@ -1138,72 +1034,53 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) case IOCTL_BCM_GET_DSX_INDICATION: { ULONG ulSFId=0; - if(copy_from_user((PCHAR)&IoBuffer, argp, - sizeof(IOCTL_BUFFER))) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Invalid IO buffer!!!" ); - Status = -EFAULT; - break; - } + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + if(IoBuffer.OutputLength < sizeof(stLocalSFAddIndicationAlt)) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Mismatch req: %lx needed is =0x%zx!!!", - IoBuffer.OutputLength, sizeof(stLocalSFAddIndicationAlt)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, + "Mismatch req: %lx needed is =0x%zx!!!", + IoBuffer.OutputLength, sizeof(stLocalSFAddIndicationAlt)); return -EINVAL; } - if(copy_from_user(&ulSFId, IoBuffer.InputBuffer, - sizeof(ulSFId))) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Invalid SFID!!! %lu", ulSFId ); - Status = -EFAULT; - break; - } + + if(copy_from_user(&ulSFId, IoBuffer.InputBuffer, sizeof(ulSFId))) + return -EFAULT; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Get DSX Data SF ID is =%lx\n", ulSFId ); - get_dsx_sf_data_to_application(Adapter, ulSFId, - IoBuffer.OutputBuffer); + get_dsx_sf_data_to_application(Adapter, ulSFId, IoBuffer.OutputBuffer); Status=STATUS_SUCCESS; } break; case IOCTL_BCM_GET_HOST_MIBS: { - PCHAR temp_buff; + PVOID temp_buff; if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy_from user for IoBuff failed\n"); - Status = -EFAULT; - break; - } + return -EFAULT; if(IoBuffer.OutputLength != sizeof(S_MIBS_HOST_STATS_MIBS)) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Length Check failed %lu %zd\n", IoBuffer.OutputLength, - sizeof(S_MIBS_HOST_STATS_MIBS)); - return -EINVAL; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, + "Length Check failed %lu %zd\n", + IoBuffer.OutputLength, sizeof(S_MIBS_HOST_STATS_MIBS)); + return -EINVAL; } - temp_buff = (PCHAR)kmalloc(IoBuffer.OutputLength, GFP_KERNEL); - + /* FIXME: HOST_STATS are too big for kmalloc (122048)! */ + temp_buff = kzalloc(sizeof(S_MIBS_HOST_STATS_MIBS), GFP_KERNEL); if(!temp_buff) - { return STATUS_FAILURE; - } - - Status = ProcessGetHostMibs(Adapter, - (PUCHAR)temp_buff, IoBuffer.OutputLength); - Status = GetDroppedAppCntrlPktMibs((PVOID)temp_buff, - (PPER_TARANG_DATA)filp->private_data); + Status = ProcessGetHostMibs(Adapter, temp_buff); + GetDroppedAppCntrlPktMibs(temp_buff, pTarang); - if(copy_to_user(IoBuffer.OutputBuffer,(PCHAR)temp_buff, - sizeof(S_MIBS_HOST_STATS_MIBS))) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy to user failed\n"); - bcm_kfree(temp_buff); - return -EFAULT; - } + if (Status != STATUS_FAILURE) + if(copy_to_user(IoBuffer.OutputBuffer, temp_buff, sizeof(S_MIBS_HOST_STATS_MIBS))) + Status = -EFAULT; - bcm_kfree(temp_buff); + kfree(temp_buff); break; } @@ -1213,10 +1090,6 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) Adapter->usIdleModePattern = ABORT_IDLE_MODE; Adapter->bWakeUpDevice = TRUE; wake_up(&Adapter->process_rx_cntrlpkt); - #if 0 - Adapter->bTriedToWakeUpFromlowPowerMode = TRUE; - InterfaceAbortIdlemode (Adapter, Adapter->usIdleModePattern); - #endif } Status = STATUS_SUCCESS; break; @@ -1235,24 +1108,20 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) Status = -EACCES; break; } + /* Copy Ioctl Buffer structure */ - if(copy_from_user((PCHAR)&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - { - Status = -EFAULT; - break; - } + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; - pvBuffer=kmalloc(IoBuffer.InputLength, GFP_KERNEL); + /* FIXME: restrict length */ + pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL); if(!pvBuffer) - { return -ENOMEM; - break; - } /* Get WrmBuffer structure */ - if(copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) + if(copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) { - bcm_kfree(pvBuffer); + kfree(pvBuffer); Status = -EFAULT; break; } @@ -1262,7 +1131,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if(((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 || ((ULONG)pBulkBuffer->Register & 0x3)) { - bcm_kfree(pvBuffer); + kfree(pvBuffer); BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,"WRM Done On invalid Address : %x Access Denied.\n",(int)pBulkBuffer->Register); Status = -EINVAL; break; @@ -1277,7 +1146,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) (uiTempVar == EEPROM_REJECT_REG_4)) && (cmd == IOCTL_BCM_REGISTER_WRITE)) { - bcm_kfree(pvBuffer); + kfree(pvBuffer); BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,"EEPROM Access Denied, not in VSG Mode\n"); Status = -EFAULT; break; @@ -1293,30 +1162,19 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "WRM Failed\n"); } - bcm_kfree(pvBuffer); + kfree(pvBuffer); break; } case IOCTL_BCM_GET_NVM_SIZE: - { - if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - { - //IOLog("failed NVM first"); - Status = -EFAULT; - break; - } + return -EFAULT; + if(Adapter->eNVMType == NVM_EEPROM || Adapter->eNVMType == NVM_FLASH ) { - if(copy_to_user(IoBuffer.OutputBuffer, - (unsigned char *)&Adapter->uiNVMDSDSize, (UINT)sizeof(UINT))) - { - Status = -EFAULT; - return Status; - } + if(copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiNVMDSDSize, sizeof(UINT))) + return -EFAULT; } - Status = STATUS_SUCCESS ; - } break; case IOCTL_BCM_CAL_INIT : @@ -1325,38 +1183,26 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) UINT uiSectorSize = 0 ; if(Adapter->eNVMType == NVM_FLASH) { - Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Copy From User space failed. status :%d", Status); + if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) return -EFAULT; - } - uiSectorSize = *((PUINT)(IoBuffer.InputBuffer)); /* FIXME: unchecked __user access */ + + if (copy_from_user(&uiSectorSize, IoBuffer.InputBuffer, sizeof(UINT))) + return -EFAULT; + if((uiSectorSize < MIN_SECTOR_SIZE) || (uiSectorSize > MAX_SECTOR_SIZE)) { - - Status = copy_to_user(IoBuffer.OutputBuffer, - (unsigned char *)&Adapter->uiSectorSize , - (UINT)sizeof(UINT)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Coping the sector size to use space failed. status:%d",Status); - return -EFAULT; - } + if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiSectorSize, + sizeof(UINT))) + return -EFAULT; } else { if(IsFlash2x(Adapter)) { - Status = copy_to_user(IoBuffer.OutputBuffer, - (unsigned char *)&Adapter->uiSectorSize , - (UINT)sizeof(UINT)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Coping the sector size to use space failed. status:%d",Status); - return -EFAULT; - } - + if (copy_to_user(IoBuffer.OutputBuffer, + &Adapter->uiSectorSize , + sizeof(UINT))) + return -EFAULT; } else { @@ -1380,25 +1226,19 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) } break; case IOCTL_BCM_SET_DEBUG : +#ifdef DEBUG { USER_BCM_DBG_STATE sUserDebugState; // BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Entered the ioctl %x \n", IOCTL_BCM_SET_DEBUG ); BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In SET_DEBUG ioctl\n"); - Status = copy_from_user((PCHAR)&IoBuffer, argp, sizeof(IOCTL_BUFFER)); - if(Status) - { - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy from user failed\n"); - Status = -EFAULT; - break; - } - Status = copy_from_user(&sUserDebugState,IoBuffer.InputBuffer, sizeof(USER_BCM_DBG_STATE)); - if(Status) - { - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IoBuffer.InputBuffer failed"); + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) return -EFAULT; - } + + if (copy_from_user(&sUserDebugState, IoBuffer.InputBuffer, sizeof(USER_BCM_DBG_STATE))) + return -EFAULT; + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL_BCM_SET_DEBUG: OnOff=%d Type = 0x%x ", sUserDebugState.OnOff, sUserDebugState.Type); @@ -1421,15 +1261,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) BCM_SHOW_DEBUG_BITMAP(Adapter); } +#endif break; case IOCTL_BCM_NVM_READ: case IOCTL_BCM_NVM_WRITE: { - - NVM_READWRITE stNVMReadWrite = {}; + NVM_READWRITE stNVMReadWrite; PUCHAR pReadData = NULL; - void __user * pBuffertobeCopied = NULL; - ULONG ulDSDMagicNumInUsrBuff = 0 ; + ULONG ulDSDMagicNumInUsrBuff = 0; struct timeval tv0, tv1; memset(&tv0,0,sizeof(struct timeval)); memset(&tv1,0,sizeof(struct timeval)); @@ -1454,21 +1293,12 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) /* Copy Ioctl Buffer structure */ if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"copy_from_user failed\n"); - Status = -EFAULT; - break; - } - if(IOCTL_BCM_NVM_READ == cmd) - pBuffertobeCopied = IoBuffer.OutputBuffer; - else - pBuffertobeCopied = IoBuffer.InputBuffer; + return -EFAULT; - if(copy_from_user(&stNVMReadWrite, pBuffertobeCopied,sizeof(NVM_READWRITE))) - { - Status = -EFAULT; - break; - } + if(copy_from_user(&stNVMReadWrite, + (IOCTL_BCM_NVM_READ == cmd) ? IoBuffer.OutputBuffer : IoBuffer.InputBuffer, + sizeof(NVM_READWRITE))) + return -EFAULT; // // Deny the access if the offset crosses the cal area limit. @@ -1481,18 +1311,15 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) break; } - pReadData =(PCHAR)kmalloc(stNVMReadWrite.uiNumBytes, GFP_KERNEL); - + pReadData = kzalloc(stNVMReadWrite.uiNumBytes, GFP_KERNEL); if(!pReadData) return -ENOMEM; - memset(pReadData,0,stNVMReadWrite.uiNumBytes); - if(copy_from_user(pReadData, stNVMReadWrite.pBuffer, stNVMReadWrite.uiNumBytes)) { Status = -EFAULT; - bcm_kfree(pReadData); + kfree(pReadData); break; } @@ -1507,7 +1334,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); up(&Adapter->NVMRdmWrmLock); - bcm_kfree(pReadData); + kfree(pReadData); return -EACCES; } @@ -1518,13 +1345,12 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if(Status != STATUS_SUCCESS) { - bcm_kfree(pReadData); + kfree(pReadData); return Status; } - if(copy_to_user(stNVMReadWrite.pBuffer, - pReadData, (UINT)stNVMReadWrite.uiNumBytes)) + if(copy_to_user(stNVMReadWrite.pBuffer,pReadData, stNVMReadWrite.uiNumBytes)) { - bcm_kfree(pReadData); + kfree(pReadData); Status = -EFAULT; } } @@ -1539,7 +1365,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); up(&Adapter->NVMRdmWrmLock); - bcm_kfree(pReadData); + kfree(pReadData); return -EACCES; } @@ -1567,7 +1393,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DSD Sig is present neither in Flash nor User provided Input.."); up(&Adapter->NVMRdmWrmLock); - bcm_kfree(pReadData); + kfree(pReadData); return Status; } @@ -1576,7 +1402,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DSD Sig is present neither in Flash nor User provided Input.."); up(&Adapter->NVMRdmWrmLock); - bcm_kfree(pReadData); + kfree(pReadData); return Status; } } @@ -1593,7 +1419,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if(Status != STATUS_SUCCESS) { - bcm_kfree(pReadData); + kfree(pReadData); return Status; } } @@ -1601,7 +1427,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " timetaken by Write/read :%ld msec\n",(tv1.tv_sec - tv0.tv_sec)*1000 +(tv1.tv_usec - tv0.tv_usec)/1000); - bcm_kfree(pReadData); + kfree(pReadData); Status = STATUS_SUCCESS; } break; @@ -1614,7 +1440,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) UINT BuffSize = 0; UINT ReadBytes = 0; UINT ReadOffset = 0; - char __user *OutPutBuff = NULL; + void __user *OutPutBuff; if(IsFlash2x(Adapter) != TRUE) { @@ -1623,20 +1449,12 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) } BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called"); - Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) return -EFAULT; - } //Reading FLASH 2.x READ structure - Status = copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer,sizeof(FLASH2X_READWRITE)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of Input Buffer failed"); + if (copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer,sizeof(FLASH2X_READWRITE))) return -EFAULT; - } BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.Section :%x" ,sFlash2xRead.Section); @@ -1672,7 +1490,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); up(&Adapter->NVMRdmWrmLock); - bcm_kfree(pReadBuff); + kfree(pReadBuff); return -EACCES; } @@ -1700,7 +1518,6 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if(Status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Copy to use failed with status :%d", Status); - Status = -EFAULT; break; } NOB = NOB - ReadBytes; @@ -1712,15 +1529,15 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) } up(&Adapter->NVMRdmWrmLock); - bcm_kfree(pReadBuff); + kfree(pReadBuff); } break ; case IOCTL_BCM_FLASH2X_SECTION_WRITE : { FLASH2X_READWRITE sFlash2xWrite = {0}; - PUCHAR pWriteBuff = NULL; - void __user *InputAddr = NULL; + PUCHAR pWriteBuff; + void __user *InputAddr; UINT NOB = 0; UINT BuffSize = 0; UINT WriteOffset = 0; @@ -1737,33 +1554,17 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_FLASH2X_SECTION_WRITE Called"); - Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) return -EFAULT; - } //Reading FLASH 2.x READ structure - Status = copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Reading of output Buffer from IOCTL buffer fails"); + if (copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE))) return -EFAULT; - } BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.Section :%x" ,sFlash2xWrite.Section); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.offset :%d" ,sFlash2xWrite.offset); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.numOfBytes :%x" ,sFlash2xWrite.numOfBytes); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.bVerify :%x\n" ,sFlash2xWrite.bVerify); - #if 0 - if((sFlash2xWrite.Section == ISO_IMAGE1) ||(sFlash2xWrite.Section == ISO_IMAGE2) || - (sFlash2xWrite.Section == DSD0) || (sFlash2xWrite.Section == DSD1) || (sFlash2xWrite.Section == DSD2)) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"ISO/DSD Image write is not allowed.... "); - return STATUS_FAILURE ; - } - #endif if((sFlash2xWrite.Section != VSA0) && (sFlash2xWrite.Section != VSA1) && (sFlash2xWrite.Section != VSA2) ) { @@ -1783,12 +1584,10 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) else BuffSize = NOB ; - pWriteBuff = (PCHAR)kmalloc(BuffSize, GFP_KERNEL); + pWriteBuff = kmalloc(BuffSize, GFP_KERNEL); if(pWriteBuff == NULL) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed for Flash 2.x Read Structure"); return -ENOMEM; - } + //extracting the remainder of the given offset. WriteBytes = Adapter->uiSectorSize ; @@ -1805,7 +1604,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); up(&Adapter->NVMRdmWrmLock); - bcm_kfree(pWriteBuff); + kfree(pWriteBuff); return -EACCES; } @@ -1816,7 +1615,6 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if(Status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Copy to user failed with status :%d", Status); - Status = -EFAULT; break ; } BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pWriteBuff,WriteBytes); @@ -1844,28 +1642,22 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) } while(NOB > 0); BcmFlash2xWriteSig(Adapter,sFlash2xWrite.Section); up(&Adapter->NVMRdmWrmLock); - bcm_kfree(pWriteBuff); + kfree(pWriteBuff); } break ; case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP : { - PFLASH2X_BITMAP psFlash2xBitMap = NULL ; + PFLASH2X_BITMAP psFlash2xBitMap; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called"); - Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) return -EFAULT; - } + if(IoBuffer.OutputLength != sizeof(FLASH2X_BITMAP)) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Structure size mismatch Lib :0x%lx Driver :0x%zx ",IoBuffer.OutputLength, sizeof(FLASH2X_BITMAP)); - break; - } + return -EINVAL; - psFlash2xBitMap = (PFLASH2X_BITMAP)kzalloc(sizeof(FLASH2X_BITMAP), GFP_KERNEL); + psFlash2xBitMap = kzalloc(sizeof(FLASH2X_BITMAP), GFP_KERNEL); if(psFlash2xBitMap == NULL) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory is not available"); @@ -1880,20 +1672,16 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); up(&Adapter->NVMRdmWrmLock); - bcm_kfree(psFlash2xBitMap); + kfree(psFlash2xBitMap); return -EACCES; } BcmGetFlash2xSectionalBitMap(Adapter, psFlash2xBitMap); up(&Adapter->NVMRdmWrmLock); - Status = copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(FLASH2X_BITMAP)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copying Flash2x bitMap failed"); - bcm_kfree(psFlash2xBitMap); - return -EFAULT; - } - bcm_kfree(psFlash2xBitMap); + if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(FLASH2X_BITMAP))) + Status = -EFAULT; + + kfree(psFlash2xBitMap); } break ; case IOCTL_BCM_SET_ACTIVE_SECTION : @@ -1911,14 +1699,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if(Status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); - return -EFAULT; + return Status; } Status = copy_from_user(&eFlash2xSectionVal,IoBuffer.InputBuffer, sizeof(INT)); if(Status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed"); - return -EFAULT; + return Status; } down(&Adapter->NVMRdmWrmLock); @@ -1946,29 +1734,6 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) Adapter->bAllDSDWriteAllow = FALSE ; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_BCM_IDENTIFY_ACTIVE_SECTION called"); - #if 0 - SECTION_TYPE section = 0 ; - - - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_IDENTIFY_ACTIVE_SECTION Called"); - Status = copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Copy of IOCTL BUFFER failed"); - return -EFAULT; - } - Status = copy_from_user((PCHAR)section,(PCHAR)&IoBuffer, sizeof(INT)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Copy of section type failed failed"); - return -EFAULT; - } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Read Section :%d", section); - if(section == DSD) - Adapter->ulFlashCalStart = Adapter->uiActiveDSDOffsetAtFwDld ; - else - Status = STATUS_FAILURE ; - #endif Status = STATUS_SUCCESS ; } break ; @@ -1989,14 +1754,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if(Status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed Status :%d", Status); - return -EFAULT; + return Status; } - Status = copy_from_user(&sCopySectStrut,IoBuffer.InputBuffer, sizeof(FLASH2X_COPY_SECTION)); + Status = copy_from_user(&sCopySectStrut, IoBuffer.InputBuffer, sizeof(FLASH2X_COPY_SECTION)); if(Status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of Copy_Section_Struct failed with Status :%d", Status); - return -EFAULT; + return Status; } BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source SEction :%x", sCopySectStrut.SrcSection); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Destination SEction :%x", sCopySectStrut.DstSection); @@ -2067,7 +1832,6 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if(Status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); - Status = -EFAULT; break; } if(Adapter->eNVMType != NVM_FLASH) @@ -2080,35 +1844,18 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) { if(IoBuffer.OutputLength < sizeof(FLASH2X_CS_INFO)) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0," Passed buffer size:0x%lX is insufficient for the CS structure.. \nRequired size :0x%zx ",IoBuffer.OutputLength, sizeof(FLASH2X_CS_INFO)); - Status = -EINVAL; - break; - } + return -EINVAL; - Status = copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlash2xCSInfo, sizeof(FLASH2X_CS_INFO)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copying Flash2x cs info failed"); - Status = -EFAULT; - break; - } + if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlash2xCSInfo, sizeof(FLASH2X_CS_INFO))) + return -EFAULT; } else { if(IoBuffer.OutputLength < sizeof(FLASH_CS_INFO)) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0," Passed buffer size:0x%lX is insufficient for the CS structure.. Required size :0x%zx ",IoBuffer.OutputLength, sizeof(FLASH_CS_INFO)); - Status = -EINVAL; - break; - } - Status = copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlashCSInfo, sizeof(FLASH_CS_INFO)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copying Flash CS info failed"); - Status = -EFAULT; - break; - } + return -EINVAL; + + if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlashCSInfo, sizeof(FLASH_CS_INFO))) + return -EFAULT; } } @@ -2130,13 +1877,13 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if(Status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); - return -EFAULT; + return Status; } - Status = copy_from_user(&eFlash2xSectionVal,IoBuffer.InputBuffer, sizeof(INT)); + Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT)); if(Status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed"); - return -EFAULT; + return Status; } BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Read Section :%d", eFlash2xSectionVal); @@ -2166,13 +1913,13 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) case IOCTL_BCM_NVM_RAW_READ : { - NVM_READWRITE stNVMRead = {}; + NVM_READWRITE stNVMRead; INT NOB ; INT BuffSize ; INT ReadOffset = 0; UINT ReadBytes = 0 ; - PUCHAR pReadBuff = NULL ; - char __user *OutPutBuff = NULL ; + PUCHAR pReadBuff; + void __user *OutPutBuff; if(Adapter->eNVMType != NVM_FLASH) { @@ -2189,10 +1936,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) } if(copy_from_user(&stNVMRead, IoBuffer.OutputBuffer,sizeof(NVM_READWRITE))) - { - Status = -EFAULT; - break; - } + return -EFAULT; NOB = stNVMRead.uiNumBytes; //In Raw-Read max Buff size : 64MB @@ -2202,11 +1946,10 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) else BuffSize = NOB ; - ReadOffset = stNVMRead.uiOffset ; + ReadOffset = stNVMRead.uiOffset; OutPutBuff = stNVMRead.pBuffer; - - pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL); + pReadBuff = kzalloc(BuffSize , GFP_KERNEL); if(pReadBuff == NULL) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed for Flash 2.x Read Structure"); @@ -2220,7 +1963,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) (Adapter->bPreparingForLowPowerMode ==TRUE)) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); - bcm_kfree(pReadBuff); + kfree(pReadBuff); up(&Adapter->NVMRdmWrmLock); return -EACCES; } @@ -2241,13 +1984,12 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) break; } - BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pReadBuff, ReadBytes); + BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pReadBuff,ReadBytes); Status = copy_to_user(OutPutBuff, pReadBuff,ReadBytes); if(Status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Copy to use failed with status :%d", Status); - Status = -EFAULT; break; } NOB = NOB - ReadBytes; @@ -2260,7 +2002,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) } Adapter->bFlashRawRead = FALSE ; up(&Adapter->NVMRdmWrmLock); - bcm_kfree(pReadBuff); + kfree(pReadBuff); break ; } @@ -2273,7 +2015,6 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if(Status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"copy of Ioctl buffer is failed from user space"); - Status = -EFAULT; break; } @@ -2281,7 +2022,6 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if(Status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"copy of control bit mask failed from user space"); - Status = -EFAULT; break; } BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\n Got user defined cntrl msg bit mask :%lx", RxCntrlMsgBitMask); @@ -2300,71 +2040,44 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) DevInfo.u32NVMType = Adapter->eNVMType; DevInfo.u32InterfaceType = BCM_USB; - Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); - Status = -EFAULT; - break; - } + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + if(IoBuffer.OutputLength < sizeof(DevInfo)) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"User Passed buffer length is less than actural buffer size"); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"user passed buffer size :0x%lX, expected size :0x%zx",IoBuffer.OutputLength, sizeof(DevInfo)); - Status = -EINVAL; - break; - } - Status = copy_to_user(IoBuffer.OutputBuffer, &DevInfo, sizeof(DevInfo)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"copying Dev info structure to user space buffer failed"); - Status = -EFAULT; - break; - } + return -EINVAL; + + if (copy_to_user(IoBuffer.OutputBuffer, &DevInfo, sizeof(DevInfo))) + return -EFAULT; } break ; case IOCTL_BCM_TIME_SINCE_NET_ENTRY: { ST_TIME_ELAPSED stTimeElapsedSinceNetEntry = {0}; - struct timeval tv = {0} ; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_BCM_TIME_SINCE_NET_ENTRY called"); - Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); - Status = -EFAULT; - break; - } + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + if(IoBuffer.OutputLength < sizeof(ST_TIME_ELAPSED)) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"User Passed buffer length:0x%lx is less than expected buff size :0x%zX",IoBuffer.OutputLength,sizeof(ST_TIME_ELAPSED)); - Status = -EINVAL; - break; - } + return -EINVAL; - //stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = Adapter->liTimeSinceLastNetEntry; - do_gettimeofday(&tv); - stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = tv.tv_sec - Adapter->liTimeSinceLastNetEntry; + stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = get_seconds() - Adapter->liTimeSinceLastNetEntry; - Status = copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry, sizeof(ST_TIME_ELAPSED)); - if(Status) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"copying ST_TIME_ELAPSED structure to user space buffer failed"); - Status = -EFAULT; - break; - } + if (copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry, sizeof(ST_TIME_ELAPSED))) + return -EFAULT; } break; - default: - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "wrong input %x",cmd); - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In default ioctl %d\n", cmd); - Status = STATUS_FAILURE; + case IOCTL_CLOSE_NOTIFICATION: + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_CLOSE_NOTIFICATION"); + break; + default: + pr_info(DRV_NAME ": unknown ioctl cmd=%#x\n", cmd); + Status = STATUS_FAILURE; break; } return Status; @@ -2380,59 +2093,37 @@ static struct file_operations bcm_fops = { .llseek = no_llseek, }; +extern struct class *bcm_class; int register_control_device_interface(PMINI_ADAPTER Adapter) { + if(Adapter->major>0) - return Adapter->major; - Adapter->major = register_chrdev(0, "tarang", &bcm_fops); - if(Adapter->major < 0) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "register_chrdev:Failed to registering WiMax control char device!"); - return Adapter->major; - } - - bcm_class = NULL; - bcm_class = class_create (THIS_MODULE, "tarang"); - if(IS_ERR (bcm_class)) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Unable to create class\n"); - unregister_chrdev(Adapter->major, "tarang"); - Adapter->major = 0; - return -ENODEV; + return Adapter->major; + + Adapter->major = register_chrdev(0, DEV_NAME, &bcm_fops); + if(Adapter->major < 0) { + pr_err(DRV_NAME ": could not created character device\n"); + return Adapter->major; } + Adapter->pstCreatedClassDevice = device_create (bcm_class, NULL, - MKDEV(Adapter->major, 0), -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26) - NULL , -#endif - "tarang"); + MKDEV(Adapter->major, 0), Adapter, + DEV_NAME); - if(IS_ERR(Adapter->pstCreatedClassDevice)) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "class device did not get created : %ld", PTR_ERR(Adapter->pstCreatedClassDevice) ); + if(IS_ERR(Adapter->pstCreatedClassDevice)) { + pr_err(DRV_NAME ": class device create failed\n"); + unregister_chrdev(Adapter->major, DEV_NAME); + return PTR_ERR(Adapter->pstCreatedClassDevice); } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Got Major No: %d", Adapter->major); - return 0; + + return 0; } void unregister_control_device_interface(PMINI_ADAPTER Adapter) { - if(Adapter->major > 0) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "destroying class device"); + if(Adapter->major > 0) { device_destroy (bcm_class, MKDEV(Adapter->major, 0)); + unregister_chrdev(Adapter->major, DEV_NAME); } - if(!IS_ERR(bcm_class)) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "destroying created class "); - class_destroy (bcm_class); - bcm_class = NULL; - } - if(Adapter->major > 0) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"unregistering character interface"); - unregister_chrdev(Adapter->major, "tarang"); - } - } diff --git a/trunk/drivers/staging/bcm/Bcmnet.c b/trunk/drivers/staging/bcm/Bcmnet.c index bc2969821421..a6ce2396c791 100644 --- a/trunk/drivers/staging/bcm/Bcmnet.c +++ b/trunk/drivers/staging/bcm/Bcmnet.c @@ -1,264 +1,238 @@ #include "headers.h" -static INT bcm_notify_event(struct notifier_block *nb, ULONG event, PVOID dev) +struct net_device *gblpnetdev; + +static INT bcm_open(struct net_device *dev) { - struct net_device *ndev = (struct net_device*)dev; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); - //PMINI_ADAPTER Adapter = (PMINI_ADAPTER)ndev->priv; - if(strncmp(ndev->name,gblpnetdev->name,5)==0) - { - switch(event) - { - case NETDEV_CHANGEADDR: - case NETDEV_GOING_DOWN: - /*ignore this */ - break; - case NETDEV_DOWN: - break; - - case NETDEV_UP: - break; - - case NETDEV_REGISTER: - /* Increment the Reference Count for "veth0" */ - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Register RefCount: %x\n", - netdev_refcnt_read(ndev)); - dev_hold(ndev); - break; - - case NETDEV_UNREGISTER: - /* Decrement the Reference Count for "veth0" */ - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Unregister RefCnt: %x\n", - netdev_refcnt_read(ndev)); - dev_put(ndev); - break; - }; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev); + + if (Adapter->fw_download_done == FALSE) { + pr_notice(PFX "%s: link up failed (download in progress)\n", + dev->name); + return -EBUSY; } - return NOTIFY_DONE; -} -/* Notifier block to receive netdevice events */ -static struct notifier_block bcm_notifier_block = -{ - .notifier_call = bcm_notify_event, -}; + if (netif_msg_ifup(Adapter)) + pr_info(PFX "%s: enabling interface\n", dev->name); -struct net_device *gblpnetdev; -/***************************************************************************************/ -/* proto-type of lower function */ -#ifdef BCM_SHM_INTERFACE -const char *bcmVirtDeviceName="bcmeth"; -#endif + if (Adapter->LinkUpStatus) { + if (netif_msg_link(Adapter)) + pr_info(PFX "%s: link up\n", dev->name); -static INT bcm_open(struct net_device *dev) -{ - PMINI_ADAPTER Adapter = NULL ; //(PMINI_ADAPTER)dev->priv; - Adapter = GET_BCM_ADAPTER(dev); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "======>"); - if(Adapter->fw_download_done==FALSE) - return -EINVAL; - Adapter->if_up=1; - if(Adapter->LinkUpStatus == 1){ - if(netif_queue_stopped(Adapter->dev)){ - netif_carrier_on(Adapter->dev); - netif_start_queue(Adapter->dev); - } + netif_carrier_on(Adapter->dev); + netif_start_queue(Adapter->dev); } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "<======"); - return 0; + return 0; } static INT bcm_close(struct net_device *dev) { - PMINI_ADAPTER Adapter = NULL ;//gpadapter ; - Adapter = GET_BCM_ADAPTER(dev); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "=====>"); - Adapter->if_up=0; - if(!netif_queue_stopped(dev)) { - netif_carrier_off(dev); - netif_stop_queue(dev); - } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"<====="); - return 0; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev); + + if (netif_msg_ifdown(Adapter)) + pr_info(PFX "%s: disabling interface\n", dev->name); + + netif_carrier_off(dev); + netif_stop_queue(dev); + + return 0; +} + +static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb) +{ + return ClassifyPacket(netdev_priv(dev), skb); } -static struct net_device_stats *bcm_get_stats(struct net_device *dev) +/******************************************************************* +* Function - bcm_transmit() +* +* Description - This is the main transmit function for our virtual +* interface(eth0). It handles the ARP packets. It +* clones this packet and then Queue it to a suitable +* Queue. Then calls the transmit_packet(). +* +* Parameter - skb - Pointer to the socket buffer structure +* dev - Pointer to the virtual net device structure +* +*********************************************************************/ + +static netdev_tx_t bcm_transmit(struct sk_buff *skb, struct net_device *dev) { - PLINUX_DEP_DATA pLinuxData=NULL; - PMINI_ADAPTER Adapter = NULL ;// gpadapter ; - Adapter = GET_BCM_ADAPTER(dev); - pLinuxData = (PLINUX_DEP_DATA)(Adapter->pvOsDepData); - - //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Dev = %p, pLinuxData = %p", dev, pLinuxData); - pLinuxData->netstats.rx_packets=atomic_read(&Adapter->RxRollOverCount)*64*1024+Adapter->PrevNumRecvDescs; - pLinuxData->netstats.rx_bytes=atomic_read(&Adapter->GoodRxByteCount)+atomic_read(&Adapter->BadRxByteCount); - pLinuxData->netstats.rx_dropped=atomic_read(&Adapter->RxPacketDroppedCount); - pLinuxData->netstats.rx_errors=atomic_read(&Adapter->RxPacketDroppedCount); - pLinuxData->netstats.rx_length_errors=0; - pLinuxData->netstats.rx_frame_errors=0; - pLinuxData->netstats.rx_crc_errors=0; - pLinuxData->netstats.tx_bytes=atomic_read(&Adapter->GoodTxByteCount); - pLinuxData->netstats.tx_packets=atomic_read(&Adapter->TxTotalPacketCount); - pLinuxData->netstats.tx_dropped=atomic_read(&Adapter->TxDroppedPacketCount); - - return &(pLinuxData->netstats); + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev); + u16 qindex = skb_get_queue_mapping(skb); + + + if (Adapter->device_removed || !Adapter->LinkUpStatus) + goto drop; + + if (Adapter->TransferMode != IP_PACKET_ONLY_MODE) + goto drop; + + if (INVALID_QUEUE_INDEX == qindex) + goto drop; + + if (Adapter->PackInfo[qindex].uiCurrentPacketsOnHost >= + SF_MAX_ALLOWED_PACKETS_TO_BACKUP) + return NETDEV_TX_BUSY; + + /* Now Enqueue the packet */ + if (netif_msg_tx_queued(Adapter)) + pr_info(PFX "%s: enqueueing packet to queue %d\n", + dev->name, qindex); + + spin_lock(&Adapter->PackInfo[qindex].SFQueueLock); + Adapter->PackInfo[qindex].uiCurrentBytesOnHost += skb->len; + Adapter->PackInfo[qindex].uiCurrentPacketsOnHost++; + + *((B_UINT32 *) skb->cb + SKB_CB_LATENCY_OFFSET) = jiffies; + ENQUEUEPACKET(Adapter->PackInfo[qindex].FirstTxQueue, + Adapter->PackInfo[qindex].LastTxQueue, skb); + atomic_inc(&Adapter->TotalPacketCount); + spin_unlock(&Adapter->PackInfo[qindex].SFQueueLock); + + /* FIXME - this is racy and incorrect, replace with work queue */ + if (!atomic_read(&Adapter->TxPktAvail)) { + atomic_set(&Adapter->TxPktAvail, 1); + wake_up(&Adapter->tx_packet_wait_queue); + } + return NETDEV_TX_OK; + + drop: + dev_kfree_skb(skb); + return NETDEV_TX_OK; } + + + /** @ingroup init_functions Register other driver entry points with the kernel */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) -static struct net_device_ops bcmNetDevOps = { +static const struct net_device_ops bcmNetDevOps = { .ndo_open = bcm_open, .ndo_stop = bcm_close, - .ndo_get_stats = bcm_get_stats, .ndo_start_xmit = bcm_transmit, .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, + .ndo_select_queue = bcm_select_queue, }; -#endif -int register_networkdev(PMINI_ADAPTER Adapter) +static struct device_type wimax_type = { + .name = "wimax", +}; + +static int bcm_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - int result=0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) - void **temp = NULL; /* actually we're *allocating* the device in alloc_etherdev */ -#endif - Adapter->dev = alloc_etherdev(sizeof(PMINI_ADAPTER)); - if(!Adapter->dev) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "ERR: No Dev"); - return -ENOMEM; - } - gblpnetdev = Adapter->dev; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) - Adapter->dev->priv = Adapter; -#else - temp = netdev_priv(Adapter->dev); - *temp = (void *)Adapter; -#endif - //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "init adapterptr: %x %x\n", (UINT)Adapter, temp); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) - Adapter->dev->netdev_ops = &bcmNetDevOps; -#else - Adapter->dev->open = bcm_open; - Adapter->dev->stop = bcm_close; - Adapter->dev->get_stats = bcm_get_stats; - Adapter->dev->hard_start_xmit = bcm_transmit; - Adapter->dev->hard_header_len = ETH_HLEN + LEADER_SIZE; -#endif - -#ifndef BCM_SHM_INTERFACE - Adapter->dev->mtu = MTU_SIZE; /* 1400 Bytes */ - /* Read the MAC Address from EEPROM */ - ReadMacAddressFromNVM(Adapter); + cmd->supported = 0; + cmd->advertising = 0; + cmd->speed = SPEED_10000; + cmd->duplex = DUPLEX_FULL; + cmd->port = PORT_TP; + cmd->phy_address = 0; + cmd->transceiver = XCVR_INTERNAL; + cmd->autoneg = AUTONEG_DISABLE; + cmd->maxtxpkt = 0; + cmd->maxrxpkt = 0; + return 0; +} +static void bcm_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev); + PS_INTERFACE_ADAPTER psIntfAdapter = Adapter->pvInterfaceAdapter; + struct usb_device *udev = interface_to_usbdev(psIntfAdapter->interface); - /* Register the notifier block for getting netdevice events */ - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Registering netdevice notifier\n"); - result = register_netdevice_notifier(&bcm_notifier_block); - if(result) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "BCM Notifier Block did not get registered"); - Adapter->bNetdeviceNotifierRegistered = FALSE; - return result; - } - else - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "BCM Notifier got Registered"); - Adapter->bNetdeviceNotifierRegistered = TRUE; - } + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + snprintf(info->fw_version, sizeof(info->fw_version), "%u.%u", + Adapter->uiFlashLayoutMajorVersion, + Adapter->uiFlashLayoutMinorVersion); -#else - - Adapter->dev->mtu = CPE_MTU_SIZE; - -#if 0 - //for CPE - harcode the virtual mac address - Adapter->dev->dev_addr[0] = MII_WIMAX_MACADDRESS[0]; - Adapter->dev->dev_addr[1] = MII_WIMAX_MACADDRESS[1]; - Adapter->dev->dev_addr[2] = MII_WIMAX_MACADDRESS[2]; - Adapter->dev->dev_addr[3] = MII_WIMAX_MACADDRESS[3]; - Adapter->dev->dev_addr[4] = MII_WIMAX_MACADDRESS[4]; - Adapter->dev->dev_addr[5] = MII_WIMAX_MACADDRESS[5]; -#else - ReadMacAddressFromNVM(Adapter); -#endif - strcpy(Adapter->dev->name, bcmVirtDeviceName); //Copy the device name - -#endif - - result = register_netdev(Adapter->dev); - if (!result) - { - Adapter->bNetworkInterfaceRegistered = TRUE ; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Beceem Network device name is %s!", Adapter->dev->name); - } - else - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Network device can not be registered!"); - Adapter->bNetworkInterfaceRegistered = FALSE ; - return result; - } + usb_make_path(udev, info->bus_info, sizeof(info->bus_info)); +} -#if 0 - Adapter->stDebugState.debug_level = DBG_LVL_CURR; - Adapter->stDebugState.type =(UINT)0xffffffff; - Adapter->stDebugState.subtype[DBG_TYPE_OTHERS] = 0xffffffff; - Adapter->stDebugState.subtype[DBG_TYPE_RX] = 0xffffffff; - Adapter->stDebugState.subtype[DBG_TYPE_TX] = 0xffffffff; - Adapter->stDebugState.subtype[DBG_TYPE_INITEXIT] = 0xffffffff; +static u32 bcm_get_link(struct net_device *dev) +{ + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev); - printk("-------ps_adapter->stDebugState.type=%x\n",Adapter->stDebugState.type); - printk("-------ps_adapter->stDebugState.subtype[DBG_TYPE_OTHERS]=%x\n",Adapter->stDebugState.subtype[DBG_TYPE_OTHERS]); - printk("-------ps_adapter->stDebugState.subtype[DBG_TYPE_RX]=%x\n",Adapter->stDebugState.subtype[DBG_TYPE_RX]); - printk("-------ps_adapter->stDebugState.subtype[DBG_TYPE_TX]=%x\n",Adapter->stDebugState.subtype[DBG_TYPE_TX]); -#endif + return Adapter->LinkUpStatus; +} - return 0; +static u32 bcm_get_msglevel (struct net_device *dev) +{ + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev); + + return Adapter->msg_enable; } -void bcm_unregister_networkdev(PMINI_ADAPTER Adapter) +static void bcm_set_msglevel (struct net_device *dev, u32 level) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Unregistering the Net Dev...\n"); - if(Adapter->dev && !IS_ERR(Adapter->dev) && Adapter->bNetworkInterfaceRegistered) - unregister_netdev(Adapter->dev); - /* Unregister the notifier block */ - if(Adapter->bNetdeviceNotifierRegistered == TRUE) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Unregistering netdevice notifier\n"); - unregister_netdevice_notifier(&bcm_notifier_block); - } + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev); + + Adapter->msg_enable = level; } -static int bcm_init(void) +static const struct ethtool_ops bcm_ethtool_ops = { + .get_settings = bcm_get_settings, + .get_drvinfo = bcm_get_drvinfo, + .get_link = bcm_get_link, + .get_msglevel = bcm_get_msglevel, + .set_msglevel = bcm_set_msglevel, +}; + +int register_networkdev(PMINI_ADAPTER Adapter) { + struct net_device *net = Adapter->dev; + PS_INTERFACE_ADAPTER IntfAdapter = Adapter->pvInterfaceAdapter; + struct usb_interface *udev = IntfAdapter->interface; + struct usb_device *xdev = IntfAdapter->udev; + int result; - result = InterfaceInitialize(); - if(result) - { - printk("Initialisation failed for usbbcm"); - } - else - { - printk("Initialised usbbcm"); + + net->netdev_ops = &bcmNetDevOps; + net->ethtool_ops = &bcm_ethtool_ops; + net->mtu = MTU_SIZE; /* 1400 Bytes */ + net->tx_queue_len = TX_QLEN; + net->flags |= IFF_NOARP; + + netif_carrier_off(net); + + SET_NETDEV_DEVTYPE(net, &wimax_type); + + /* Read the MAC Address from EEPROM */ + result = ReadMacAddressFromNVM(Adapter); + if (result != STATUS_SUCCESS) { + dev_err(&udev->dev, + PFX "Error in Reading the mac Address: %d", result); + return -EIO; } - return result; -} + result = register_netdev(net); + if (result) + return result; -static void bcm_exit(void) -{ - printk("%s %s Calling InterfaceExit\n",__FILE__, __FUNCTION__); - InterfaceExit(); - printk("%s %s InterfaceExit returned\n",__FILE__, __FUNCTION__); -} + gblpnetdev = Adapter->dev; -module_init(bcm_init); -module_exit(bcm_exit); -MODULE_LICENSE ("GPL"); + if (netif_msg_probe(Adapter)) + dev_info(&udev->dev, PFX "%s: register usb-%s-%s %pM\n", + net->name, xdev->bus->bus_name, xdev->devpath, + net->dev_addr); + return 0; +} +void unregister_networkdev(PMINI_ADAPTER Adapter) +{ + struct net_device *net = Adapter->dev; + PS_INTERFACE_ADAPTER IntfAdapter = Adapter->pvInterfaceAdapter; + struct usb_interface *udev = IntfAdapter->interface; + struct usb_device *xdev = IntfAdapter->udev; + + if (netif_msg_probe(Adapter)) + dev_info(&udev->dev, PFX "%s: unregister usb-%s%s\n", + net->name, xdev->bus->bus_name, xdev->devpath); + + unregister_netdev(Adapter->dev); +} diff --git a/trunk/drivers/staging/bcm/CmHost.c b/trunk/drivers/staging/bcm/CmHost.c index 6f388a374ddc..38b64e69d81a 100644 --- a/trunk/drivers/staging/bcm/CmHost.c +++ b/trunk/drivers/staging/bcm/CmHost.c @@ -15,6 +15,7 @@ typedef enum _E_CLASSIFIER_ACTION eDeleteClassifier }E_CLASSIFIER_ACTION; +static ULONG GetNextTargetBufferLocation(PMINI_ADAPTER Adapter,B_UINT16 tid); /************************************************************ * Function - SearchSfid @@ -28,7 +29,7 @@ typedef enum _E_CLASSIFIER_ACTION * Returns - Queue index for this SFID(If matched) Else Invalid Queue Index(If Not matched) ************************************************************/ -__inline INT SearchSfid(PMINI_ADAPTER Adapter,UINT uiSfid) +INT SearchSfid(PMINI_ADAPTER Adapter,UINT uiSfid) { INT iIndex=0; for(iIndex=(NO_OF_QUEUES-1); iIndex>=0; iIndex--) @@ -47,26 +48,16 @@ __inline INT SearchSfid(PMINI_ADAPTER Adapter,UINT uiSfid) * Returns - Queue index for the free SFID * Else returns Invalid Index. ****************************************************************/ -__inline INT SearchFreeSfid(PMINI_ADAPTER Adapter) +static INT SearchFreeSfid(PMINI_ADAPTER Adapter) { UINT uiIndex=0; + for(uiIndex=0; uiIndex < (NO_OF_QUEUES-1); uiIndex++) if(Adapter->PackInfo[uiIndex].ulSFID==0) return uiIndex; return NO_OF_QUEUES+1; } -__inline int SearchVcid(PMINI_ADAPTER Adapter,unsigned short usVcid) -{ - int iIndex=0; - for(iIndex=(NO_OF_QUEUES-1);iIndex>=0;iIndex--) - if(Adapter->PackInfo[iIndex].usVCID_Value == usVcid) - return iIndex; - return NO_OF_QUEUES+1; - -} - - /* Function: SearchClsid Description: This routinue would search Classifier having specified ClassifierID as input parameter @@ -76,7 +67,7 @@ Input parameters: PMINI_ADAPTER Adapter - Adapter Context Return: int :Classifier table index of matching entry */ -__inline int SearchClsid(PMINI_ADAPTER Adapter,ULONG ulSFID,B_UINT16 uiClassifierID) +static int SearchClsid(PMINI_ADAPTER Adapter,ULONG ulSFID,B_UINT16 uiClassifierID) { unsigned int uiClassifierIndex = 0; for(uiClassifierIndex=0;uiClassifierIndexPackInfo[uiSearchRuleIndex].pstSFIndication) { - bcm_kfree(Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication); + kfree(Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication); Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication = NULL; } Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication = pstAddIndication; @@ -1061,12 +1052,6 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) pstAddIndication->sfAuthorizedSet.u32MaxTrafficBurst); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MinReservedTrafficRate : 0x%X", pstAddIndication->sfAuthorizedSet.u32MinReservedTrafficRate); -#if 0 - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MinimumTolerableTrafficRate : 0x%X", - pstAddIndication->sfAuthorizedSet.u32MinimumTolerableTrafficRate); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32RequesttransmissionPolicy : 0x%X", - pstAddIndication->sfAuthorizedSet.u32RequesttransmissionPolicy); -#endif BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParamLength : 0x%X", pstAddIndication->sfAuthorizedSet.u8VendorSpecificQoSParamLength); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParam : 0x%X", @@ -1114,13 +1099,6 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) pstAddIndication->sfAuthorizedSet.u8PagingPreference); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16UnsolicitedPollingInterval : 0x%X", pstAddIndication->sfAuthorizedSet.u16UnsolicitedPollingInterval); -#if 0 - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "MBSZoneIdentifierassignmentLength : 0x%X", - pstAddIndication->sfAuthorizedSet.MBSZoneIdentifierassignmentLength); - for(uiLoopIndex=0; uiLoopIndex < MAX_STRING_LEN; uiLoopIndex++) - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "MBSZoneIdentifierassignment : 0x%X", - pstAddIndication->sfAuthorizedSet.MBSZoneIdentifierassignment[uiLoopIndex]); -#endif BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "sfAuthorizedSet.u8HARQChannelMapping %x %x %x ", *(unsigned int*)pstAddIndication->sfAuthorizedSet.u8HARQChannelMapping, @@ -1158,11 +1136,6 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0], psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1], psfCSType->cCPacketClassificationRule.u8IPTypeOfService[2]); -#if 0 - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "u8ProtocolLength :0x%X ", - psfCSType->cCPacketClassificationRule.u8ProtocolLength); -#endif for(uiLoopIndex=0; uiLoopIndex < 1; uiLoopIndex++) BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Protocol : 0x%02X ", @@ -1278,14 +1251,6 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) pstAddIndication->sfAdmittedSet.u8QosParamSet); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficPriority : 0x%02X", pstAddIndication->sfAdmittedSet.u8TrafficPriority); -#if 0 - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "u32MaxSustainedTrafficRate : 0x%02X", - ntohl(pstAddIndication->sfAdmittedSet.u32MaxSustainedTrafficRate)); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "u32MinimumTolerableTrafficRate : 0x%X", - pstAddIndication->sfAdmittedSet.u32MinimumTolerableTrafficRate); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "u32RequesttransmissionPolicy : 0x%X", - pstAddIndication->sfAdmittedSet.u32RequesttransmissionPolicy); -#endif BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaxTrafficBurst : 0x%X", pstAddIndication->sfAdmittedSet.u32MaxTrafficBurst); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MinReservedTrafficRate : 0x%X", @@ -1339,13 +1304,6 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) pstAddIndication->sfAdmittedSet.u16TimeBase); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8PagingPreference : 0x%X", pstAddIndication->sfAdmittedSet.u8PagingPreference); -#if 0 - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "MBSZoneIdentifierassignmentLength : 0x%X", - pstAddIndication->sfAdmittedSet.MBSZoneIdentifierassignmentLength); - for(uiLoopIndex=0; uiLoopIndex < MAX_STRING_LEN; uiLoopIndex++) - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "MBSZoneIdentifierassignment : 0x%X", - pstAddIndication->sfAdmittedSet.MBSZoneIdentifierassignment[uiLoopIndex]); -#endif BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficIndicationPreference : 0x%02X", @@ -1378,11 +1336,6 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0], psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1], psfCSType->cCPacketClassificationRule.u8IPTypeOfService[2]); -#if 0 - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolLength :0x%02X ", - psfCSType->cCPacketClassificationRule.u8ProtocolLength); -#endif for(uiLoopIndex=0; uiLoopIndex < 1; uiLoopIndex++) BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Protocol: 0x%02X ", psfCSType->cCPacketClassificationRule.u8Protocol); @@ -1497,20 +1450,10 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) pstAddIndication->sfActiveSet.u8QosParamSet); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficPriority : 0x%02X", pstAddIndication->sfActiveSet.u8TrafficPriority); -#if 0 - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "u32MaxSustainedTrafficRate : 0x%02X", - ntohl(pstAddIndication->sfActiveSet.u32MaxSustainedTrafficRate)); -#endif BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaxTrafficBurst : 0x%X", pstAddIndication->sfActiveSet.u32MaxTrafficBurst); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MinReservedTrafficRate : 0x%X", pstAddIndication->sfActiveSet.u32MinReservedTrafficRate); -#if 0 - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "u32MinimumTolerableTrafficRate : 0x%X", - pstAddIndication->sfActiveSet.u32MinimumTolerableTrafficRate); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "u32RequesttransmissionPolicy : 0x%X", - pstAddIndication->sfActiveSet.u32RequesttransmissionPolicy); -#endif BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParamLength : 0x%02X", pstAddIndication->sfActiveSet.u8VendorSpecificQoSParamLength); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParam : 0x%02X", @@ -1558,13 +1501,6 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) pstAddIndication->sfActiveSet.u16TimeBase); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8PagingPreference : 0x%X", pstAddIndication->sfActiveSet.u8PagingPreference); -#if 0 - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " MBSZoneIdentifierassignmentLength : 0x%X", - pstAddIndication->sfActiveSet.MBSZoneIdentifierassignmentLength); - for(uiLoopIndex=0; uiLoopIndex < MAX_STRING_LEN; uiLoopIndex++) - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " MBSZoneIdentifierassignment : 0x%X", - pstAddIndication->sfActiveSet.MBSZoneIdentifierassignment[uiLoopIndex]); -#endif BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8TrafficIndicationPreference : 0x%X", @@ -1597,11 +1533,6 @@ static VOID DumpCmControlPacket(PVOID pvBuffer) psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0], psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1], psfCSType->cCPacketClassificationRule.u8IPTypeOfService[2]); -#if 0 - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " u8ProtocolLength :0x%X ", - psfCSType->cCPacketClassificationRule.u8ProtocolLength); -#endif for(uiLoopIndex=0; uiLoopIndex < 1; uiLoopIndex++) BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8Protocol : 0x%X ", psfCSType->cCPacketClassificationRule.u8Protocol); @@ -1706,12 +1637,8 @@ static inline ULONG RestoreSFParam(PMINI_ADAPTER Adapter, ULONG ulAddrSFParamSet return 0; } ulAddrSFParamSet = ntohl(ulAddrSFParamSet); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " RestoreSFParam: Total Words of DSX Message To Read: 0x%zx From Target At : 0x%lx ", - nBytesToRead/sizeof(ULONG),ulAddrSFParamSet); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "sizeof(stServiceFlowParamSI) = %zx", sizeof(stServiceFlowParamSI)); //Read out the SF Param Set At the indicated Location - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "nBytesToRead = %x", nBytesToRead); if(rdm(Adapter, ulAddrSFParamSet, (PUCHAR)pucDestBuffer, nBytesToRead) < 0) return STATUS_FAILURE; @@ -1719,7 +1646,7 @@ static inline ULONG RestoreSFParam(PMINI_ADAPTER Adapter, ULONG ulAddrSFParamSet } -static __inline ULONG StoreSFParam(PMINI_ADAPTER Adapter,PUCHAR pucSrcBuffer,ULONG ulAddrSFParamSet) +static ULONG StoreSFParam(PMINI_ADAPTER Adapter,PUCHAR pucSrcBuffer,ULONG ulAddrSFParamSet) { UINT nBytesToWrite = sizeof(stServiceFlowParamSI); UINT uiRetVal =0; @@ -1728,9 +1655,6 @@ static __inline ULONG StoreSFParam(PMINI_ADAPTER Adapter,PUCHAR pucSrcBuffer,ULO { return 0; } - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " StoreSFParam: Total Words of DSX Message To Write: 0x%zX To Target At : 0x%lX ",(nBytesToWrite/sizeof(ULONG)),ulAddrSFParamSet); - - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "WRM with %x bytes",nBytesToWrite); uiRetVal = wrm(Adapter,ulAddrSFParamSet,(PUCHAR)pucSrcBuffer, nBytesToWrite); if(uiRetVal < 0) { @@ -1844,7 +1768,7 @@ ULONG StoreCmControlResponseMessage(PMINI_ADAPTER Adapter,PVOID pvBuffer,UINT *p (*puBufferLength) = sizeof(stLocalSFAddIndication); *(stLocalSFAddIndication *)pvBuffer = *pstAddIndication; - bcm_kfree(pstAddIndication); + kfree(pstAddIndication); return 1; } @@ -1931,7 +1855,7 @@ static inline stLocalSFAddIndicationAlt BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "============================================================"); return pstAddIndicationDest; failed_restore_sf_param: - bcm_kfree(pstAddIndicationDest); + kfree(pstAddIndicationDest); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "<=====" ); return NULL; } @@ -1988,7 +1912,7 @@ ULONG SetUpTargetDsxBuffers(PMINI_ADAPTER Adapter) return 1; } -ULONG GetNextTargetBufferLocation(PMINI_ADAPTER Adapter,B_UINT16 tid) +static ULONG GetNextTargetBufferLocation(PMINI_ADAPTER Adapter,B_UINT16 tid) { ULONG ulTargetDSXBufferAddress; ULONG ulTargetDsxBufferIndexToUse,ulMaxTry; @@ -2049,7 +1973,7 @@ INT FreeAdapterDsxBuffer(PMINI_ADAPTER Adapter) { if(Adapter->caDsxReqResp) { - bcm_kfree(Adapter->caDsxReqResp); + kfree(Adapter->caDsxReqResp); } return 0; @@ -2102,7 +2026,7 @@ BOOLEAN CmControlResponseMessage(PMINI_ADAPTER Adapter, /**u16VCID)); CopyBufferToControlPacket(Adapter,(PVOID)Adapter->caDsxReqResp); - bcm_kfree(pstAddIndication); + kfree(pstAddIndication); } break; case DSA_RSP: @@ -2118,7 +2042,7 @@ BOOLEAN CmControlResponseMessage(PMINI_ADAPTER Adapter, /**u16VCID)); uiSearchRuleIndex=SearchFreeSfid(Adapter); @@ -2169,7 +2093,7 @@ BOOLEAN CmControlResponseMessage(PMINI_ADAPTER Adapter, /**PackInfo[uiSearchRuleIndex].bActive=FALSE; Adapter->PackInfo[uiSearchRuleIndex].bValid=FALSE; Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value=0; - bcm_kfree(pstAddIndication); + kfree(pstAddIndication); } else if(psfLocalSet->bValid && (pstAddIndication->u8CC == 0)) @@ -2200,14 +2124,13 @@ BOOLEAN CmControlResponseMessage(PMINI_ADAPTER Adapter, /**LinkUpStatus) { netif_carrier_on(Adapter->dev); - netif_start_queue(Adapter->dev); + netif_start_queue(Adapter->dev); Adapter->LinkUpStatus = 1; - do_gettimeofday(&tv); - + if (netif_msg_link(Adapter)) + pr_info(PFX "%s: link up\n", Adapter->dev->name); atomic_set(&Adapter->TxPktAvail, 1); wake_up(&Adapter->tx_packet_wait_queue); - Adapter->liTimeSinceLastNetEntry = tv.tv_sec; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "============Tx Service Flow Created!"); + Adapter->liTimeSinceLastNetEntry = get_seconds(); } } } @@ -2218,13 +2141,13 @@ BOOLEAN CmControlResponseMessage(PMINI_ADAPTER Adapter, /**PackInfo[uiSearchRuleIndex].bActive=FALSE; Adapter->PackInfo[uiSearchRuleIndex].bValid=FALSE; Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value=0; - bcm_kfree(pstAddIndication); + kfree(pstAddIndication); } } else { BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0, "DSA ACK did not get valid SFID"); - bcm_kfree(pstAddIndication); + kfree(pstAddIndication); return FALSE; } } @@ -2239,7 +2162,7 @@ BOOLEAN CmControlResponseMessage(PMINI_ADAPTER Adapter, /**caDsxReqResp[LEADER_SIZE]))->u8Type = DSC_RSP; CopyBufferToControlPacket(Adapter,(PVOID)Adapter->caDsxReqResp); - bcm_kfree(pstAddIndication); + kfree(pstAddIndication); } break; case DSC_RSP: @@ -2312,13 +2235,13 @@ BOOLEAN CmControlResponseMessage(PMINI_ADAPTER Adapter, /**u8CC == 6) { deleteSFBySfid(Adapter,uiSearchRuleIndex); - bcm_kfree(pstAddIndication); + kfree(pstAddIndication); } } else { BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0, "DSC ACK did not get valid SFID"); - bcm_kfree(pstAddIndication); + kfree(pstAddIndication); return FALSE; } } @@ -2355,7 +2278,7 @@ BOOLEAN CmControlResponseMessage(PMINI_ADAPTER Adapter, /**=current_debug_level) - { - int i=0; - printk("\n%s:%s:%d:Buffer dump of size 0x%x in the %s:\n", file_name, function_name, line_number, bufferlen, buff_dump_base[1]); - for(;i #define NONE 0xFFFF -typedef enum _BASE_TYPE -{ - BCM_BASE_TYPE_DEC, - BCM_BASE_TYPE_OCT, - BCM_BASE_TYPE_BIN, - BCM_BASE_TYPE_HEX, - BCM_BASE_TYPE_NONE, -} BASE_TYPE, *PBASE_TYPE; - -int bcm_print_buffer( UINT debug_level, const char *function_name, - char *file_name, int line_number, unsigned char *buffer, int bufferlen, BASE_TYPE base); - -#ifdef BCM_SHM_INTERFACE -#define CPE_VIRTUAL_ERROR_CODE_BASE_ADDR (0xBFC02E00 + 0x4C) -// ERROR codes for debugging -extern unsigned char u32ErrorCounter ; -#define ERROR_DEVICE_REMOVED 0x1 -#define ERROR_LEADER_LENGTH_ZERO 0x2 -#define ERROR_LEADER_LENGTH_CORRUPTED 0x3 -#define ERROR_NO_SKBUFF 0x4 - -#define ERROR_DL_MODULE 0xaa000000 -extern void CPE_ERROR_LOG(unsigned int module,unsigned int code); - -#endif - - - //-------------------------------------------------------------------------------- @@ -242,44 +214,34 @@ typedef struct _S_BCM_DEBUG_STATE { //--- Only for direct printk's; "hidden" to API. #define DBG_TYPE_PRINTK 3 -#define PRINTKS_ON 1 // "hidden" from API, set to 0 to turn off all printk's - -#define BCM_DEBUG_PRINT(Adapter, Type, SubType, dbg_level, string, args...) do { \ - if ((DBG_TYPE_PRINTK == Type) && (PRINTKS_ON)) { \ - printk ("%s:" string, __FUNCTION__, ##args); \ - printk("\n"); \ - } else if (!Adapter) \ - ; \ - else { \ - if (((dbg_level & DBG_LVL_BITMASK) <= Adapter->stDebugState.debug_level) && \ - ((Type & Adapter->stDebugState.type) && (SubType & Adapter->stDebugState.subtype[Type]))) { \ - if (dbg_level & DBG_NO_FUNC_PRINT) \ - printk (string, ##args); \ - else \ - { \ - printk ("%s:" string, __FUNCTION__, ##args); \ - printk("\n"); \ - } \ - } \ - } \ -} while (0) -#define BCM_DEBUG_PRINT_BUFFER(Adapter, Type, SubType, dbg_level, buffer, bufferlen) do { \ - if ((DBG_TYPE_PRINTK == Type) && (PRINTKS_ON)) { \ - bcm_print_buffer( dbg_level, __FUNCTION__, __FILE__, __LINE__, buffer, bufferlen, BCM_BASE_TYPE_HEX); \ - } else if (!Adapter) \ - ; \ - else { \ - if (((dbg_level & DBG_LVL_BITMASK) <= Adapter->stDebugState.debug_level) && \ - ((Type & Adapter->stDebugState.type) && (SubType & Adapter->stDebugState.subtype[Type]))) { \ - if (dbg_level & DBG_NO_FUNC_PRINT) \ - bcm_print_buffer( dbg_level, NULL, NULL, __LINE__, buffer, bufferlen, BCM_BASE_TYPE_HEX); \ - else \ - bcm_print_buffer( dbg_level, __FUNCTION__, __FILE__, __LINE__, buffer, bufferlen, BCM_BASE_TYPE_HEX); \ - } \ - } \ +#define BCM_DEBUG_PRINT(Adapter, Type, SubType, dbg_level, string, args...) \ + do { \ + if (DBG_TYPE_PRINTK == Type) \ + pr_info("%s:" string, __func__, ##args); \ + else if (Adapter && \ + (dbg_level & DBG_LVL_BITMASK) <= Adapter->stDebugState.debug_level && \ + (Type & Adapter->stDebugState.type) && \ + (SubType & Adapter->stDebugState.subtype[Type])) { \ + if (dbg_level & DBG_NO_FUNC_PRINT) \ + printk(KERN_DEBUG string, ##args); \ + else \ + printk(KERN_DEBUG "%s:" string, __func__, ##args); \ + } \ } while (0) +#define BCM_DEBUG_PRINT_BUFFER(Adapter, Type, SubType, dbg_level, buffer, bufferlen) do { \ + if (DBG_TYPE_PRINTK == Type || \ + (Adapter && \ + (dbg_level & DBG_LVL_BITMASK) <= Adapter->stDebugState.debug_level && \ + (Type & Adapter->stDebugState.type) && \ + (SubType & Adapter->stDebugState.subtype[Type]))) { \ + printk(KERN_DEBUG "%s:\n", __func__); \ + print_hex_dump(KERN_DEBUG, " ", DUMP_PREFIX_OFFSET, \ + 16, 1, buffer, bufferlen, false); \ + } \ +} while(0) + #define BCM_SHOW_DEBUG_BITMAP(Adapter) do { \ int i; \ diff --git a/trunk/drivers/staging/bcm/HandleControlPacket.c b/trunk/drivers/staging/bcm/HandleControlPacket.c index 7b2ec28a4bc1..2b1e9e17e11c 100644 --- a/trunk/drivers/staging/bcm/HandleControlPacket.c +++ b/trunk/drivers/staging/bcm/HandleControlPacket.c @@ -11,8 +11,7 @@ When a control packet is received, analyze the Enqueue the control packet for Application. @return None */ -VOID handle_rx_control_packet(PMINI_ADAPTER Adapter, /**data); - BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "=====>"); - /* Get the Leader field */ + + if (netif_msg_pktdata(Adapter)) + print_hex_dump(KERN_DEBUG, PFX "rx control: ", DUMP_PREFIX_NONE, + 16, 1, skb->data, skb->len, 0); switch(usStatus) { @@ -134,7 +135,7 @@ VOID handle_rx_control_packet(PMINI_ADAPTER Adapter, /**RxAppControlQueuelock); wake_up(&Adapter->process_read_wait_queue); - bcm_kfree_skb(skb); + dev_kfree_skb(skb); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "After wake_up_interruptible"); } @@ -185,33 +186,7 @@ int control_packet_handler (PMINI_ADAPTER Adapter /**< pointer to adapter obje { DEQUEUEPACKET(Adapter->RxControlHead,Adapter->RxControlTail); // Adapter->RxControlHead=ctrl_packet->next; - ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.rx_packets++; - ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.rx_bytes+= - ((PLEADER)ctrl_packet->data)->PLength; - } - #if 0 //Idle mode debug profiling... - if(*(PUSHORT)ctrl_packet->data == IDLE_MODE_STATUS) - { - puiBuffer = (PUINT)(ctrl_packet->data +sizeof(USHORT)); - if((ntohl(*puiBuffer) == GO_TO_IDLE_MODE_PAYLOAD)) - { - memset(&tv, 0, sizeof(tv)); - do_gettimeofday(&tv); - if((ntohl(*(puiBuffer+1)) == 0)) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "IdleMode Wake-up Msg from f/w at time :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000); - } - else - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "IdleMode req Msg from f/w at time :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000); - } - } - else if((ntohl(*puiBuffer) == IDLE_MODE_SF_UPDATE_MSG)) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "GOT IDLE_MODE_SF_UPDATE MSG at time :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000); - } } - #endif spin_unlock_irqrestore (&Adapter->control_queue_lock, flags); handle_rx_control_packet(Adapter, ctrl_packet); @@ -234,7 +209,7 @@ INT flushAllAppQ(void) { PacketToDrop=pTarang->RxAppControlHead; DEQUEUEPACKET(pTarang->RxAppControlHead,pTarang->RxAppControlTail); - bcm_kfree_skb(PacketToDrop); + dev_kfree_skb(PacketToDrop); } pTarang->AppCtrlQueueLen = 0; //dropped contrl packet statistics also should be reset. diff --git a/trunk/drivers/staging/bcm/HostMibs.h b/trunk/drivers/staging/bcm/HostMibs.h deleted file mode 100644 index 28a578311378..000000000000 --- a/trunk/drivers/staging/bcm/HostMibs.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _HOST_MIBS_H -#define _HOST_MIBS_H - -INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, - PVOID ioBuffer, - ULONG inputBufferLength); -#endif diff --git a/trunk/drivers/staging/bcm/IPv6Protocol.c b/trunk/drivers/staging/bcm/IPv6Protocol.c index 5ec3b896c6a7..91b6fbe33c91 100644 --- a/trunk/drivers/staging/bcm/IPv6Protocol.c +++ b/trunk/drivers/staging/bcm/IPv6Protocol.c @@ -1,5 +1,9 @@ #include "headers.h" +static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header); +static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header); +static VOID DumpIpv6Header(IPV6Header *pstIpv6Header); + static UCHAR * GetNextIPV6ChainedHeader(UCHAR **ppucPayload,UCHAR *pucNextHeader,BOOLEAN *bParseDone,USHORT *pusPayloadLength) { UCHAR *pucRetHeaderPtr = NULL; @@ -257,7 +261,7 @@ USHORT IpVersion6(PMINI_ADAPTER Adapter, /**< Pointer to the driver control stru } -BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header) +static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header) { UINT uiLoopIndex=0; UINT uiIpv6AddIndex=0; @@ -310,7 +314,7 @@ BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pst return FALSE; } -BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header) +static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header) { UINT uiLoopIndex=0; UINT uiIpv6AddIndex=0; @@ -376,7 +380,7 @@ VOID DumpIpv6Address(ULONG *puIpv6Address) } -VOID DumpIpv6Header(IPV6Header *pstIpv6Header) +static VOID DumpIpv6Header(IPV6Header *pstIpv6Header) { UCHAR ucVersion; UCHAR ucPrio ; diff --git a/trunk/drivers/staging/bcm/IPv6ProtocolHdr.h b/trunk/drivers/staging/bcm/IPv6ProtocolHdr.h index b93f7902e283..a0db5a1de763 100644 --- a/trunk/drivers/staging/bcm/IPv6ProtocolHdr.h +++ b/trunk/drivers/staging/bcm/IPv6ProtocolHdr.h @@ -101,15 +101,12 @@ typedef enum _E_IPADDR_CONTEXT //Function Prototypes -BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header); -BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header); USHORT IpVersion6(PMINI_ADAPTER Adapter, /**< Pointer to the driver control structure */ PVOID pcIpHeader, /**pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength); if(retval) { - bcm_kfree (Adapter->pstargetparams); + kfree(Adapter->pstargetparams); Adapter->pstargetparams = NULL; return -EFAULT; } @@ -231,41 +230,6 @@ static int bcm_download_config_file(PMINI_ADAPTER Adapter, return retval; } -#if 0 -static int bcm_download_buffer(PMINI_ADAPTER Adapter, - unsigned char *mappedbuffer, unsigned int u32FirmwareLength, - unsigned long u32StartingAddress) -{ - char *buff=NULL; - unsigned int len = 0; - int retval = STATUS_SUCCESS; - buff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL); - - len = u32FirmwareLength; - - while(u32FirmwareLength) - { - len = MIN_VAL (u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB); - if(STATUS_SUCCESS != (retval = copy_from_user(buff, - (unsigned char *)mappedbuffer, len))) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "copy_from_user failed\n"); - break; - } - retval = wrm (Adapter, u32StartingAddress, buff, len); - if(retval) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "wrm failed\n"); - break; - } - u32StartingAddress += len; - u32FirmwareLength -= len; - mappedbuffer +=len; - } - bcm_kfree(buff); - return retval; -} -#endif static int bcm_compare_buff_contents(unsigned char *readbackbuff, unsigned char *buff,unsigned int len) { @@ -297,58 +261,6 @@ static int bcm_compare_buff_contents(unsigned char *readbackbuff, } return retval; } -#if 0 -static int bcm_buffer_readback(PMINI_ADAPTER Adapter, - unsigned char *mappedbuffer, unsigned int u32FirmwareLength, - unsigned long u32StartingAddress) -{ - unsigned char *buff = NULL; - unsigned char *readbackbuff = NULL; - unsigned int len = u32FirmwareLength; - int retval = STATUS_SUCCESS; - - buff=(unsigned char *)kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL); - if(NULL == buff) - return -ENOMEM; - readbackbuff = (unsigned char *)kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, - GFP_KERNEL); - if(NULL == readbackbuff) - { - bcm_kfree(buff); - return -ENOMEM; - } - while (u32FirmwareLength && !retval) - { - len = MIN_VAL (u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB); - - /* read from the appl buff and then read from the target, compare */ - if(STATUS_SUCCESS != (retval = copy_from_user(buff, - (unsigned char *)mappedbuffer, len))) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "copy_from_user failed\n"); - break; - } - retval = rdm (Adapter, u32StartingAddress, readbackbuff, len); - if(retval) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "rdm failed\n"); - break; - } - - if (STATUS_SUCCESS != - (retval = bcm_compare_buff_contents (readbackbuff, buff, len))) - { - break; - } - u32StartingAddress += len; - u32FirmwareLength -= len; - mappedbuffer +=len; - }/* end of while (u32FirmwareLength && !retval) */ - bcm_kfree(buff); - bcm_kfree(readbackbuff); - return retval; -} -#endif int bcm_ioctl_fw_download(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo) { int retval = STATUS_SUCCESS; @@ -389,23 +301,6 @@ int bcm_ioctl_fw_download(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo) goto error ; } - #if 0 - retval = bcm_download_buffer(Adapter, - (unsigned char *)psFwInfo->pvMappedFirmwareAddress, - psFwInfo->u32FirmwareLength, psFwInfo->u32StartingAddress); - if(retval != STATUS_SUCCESS) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "User space buffer download fails...."); - } - retval = bcm_buffer_readback (Adapter, - (unsigned char *)psFwInfo->pvMappedFirmwareAddress, - psFwInfo->u32FirmwareLength, psFwInfo->u32StartingAddress); - - if(retval != STATUS_SUCCESS) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "read back verifier failed ...."); - } - #endif retval = buffDnldVerify(Adapter, buff, psFwInfo->u32FirmwareLength, @@ -417,7 +312,7 @@ int bcm_ioctl_fw_download(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo) } } error: - bcm_kfree(buff); + kfree(buff); return retval; } @@ -480,7 +375,7 @@ static INT buffRdbkVerify(PMINI_ADAPTER Adapter, u32FirmwareLength -= len; mappedbuffer +=len; }/* end of while (u32FirmwareLength && !retval) */ - bcm_kfree(readbackbuff); + kfree(readbackbuff); return retval; } @@ -506,5 +401,4 @@ INT buffDnldVerify(PMINI_ADAPTER Adapter, unsigned char *mappedbuffer, unsigned return status; } -#endif diff --git a/trunk/drivers/staging/bcm/InterfaceIdleMode.c b/trunk/drivers/staging/bcm/InterfaceIdleMode.c index 0750382733ff..bf5c0ad86610 100644 --- a/trunk/drivers/staging/bcm/InterfaceIdleMode.c +++ b/trunk/drivers/staging/bcm/InterfaceIdleMode.c @@ -98,14 +98,6 @@ int InterfaceIdleModeRespond(PMINI_ADAPTER Adapter, unsigned int* puiBuffer) Adapter->bTriedToWakeUpFromlowPowerMode = FALSE; wake_up(&Adapter->lowpower_mode_wait_queue); - #if 0 - if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"LED Thread is Running. Hence Setting the LED Event as IDLEMODE_EXIT"); - Adapter->DriverState = IDLEMODE_EXIT; - wake_up(&Adapter->LEDInfo.notify_led_event); - } - #endif } else @@ -154,17 +146,7 @@ int InterfaceIdleModeRespond(PMINI_ADAPTER Adapter, unsigned int* puiBuffer) return status; } - -VOID InterfaceWriteIdleModeWakePattern(PMINI_ADAPTER Adapter) -{ -/* BeceemWriteMemoryUshort(Adapter, Host2CPU_Mailbox_Low, 0x1d1e); - BeceemWriteMemoryUshort(Adapter, Host2CPU_Mailbox_Low, 0x1d1e); - BeceemWriteMemoryUshort(Adapter, Host2CPU_Mailbox_Upp, 0xd0ea); - BeceemWriteMemoryUshort(Adapter, Host2CPU_Mailbox_Upp, 0xd0ea);*/ - return; -} - -int InterfaceAbortIdlemode(PMINI_ADAPTER Adapter, unsigned int Pattern) +static int InterfaceAbortIdlemode(PMINI_ADAPTER Adapter, unsigned int Pattern) { int status = STATUS_SUCCESS; unsigned int value; diff --git a/trunk/drivers/staging/bcm/InterfaceIdleMode.h b/trunk/drivers/staging/bcm/InterfaceIdleMode.h index 1bc723d2d72c..859a2ffba6b7 100644 --- a/trunk/drivers/staging/bcm/InterfaceIdleMode.h +++ b/trunk/drivers/staging/bcm/InterfaceIdleMode.h @@ -7,8 +7,6 @@ INT InterfaceIdleModeRespond(PMINI_ADAPTER Adapter, unsigned int *puiBuffer); VOID InterfaceWriteIdleModeWakePattern(PMINI_ADAPTER Adapter); -INT InterfaceAbortIdlemode(PMINI_ADAPTER Adapter, unsigned int Pattern); - INT InterfaceWakeUp(PMINI_ADAPTER Adapter); VOID InterfaceHandleShutdownModeWakeup(PMINI_ADAPTER Adapter); diff --git a/trunk/drivers/staging/bcm/InterfaceInit.c b/trunk/drivers/staging/bcm/InterfaceInit.c index 824f9a45007a..8a26a3ef5bd3 100644 --- a/trunk/drivers/staging/bcm/InterfaceInit.c +++ b/trunk/drivers/staging/bcm/InterfaceInit.c @@ -2,14 +2,27 @@ static struct usb_device_id InterfaceUsbtable[] = { { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3) }, - { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3B) }, - { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3L) }, - { USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_226) }, - { USB_DEVICE(BCM_USB_VENDOR_ID_FOXCONN, BCM_USB_PRODUCT_ID_1901) }, - {} + { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3B) }, + { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3L) }, + { USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_226) }, + { USB_DEVICE(BCM_USB_VENDOR_ID_FOXCONN, BCM_USB_PRODUCT_ID_1901) }, + + { } }; +MODULE_DEVICE_TABLE(usb, InterfaceUsbtable); + +static int debug = -1; +module_param(debug, uint, 0600); +MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + +static const u32 default_msg = + NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK + | NETIF_MSG_TIMER | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR + | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN; + +static INT InterfaceAdapterInit(PS_INTERFACE_ADAPTER Adapter); -VOID InterfaceAdapterFree(PS_INTERFACE_ADAPTER psIntfAdapter) +static VOID InterfaceAdapterFree(PS_INTERFACE_ADAPTER psIntfAdapter) { INT i = 0; // Wake up the wait_queue... @@ -48,7 +61,7 @@ VOID InterfaceAdapterFree(PS_INTERFACE_ADAPTER psIntfAdapter) { if (psIntfAdapter->asUsbRcb[i].urb != NULL) { - bcm_kfree(psIntfAdapter->asUsbRcb[i].urb->transfer_buffer); + kfree(psIntfAdapter->asUsbRcb[i].urb->transfer_buffer); usb_free_urb(psIntfAdapter->asUsbRcb[i].urb); psIntfAdapter->asUsbRcb[i].urb = NULL; } @@ -56,30 +69,7 @@ VOID InterfaceAdapterFree(PS_INTERFACE_ADAPTER psIntfAdapter) AdapterFree(psIntfAdapter->psAdapter); } - - -static int usbbcm_open(struct inode *inode, struct file *file) -{ - return 0; -} - -static int usbbcm_release(struct inode *inode, struct file *file) -{ - return 0; -} - -static ssize_t usbbcm_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) -{ - return 0; -} - -static ssize_t usbbcm_write(struct file *file, const char __user *user_buffer, size_t count, loff_t *ppos) -{ - return 0; -} - - -VOID ConfigureEndPointTypesThroughEEPROM(PMINI_ADAPTER Adapter) +static VOID ConfigureEndPointTypesThroughEEPROM(PMINI_ADAPTER Adapter) { ULONG ulReg = 0; @@ -157,48 +147,32 @@ VOID ConfigureEndPointTypesThroughEEPROM(PMINI_ADAPTER Adapter) } -static struct file_operations usbbcm_fops = { - .open = usbbcm_open, - .release = usbbcm_release, - .read = usbbcm_read, - .write = usbbcm_write, - .owner = THIS_MODULE, - .llseek = no_llseek, -}; - -static struct usb_class_driver usbbcm_class = { - .name = "usbbcm", - .fops = &usbbcm_fops, - .minor_base = BCM_USB_MINOR_BASE, -}; - static int usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id) { - int retval =0 ; - PMINI_ADAPTER psAdapter = NULL; - PS_INTERFACE_ADAPTER psIntfAdapter = NULL; - struct usb_device *udev = NULL; + struct usb_device *udev = interface_to_usbdev (intf); + int retval; + PMINI_ADAPTER psAdapter; + PS_INTERFACE_ADAPTER psIntfAdapter; + struct net_device *ndev; -// BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Usbbcm probe!!"); - if((intf == NULL) || (id == NULL)) - { - // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "intf or id is NULL"); - return -EINVAL; - } - - /* Allocate Adapter structure */ - if((psAdapter = kzalloc(sizeof(MINI_ADAPTER), GFP_KERNEL)) == NULL) - { - BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0, "Out of memory"); + /* Reserve one extra queue for the bit-bucket */ + ndev = alloc_etherdev_mq(sizeof(MINI_ADAPTER), NO_OF_QUEUES+1); + if(ndev == NULL) { + dev_err(&udev->dev, DRV_NAME ": no memory for device\n"); return -ENOMEM; } + SET_NETDEV_DEV(ndev, &intf->dev); + + psAdapter = netdev_priv(ndev); + psAdapter->dev = ndev; + psAdapter->msg_enable = netif_msg_init(debug, default_msg); + /* Init default driver debug state */ - psAdapter->stDebugState.debug_level = DBG_LVL_CURR; + psAdapter->stDebugState.debug_level = DBG_LVL_CURR; psAdapter->stDebugState.type = DBG_TYPE_INITEXIT; - memset (psAdapter->stDebugState.subtype, 0, sizeof (psAdapter->stDebugState.subtype)); /* Technically, one can start using BCM_DEBUG_PRINT after this point. * However, realize that by default the Type/Subtype bitmaps are all zero now; @@ -217,22 +191,21 @@ usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id) retval = InitAdapter(psAdapter); if(retval) { - BCM_DEBUG_PRINT (psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "InitAdapter Failed\n"); + dev_err(&udev->dev, DRV_NAME ": InitAdapter Failed\n"); AdapterFree(psAdapter); return retval; } /* Allocate interface adapter structure */ - if((psAdapter->pvInterfaceAdapter = - kmalloc(sizeof(S_INTERFACE_ADAPTER), GFP_KERNEL)) == NULL) + psIntfAdapter = kzalloc(sizeof(S_INTERFACE_ADAPTER), GFP_KERNEL); + if (psIntfAdapter == NULL) { - BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0, "Out of memory"); + dev_err(&udev->dev, DRV_NAME ": no memory for Interface adapter\n"); AdapterFree (psAdapter); return -ENOMEM; } - memset(psAdapter->pvInterfaceAdapter, 0, sizeof(S_INTERFACE_ADAPTER)); - psIntfAdapter = InterfaceAdapterGet(psAdapter); + psAdapter->pvInterfaceAdapter = psIntfAdapter; psIntfAdapter->psAdapter = psAdapter; /* Store usb interface in Interface Adapter */ @@ -255,8 +228,6 @@ usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id) usb_set_intfdata(intf, NULL); udev = interface_to_usbdev (intf); usb_put_dev(udev); - if(psAdapter->bUsbClassDriverRegistered == TRUE) - usb_deregister_dev (intf, &usbbcm_class); InterfaceAdapterFree(psIntfAdapter); return retval ; } @@ -269,7 +240,6 @@ usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id) } } - udev = interface_to_usbdev (intf); /* Check whether the USB-Device Supports remote Wake-Up */ if(USB_CONFIG_ATT_WAKEUP & udev->actconfig->desc.bmAttributes) { @@ -309,38 +279,26 @@ usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id) static void usbbcm_disconnect (struct usb_interface *intf) { - PS_INTERFACE_ADAPTER psIntfAdapter = NULL; - PMINI_ADAPTER psAdapter = NULL; - struct usb_device *udev = NULL; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + PS_INTERFACE_ADAPTER psIntfAdapter = usb_get_intfdata(intf); + PMINI_ADAPTER psAdapter; + struct usb_device *udev = interface_to_usbdev (intf); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Usb disconnected"); - if(intf == NULL) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "intf pointer is NULL"); - return; - } - psIntfAdapter = usb_get_intfdata(intf); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "psIntfAdapter 0x%p",psIntfAdapter); if(psIntfAdapter == NULL) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "InterfaceAdapter pointer is NULL"); return; - } + psAdapter = psIntfAdapter->psAdapter; + netif_device_detach(psAdapter->dev); + if(psAdapter->bDoSuspend) intf->needs_remote_wakeup = 0; psAdapter->device_removed = TRUE ; usb_set_intfdata(intf, NULL); InterfaceAdapterFree(psIntfAdapter); - udev = interface_to_usbdev (intf); usb_put_dev(udev); - usb_deregister_dev (intf, &usbbcm_class); } - -static __inline int AllocUsbCb(PS_INTERFACE_ADAPTER psIntfAdapter) +static int AllocUsbCb(PS_INTERFACE_ADAPTER psIntfAdapter) { int i = 0; for(i = 0; i < MAXIMUM_USB_TCB; i++) @@ -382,13 +340,11 @@ static int device_run(PS_INTERFACE_ADAPTER psIntfAdapter) status = InitCardAndDownloadFirmware(psIntfAdapter->psAdapter); if(status != STATUS_SUCCESS) { - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "InitCardAndDownloadFirmware failed.\n"); + pr_err(DRV_NAME "InitCardAndDownloadFirmware failed.\n"); return status; } if(TRUE == psIntfAdapter->psAdapter->fw_download_done) { - - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Sending first interrupt URB down......"); if(StartInterruptUrb(psIntfAdapter)) { BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Cannot send interrupt in URB"); @@ -401,48 +357,17 @@ static int device_run(PS_INTERFACE_ADAPTER psIntfAdapter) psIntfAdapter->psAdapter->waiting_to_fw_download_done, 5*HZ); if(value == 0) - { - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Mailbox Interrupt has not reached to Driver.."); - } - else - { - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Got the mailbox interrupt ...Registering control interface...\n "); - } + pr_err(DRV_NAME ": Mailbox Interrupt has not reached to Driver..\n"); + if(register_control_device_interface(psIntfAdapter->psAdapter) < 0) { - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Register Control Device failed..."); + pr_err(DRV_NAME ": Register Control Device failed...\n"); return -EIO; } } return 0; } -#if 0 -static void print_usb_interface_desc(struct usb_interface_descriptor *usb_intf_desc) -{ - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "**************** INTERFACE DESCRIPTOR *********************"); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bLength: %x", usb_intf_desc->bLength); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bDescriptorType: %x", usb_intf_desc->bDescriptorType); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterfaceNumber: %x", usb_intf_desc->bInterfaceNumber); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bAlternateSetting: %x", usb_intf_desc->bAlternateSetting); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bNumEndpoints: %x", usb_intf_desc->bNumEndpoints); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterfaceClass: %x", usb_intf_desc->bInterfaceClass); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterfaceSubClass: %x", usb_intf_desc->bInterfaceSubClass); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterfaceProtocol: %x", usb_intf_desc->bInterfaceProtocol); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "iInterface :%x\n",usb_intf_desc->iInterface); -} -static void print_usb_endpoint_descriptor(struct usb_endpoint_descriptor *usb_ep_desc) -{ - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "**************** ENDPOINT DESCRIPTOR *********************"); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bLength :%x ", usb_ep_desc->bLength); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bDescriptorType :%x ", usb_ep_desc->bDescriptorType); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bEndpointAddress :%x ", usb_ep_desc->bEndpointAddress); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bmAttributes :%x ", usb_ep_desc->bmAttributes); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "wMaxPacketSize :%x ",usb_ep_desc->wMaxPacketSize); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterval :%x ",usb_ep_desc->bInterval); -} - -#endif static inline int bcm_usb_endpoint_num(const struct usb_endpoint_descriptor *epd) { @@ -518,7 +443,7 @@ static inline int bcm_usb_endpoint_is_isoc_out(const struct usb_endpoint_descrip return (bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_out(epd)); } -INT InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter) +static INT InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter) { struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; @@ -530,20 +455,9 @@ INT InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter) UINT uiData = 0; /* Store the usb dev into interface adapter */ - psIntfAdapter->udev = usb_get_dev(interface_to_usbdev( - psIntfAdapter->interface)); - - if((psIntfAdapter->udev->speed == USB_SPEED_HIGH)) - { - psIntfAdapter->bHighSpeedDevice = TRUE ; - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "MODEM IS CONFIGURED TO HIGH_SPEED "); - } - else - { - psIntfAdapter->bHighSpeedDevice = FALSE ; - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "MODEM IS CONFIGURED TO FULL_SPEED "); - } + psIntfAdapter->udev = usb_get_dev(interface_to_usbdev(psIntfAdapter->interface)); + psIntfAdapter->bHighSpeedDevice = (psIntfAdapter->udev->speed == USB_SPEED_HIGH); psIntfAdapter->psAdapter->interface_rdm = BcmRDM; psIntfAdapter->psAdapter->interface_wrm = BcmWRM; @@ -552,28 +466,27 @@ INT InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter) BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "CHIP ID Read Failed\n"); return STATUS_FAILURE; } - if(0xbece3200==(psIntfAdapter->psAdapter->chip_id&~(0xF0))) - { - psIntfAdapter->psAdapter->chip_id=(psIntfAdapter->psAdapter->chip_id&~(0xF0)); - } - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "First RDM Chip ID 0x%lx\n", psIntfAdapter->psAdapter->chip_id); + if(0xbece3200==(psIntfAdapter->psAdapter->chip_id&~(0xF0))) + psIntfAdapter->psAdapter->chip_id &= ~0xF0; - iface_desc = psIntfAdapter->interface->cur_altsetting; - //print_usb_interface_desc(&(iface_desc->desc)); + dev_info(&psIntfAdapter->udev->dev, "RDM Chip ID 0x%lx\n", + psIntfAdapter->psAdapter->chip_id); + + iface_desc = psIntfAdapter->interface->cur_altsetting; if(psIntfAdapter->psAdapter->chip_id == T3B) { - // //T3B device will have EEPROM,check if EEPROM is proper and BCM16 can be done or not. // BeceemEEPROMBulkRead(psIntfAdapter->psAdapter,&uiData,0x0,4); if(uiData == BECM) - { bBcm16 = TRUE; - } - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Number of Altsetting aviailable for This Modem 0x%x\n", psIntfAdapter->interface->num_altsetting); + + dev_info(&psIntfAdapter->udev->dev, "number of alternate setting %d\n", + psIntfAdapter->interface->num_altsetting); + if(bBcm16 == TRUE) { //selecting alternate setting one as a default setting for High Speed modem. @@ -644,12 +557,10 @@ INT InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter) } iface_desc = psIntfAdapter->interface->cur_altsetting; - //print_usb_interface_desc(&(iface_desc->desc)); - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Current number of endpoints :%x \n", iface_desc->desc.bNumEndpoints); - for (value = 0; value < iface_desc->desc.bNumEndpoints; ++value) + + for (value = 0; value < iface_desc->desc.bNumEndpoints; ++value) { - endpoint = &iface_desc->endpoint[value].desc; - //print_usb_endpoint_descriptor(endpoint); + endpoint = &iface_desc->endpoint[value].desc; if (!psIntfAdapter->sBulkIn.bulk_in_endpointAddr && bcm_usb_endpoint_is_bulk_in(endpoint)) { @@ -682,10 +593,10 @@ INT InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter) psIntfAdapter->sIntrIn.int_in_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!psIntfAdapter->sIntrIn.int_in_buffer) { - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Could not allocate interrupt_in_buffer"); + dev_err(&psIntfAdapter->udev->dev, + "could not allocate interrupt_in_buffer\n"); return -EINVAL; } - //psIntfAdapter->sIntrIn.int_in_pipe = } if (!psIntfAdapter->sIntrOut.int_out_endpointAddr && bcm_usb_endpoint_is_int_out(endpoint)) @@ -716,26 +627,15 @@ INT InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter) psIntfAdapter->sIntrOut.int_out_buffer= kmalloc(buffer_size, GFP_KERNEL); if (!psIntfAdapter->sIntrOut.int_out_buffer) - { - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Could not allocate interrupt_out_buffer"); - return -EINVAL; - } + { + dev_err(&psIntfAdapter->udev->dev, + "could not allocate interrupt_out_buffer\n"); + return -EINVAL; + } } } } usb_set_intfdata(psIntfAdapter->interface, psIntfAdapter); - retval = usb_register_dev(psIntfAdapter->interface, &usbbcm_class); - if(retval) - { - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "usb register dev failed = %d", retval); - psIntfAdapter->psAdapter->bUsbClassDriverRegistered = FALSE; - return retval; - } - else - { - psIntfAdapter->psAdapter->bUsbClassDriverRegistered = TRUE; - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "usb dev registered"); - } psIntfAdapter->psAdapter->bcm_file_download = InterfaceFileDownload; psIntfAdapter->psAdapter->bcm_file_readback_from_chip = @@ -757,21 +657,13 @@ INT InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter) } - retval = device_run(psIntfAdapter); - if(retval) - { - return retval; - } - - - return 0; + return device_run(psIntfAdapter); } static int InterfaceSuspend (struct usb_interface *intf, pm_message_t message) { PS_INTERFACE_ADAPTER psIntfAdapter = usb_get_intfdata(intf); - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "=================================\n"); - //Bcm_kill_all_URBs(psIntfAdapter); + psIntfAdapter->bSuspended = TRUE; if(TRUE == psIntfAdapter->bPreparingForBusSuspend) @@ -812,57 +704,43 @@ static int InterfaceResume (struct usb_interface *intf) return 0; } -static int InterfacePreReset(struct usb_interface *intf) -{ - printk("====================>"); - return STATUS_SUCCESS; -} - -static int InterfacePostReset(struct usb_interface *intf) -{ - printk("Do Post chip reset setting here if it is required"); - return STATUS_SUCCESS; -} static struct usb_driver usbbcm_driver = { .name = "usbbcm", .probe = usbbcm_device_probe, .disconnect = usbbcm_disconnect, .suspend = InterfaceSuspend, .resume = InterfaceResume, - .pre_reset=InterfacePreReset, - .post_reset=InterfacePostReset, .id_table = InterfaceUsbtable, .supports_autosuspend = 1, }; +struct class *bcm_class; -/* -Function: InterfaceInitialize -Description: This is the hardware specific initialization Function. - Registering the driver with NDIS , other device specific NDIS - and hardware initializations are done here. - -Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context +static __init int bcm_init(void) +{ + printk(KERN_INFO "%s: %s, %s\n", DRV_NAME, DRV_DESCRIPTION, DRV_VERSION); + printk(KERN_INFO "%s\n", DRV_COPYRIGHT); + bcm_class = class_create(THIS_MODULE, DRV_NAME); + if (IS_ERR(bcm_class)) { + printk(KERN_ERR DRV_NAME ": could not create class\n"); + return PTR_ERR(bcm_class); + } -Return: BCM_STATUS_SUCCESS - If Initialization of the - HW Interface was successful. - Other - If an error occured. -*/ -INT InterfaceInitialize(void) -{ -// BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Registering Usb driver!!"); return usb_register(&usbbcm_driver); } -INT InterfaceExit(void) +static __exit void bcm_exit(void) { - //PMINI_ADAPTER psAdapter = NULL; - int status = 0; + class_destroy (bcm_class); - //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Deregistering Usb driver!!"); usb_deregister(&usbbcm_driver); - return status; } + +module_init(bcm_init); +module_exit(bcm_exit); + +MODULE_DESCRIPTION(DRV_DESCRIPTION); +MODULE_VERSION(DRV_VERSION); MODULE_LICENSE ("GPL"); diff --git a/trunk/drivers/staging/bcm/InterfaceInit.h b/trunk/drivers/staging/bcm/InterfaceInit.h index e7a96e5c5c50..3b8e17b619ba 100644 --- a/trunk/drivers/staging/bcm/InterfaceInit.h +++ b/trunk/drivers/staging/bcm/InterfaceInit.h @@ -19,33 +19,7 @@ INT InterfaceInitialize(void); INT InterfaceExit(void); -#ifndef BCM_SHM_INTERFACE -INT InterfaceAdapterInit(PS_INTERFACE_ADAPTER Adapter); - INT usbbcm_worker_thread(PS_INTERFACE_ADAPTER psIntfAdapter); -VOID InterfaceAdapterFree(PS_INTERFACE_ADAPTER psIntfAdapter); - -#else -INT InterfaceAdapterInit(PMINI_ADAPTER Adapter); -#endif - - -#if 0 - -ULONG InterfaceClaimAdapter(PMINI_ADAPTER Adapter); - -VOID InterfaceDDRControllerInit(PMINI_ADAPTER Adapter); - -ULONG InterfaceReset(PMINI_ADAPTER Adapter); - -ULONG InterfaceRegisterResources(PMINI_ADAPTER Adapter); - -VOID InterfaceUnRegisterResources(PMINI_ADAPTER Adapter); - -ULONG InterfaceFirmwareDownload(PMINI_ADAPTER Adapter); - -#endif - #endif diff --git a/trunk/drivers/staging/bcm/InterfaceIsr.c b/trunk/drivers/staging/bcm/InterfaceIsr.c index f928fe4d564d..423464765e59 100644 --- a/trunk/drivers/staging/bcm/InterfaceIsr.c +++ b/trunk/drivers/staging/bcm/InterfaceIsr.c @@ -1,6 +1,5 @@ #include "headers.h" -#ifndef BCM_SHM_INTERFACE static void read_int_callback(struct urb *urb/*, struct pt_regs *regs*/) { @@ -8,6 +7,10 @@ static void read_int_callback(struct urb *urb/*, struct pt_regs *regs*/) PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)urb->context; PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter ; + if (netif_msg_intr(Adapter)) + pr_info(PFX "%s: interrupt status %d\n", + Adapter->dev->name, status); + if(Adapter->device_removed == TRUE) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Device has Got Removed."); @@ -164,40 +167,3 @@ INT StartInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter) return status; } -/* -Function: InterfaceEnableInterrupt - -Description: This is the hardware specific Function for configuring - and enabling the interrupts on the device. - -Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context - - -Return: BCM_STATUS_SUCCESS - If configuring the interrupts was successful. - Other - If an error occured. -*/ - -void InterfaceEnableInterrupt(PMINI_ADAPTER Adapter) -{ - -} - -/* -Function: InterfaceDisableInterrupt - -Description: This is the hardware specific Function for disabling the interrupts on the device. - -Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context - - -Return: BCM_STATUS_SUCCESS - If disabling the interrupts was successful. - Other - If an error occured. -*/ - -void InterfaceDisableInterrupt(PMINI_ADAPTER Adapter) -{ - -} - -#endif - diff --git a/trunk/drivers/staging/bcm/InterfaceMisc.c b/trunk/drivers/staging/bcm/InterfaceMisc.c index 8fc893b37fe4..b7d6e7a414a9 100644 --- a/trunk/drivers/staging/bcm/InterfaceMisc.c +++ b/trunk/drivers/staging/bcm/InterfaceMisc.c @@ -1,17 +1,5 @@ #include "headers.h" -#ifndef BCM_SHM_INTERFACE - -PS_INTERFACE_ADAPTER -InterfaceAdapterGet(PMINI_ADAPTER psAdapter) -{ - if(psAdapter == NULL) - { - return NULL; - } - return (PS_INTERFACE_ADAPTER)(psAdapter->pvInterfaceAdapter); -} - INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter, UINT addr, @@ -236,9 +224,7 @@ VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter) } /* Cancel All submitted TX URB's */ - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cancelling All Submitted TX Urbs \n"); - - for(i = 0; i < MAXIMUM_USB_TCB; i++) + for(i = 0; i < MAXIMUM_USB_TCB; i++) { tempUrb = psIntfAdapter->asUsbTcb[i].urb; if(tempUrb) @@ -248,9 +234,6 @@ VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter) } } - - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cancelling All submitted Rx Urbs \n"); - for(i = 0; i < MAXIMUM_USB_RCB; i++) { tempUrb = psIntfAdapter->asUsbRcb[i].urb; @@ -261,16 +244,11 @@ VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter) } } - atomic_set(&psIntfAdapter->uNumTcbUsed, 0); atomic_set(&psIntfAdapter->uCurrTcb, 0); atomic_set(&psIntfAdapter->uNumRcbUsed, 0); atomic_set(&psIntfAdapter->uCurrRcb, 0); - - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "TCB: used- %d cur-%d\n", atomic_read(&psIntfAdapter->uNumTcbUsed), atomic_read(&psIntfAdapter->uCurrTcb)); - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "RCB: used- %d cur-%d\n", atomic_read(&psIntfAdapter->uNumRcbUsed), atomic_read(&psIntfAdapter->uCurrRcb)); - } VOID putUsbSuspend(struct work_struct *work) @@ -282,9 +260,6 @@ VOID putUsbSuspend(struct work_struct *work) if(psIntfAdapter->bSuspended == FALSE) usb_autopm_put_interface(intf); - else - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Interface Resumed Completely\n"); } -#endif diff --git a/trunk/drivers/staging/bcm/InterfaceMisc.h b/trunk/drivers/staging/bcm/InterfaceMisc.h index 74c81d45cff4..6c9e39bf9889 100644 --- a/trunk/drivers/staging/bcm/InterfaceMisc.h +++ b/trunk/drivers/staging/bcm/InterfaceMisc.h @@ -1,9 +1,6 @@ #ifndef __INTERFACE_MISC_H #define __INTERFACE_MISC_H -PS_INTERFACE_ADAPTER -InterfaceAdapterGet(PMINI_ADAPTER psAdapter); - INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter, UINT addr, diff --git a/trunk/drivers/staging/bcm/InterfaceRx.c b/trunk/drivers/staging/bcm/InterfaceRx.c index 6fee9684f2ef..533f8ebe0f84 100644 --- a/trunk/drivers/staging/bcm/InterfaceRx.c +++ b/trunk/drivers/staging/bcm/InterfaceRx.c @@ -1,5 +1,15 @@ #include "headers.h" -extern int SearchVcid(PMINI_ADAPTER , unsigned short); + +static int SearchVcid(PMINI_ADAPTER Adapter,unsigned short usVcid) +{ + int iIndex=0; + + for(iIndex=(NO_OF_QUEUES-1);iIndex>=0;iIndex--) + if(Adapter->PackInfo[iIndex].usVCID_Value == usVcid) + return iIndex; + return NO_OF_QUEUES+1; + +} static PUSB_RCB @@ -38,13 +48,9 @@ static void read_bulk_callback(struct urb *urb) PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter; PLEADER pLeader = urb->transfer_buffer; - - #if 0 - int *puiBuffer = NULL; - struct timeval tv; - memset(&tv, 0, sizeof(tv)); - do_gettimeofday(&tv); - #endif + if (unlikely(netif_msg_rx_status(Adapter))) + pr_info(PFX "%s: rx urb status %d length %d\n", + Adapter->dev->name, urb->status, urb->actual_length); if((Adapter->device_removed == TRUE) || (TRUE == Adapter->bEndPointHalted) || @@ -89,10 +95,10 @@ static void read_bulk_callback(struct urb *urb) BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Leader Status:0x%hX, Length:0x%hX, VCID:0x%hX", pLeader->Status,pLeader->PLength,pLeader->Vcid); if(MAX_CNTL_PKT_SIZE < pLeader->PLength) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Corrupted leader length...%d\n", - pLeader->PLength); - atomic_inc(&Adapter->RxPacketDroppedCount); - atomic_add(pLeader->PLength, &Adapter->BadRxByteCount); + if (netif_msg_rx_err(Adapter)) + pr_info(PFX "%s: corrupted leader length...%d\n", + Adapter->dev->name, pLeader->PLength); + ++Adapter->dev->stats.rx_dropped; atomic_dec(&psIntfAdapter->uNumRcbUsed); return; } @@ -145,10 +151,9 @@ static void read_bulk_callback(struct urb *urb) skb_put (skb, pLeader->PLength + ETH_HLEN); Adapter->PackInfo[QueueIndex].uiTotalRxBytes+=pLeader->PLength; Adapter->PackInfo[QueueIndex].uiThisPeriodRxBytes+= pLeader->PLength; - atomic_add(pLeader->PLength, &Adapter->GoodRxByteCount); BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Recived Data pkt of len :0x%X", pLeader->PLength); - if(Adapter->if_up) + if(netif_running(Adapter->dev)) { /* Moving ahead by ETH_HLEN to the data ptr as received from FW */ skb_pull(skb, ETH_HLEN); @@ -173,9 +178,12 @@ static void read_bulk_callback(struct urb *urb) else { BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "i/f not up hance freeing SKB..."); - bcm_kfree_skb(skb); + dev_kfree_skb(skb); } - atomic_inc(&Adapter->GoodRxPktCount); + + ++Adapter->dev->stats.rx_packets; + Adapter->dev->stats.rx_bytes += pLeader->PLength; + for(uiIndex = 0 ; uiIndex < MIBS_MAX_HIST_ENTRIES ; uiIndex++) { if((pLeader->PLength <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) diff --git a/trunk/drivers/staging/bcm/InterfaceTx.c b/trunk/drivers/staging/bcm/InterfaceTx.c index 771f7b34d2ec..f434b899a0d0 100644 --- a/trunk/drivers/staging/bcm/InterfaceTx.c +++ b/trunk/drivers/staging/bcm/InterfaceTx.c @@ -1,50 +1,5 @@ #include "headers.h" -#ifndef BCM_SHM_INTERFACE - -/* -Function: InterfaceTxDataPacket - -Description: This is the hardware specific Function for Transmitting - data packet to the device. - -Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context - PVOID Packet - Packet Containing the data to be transmitted - USHORT usVcid - VCID on which data packet is to be sent - - -Return: BCM_STATUS_SUCCESS - If Tx was successful. - Other - If an error occured. -*/ - -ULONG InterfaceTxDataPacket(PMINI_ADAPTER Adapter,PVOID Packet,USHORT usVcid) -{ - ULONG Status = 0; - return Status; -} - -/* -Function: InterfaceTxControlPacket - -Description: This is the hardware specific Function for Transmitting - control packet to the device. - -Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context - PVOID pvBuffer - Buffer containg control packet - UINT uiBufferLength - Buffer Length - -Return: BCM_STATUS_SUCCESS - If control packet transmit was successful. - Other - If an error occured. -*/ - -ULONG InterfaceTxControlPacket(PMINI_ADAPTER Adapter,PVOID pvBuffer,UINT uiBufferLength) -{ - ULONG Status = 0; - - - - return Status; -} /*this is transmit call-back(BULK OUT)*/ static void write_bulk_callback(struct urb *urb/*, struct pt_regs *regs*/) { @@ -54,10 +9,10 @@ static void write_bulk_callback(struct urb *urb/*, struct pt_regs *regs*/) PMINI_ADAPTER psAdapter = psIntfAdapter->psAdapter ; BOOLEAN bpowerDownMsg = FALSE ; PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); -#if 0 - struct timeval tv; - UINT time_ms = 0; -#endif + + if (unlikely(netif_msg_tx_done(Adapter))) + pr_info(PFX "%s: transmit status %d\n", Adapter->dev->name, urb->status); + if(urb->status != STATUS_SUCCESS) { if(urb->status == -EPIPE) @@ -78,11 +33,6 @@ static void write_bulk_callback(struct urb *urb/*, struct pt_regs *regs*/) if(TRUE == psAdapter->bPreparingForLowPowerMode) { - #if 0 - do_gettimeofday(&tv); - time_ms = tv.tv_sec *1000 + tv.tv_usec/1000; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, " %s Idle Mode ACK_Sent got from device at time :0x%x", __FUNCTION__, time_ms); - #endif if(((pControlMsg->szData[0] == GO_TO_IDLE_MODE_PAYLOAD) && (pControlMsg->szData[1] == TARGET_CAN_GO_TO_IDLE_MODE))) @@ -162,7 +112,7 @@ err_exit : } -static __inline PUSB_TCB GetBulkOutTcb(PS_INTERFACE_ADAPTER psIntfAdapter) +static PUSB_TCB GetBulkOutTcb(PS_INTERFACE_ADAPTER psIntfAdapter) { PUSB_TCB pTcb = NULL; UINT index = 0; @@ -183,7 +133,7 @@ static __inline PUSB_TCB GetBulkOutTcb(PS_INTERFACE_ADAPTER psIntfAdapter) return pTcb; } -static __inline int TransmitTcb(PS_INTERFACE_ADAPTER psIntfAdapter, PUSB_TCB pTcb, PVOID data, int len) +static int TransmitTcb(PS_INTERFACE_ADAPTER psIntfAdapter, PUSB_TCB pTcb, PVOID data, int len) { struct urb *urb = pTcb->urb; @@ -255,5 +205,4 @@ int InterfaceTransmitPacket(PVOID arg, PVOID data, UINT len) return TransmitTcb(psIntfAdapter, pTcb, data, len); } -#endif diff --git a/trunk/drivers/staging/bcm/InterfaceTx.h b/trunk/drivers/staging/bcm/InterfaceTx.h index 053f631e2042..273147577c17 100644 --- a/trunk/drivers/staging/bcm/InterfaceTx.h +++ b/trunk/drivers/staging/bcm/InterfaceTx.h @@ -3,11 +3,5 @@ INT InterfaceTransmitPacket(PVOID arg, PVOID data, UINT len); - -ULONG InterfaceTxDataPacket(PMINI_ADAPTER Adapter,PVOID Packet,USHORT usVcid); - -ULONG InterfaceTxControlPacket(PMINI_ADAPTER Adapter,PVOID pvBuffer,UINT uiBufferLength); - - #endif diff --git a/trunk/drivers/staging/bcm/Interfacemain.h b/trunk/drivers/staging/bcm/Interfacemain.h deleted file mode 100644 index e0db563c5e0f..000000000000 --- a/trunk/drivers/staging/bcm/Interfacemain.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _MAIN_ -#define _MAIN_ -#if 0 -typedef struct _MINI_ADAPTER -{ - S_INTERFACE_ADAPTER stInterfaceAdapter; -}MINI_ADAPTER,*PMINI_ADAPTER; - -#endif -#endif diff --git a/trunk/drivers/staging/bcm/LeakyBucket.c b/trunk/drivers/staging/bcm/LeakyBucket.c index cae382313ce9..f4cf41c0e46b 100644 --- a/trunk/drivers/staging/bcm/LeakyBucket.c +++ b/trunk/drivers/staging/bcm/LeakyBucket.c @@ -75,14 +75,14 @@ static VOID UpdateTokenCount(register PMINI_ADAPTER Adapter) * Returns - The number of bytes allowed for transmission. * ***********************************************************************/ -static __inline ULONG GetSFTokenCount(PMINI_ADAPTER Adapter, PacketInfo *psSF) +static ULONG GetSFTokenCount(PMINI_ADAPTER Adapter, PacketInfo *psSF) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow ===>"); /* Validate the parameters */ if(NULL == Adapter || (psSF < Adapter->PackInfo && (uintptr_t)psSF > (uintptr_t) &Adapter->PackInfo[HiPriority])) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Got wrong Parameters:Adapter: %p, QIndex: %ld\n", Adapter, (psSF-Adapter->PackInfo)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Got wrong Parameters:Adapter: %p, QIndex: %zd\n", Adapter, (psSF-Adapter->PackInfo)); return 0; } @@ -94,51 +94,27 @@ static __inline ULONG GetSFTokenCount(PMINI_ADAPTER Adapter, PacketInfo *psSF) } else { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Not enough tokens in queue %ld Available %u\n", + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Not enough tokens in queue %zd Available %u\n", psSF-Adapter->PackInfo, psSF->uiCurrentTokenCount); psSF->uiPendedLast = 1; } } else { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Queue %ld not valid\n", psSF-Adapter->PackInfo); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Queue %zd not valid\n", psSF-Adapter->PackInfo); } BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow <==="); return 0; } -static __inline void RemovePacketFromQueue(PacketInfo *pPackInfo , struct sk_buff *Packet) -{ - struct sk_buff *psQueueCurrent=NULL, *psLastQueueNode=NULL; - psQueueCurrent = pPackInfo->FirstTxQueue; - while(psQueueCurrent) - { - if(Packet == psQueueCurrent) - { - if(psQueueCurrent == pPackInfo->FirstTxQueue) - { - pPackInfo->FirstTxQueue=psQueueCurrent->next; - if(psQueueCurrent==pPackInfo->LastTxQueue) - pPackInfo->LastTxQueue=NULL; - } - else - { - psLastQueueNode->next=psQueueCurrent->next; - } - break; - } - psLastQueueNode = psQueueCurrent; - psQueueCurrent=psQueueCurrent->next; - } -} /** @ingroup tx_functions This function despatches packet from the specified queue. @return Zero(success) or Negative value(failure) */ -static __inline INT SendPacketFromQueue(PMINI_ADAPTER Adapter,/**", (psSF-Adapter->PackInfo)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "%zd ====>", (psSF-Adapter->PackInfo)); if((psSF != &Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount))//Get data packet { if(!psSF->ucDirection ) @@ -197,10 +172,8 @@ static __inline VOID CheckAndSendPacketFromIndex BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "UpdateTokenCount "); if(Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle Mode..Hence blocking Data Packets..\n"); - return; - } + return; /* in idle mode */ + // Check for Free Descriptors if(atomic_read(&Adapter->CurrNumFreeTxDesc) <= MINIMUM_PENDING_DESCRIPTORS) { @@ -208,9 +181,6 @@ static __inline VOID CheckAndSendPacketFromIndex return ; } -#if 0 - PruneQueue(Adapter,(psSF-Adapter->PackInfo)); -#endif spin_lock_bh(&psSF->SFQueueLock); QueuePacket=psSF->FirstTxQueue; @@ -240,7 +210,7 @@ static __inline VOID CheckAndSendPacketFromIndex } else { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %ld\n", psSF-Adapter->PackInfo); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %zd\n", psSF-Adapter->PackInfo); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n", psSF->uiCurrentTokenCount, iPacketLen); //this part indicates that becuase of non-availability of the tokens @@ -290,17 +260,6 @@ static __inline VOID CheckAndSendPacketFromIndex } } } - - if(Status != STATUS_SUCCESS) //Tx of data packet to device Failed - { - if(Adapter->bcm_jiffies == 0) - Adapter->bcm_jiffies = jiffies; - } - else - { - Adapter->bcm_jiffies = 0; - } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<====="); } @@ -387,12 +346,7 @@ VOID transmit_packets(PMINI_ADAPTER Adapter) if(exit_flag == TRUE ) break ; }/* end of inner while loop */ - if(Adapter->bcm_jiffies == 0 && - atomic_read(&Adapter->TotalPacketCount) != 0 && - uiPrevTotalCount == atomic_read(&Adapter->TotalPacketCount)) - { - Adapter->bcm_jiffies = jiffies; - } + update_per_cid_rx (Adapter); Adapter->txtransmit_running = 0; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<======"); diff --git a/trunk/drivers/staging/bcm/Macros.h b/trunk/drivers/staging/bcm/Macros.h index 0241234605f1..feb351578c8b 100644 --- a/trunk/drivers/staging/bcm/Macros.h +++ b/trunk/drivers/staging/bcm/Macros.h @@ -4,10 +4,6 @@ #ifndef __MACROS_H__ #define __MACROS_H__ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#define kthread_run(threadfn,data,datafmt)(struct task_struct *)kernel_thread(threadfn,data,0) -#endif - #define TX_TIMER_PERIOD 10 //10 msec #define MAX_CLASSIFIERS 100 //#define MAX_CLASSIFIERS_PER_SF 20 @@ -17,10 +13,9 @@ #define MAX_DATA_PKTS 200 #define MAX_ETH_SIZE 1536 #define MAX_CNTL_PKT_SIZE 2048 -/* TIMER RELATED */ -#define JIFFIES_2_QUADPART() (ULONG)(jiffies * 10000) // jiffies(1msec) to Quadpart(100nsec) #define MTU_SIZE 1400 +#define TX_QLEN 5 #define MAC_ADDR_REGISTER 0xbf60d000 @@ -266,7 +261,7 @@ typedef enum _E_PHS_DSC_ACTION #define FIRMWARE_BEGIN_ADDR 0xBFC00000 -#define INVALID_QUEUE_INDEX (USHORT)-1 +#define INVALID_QUEUE_INDEX NO_OF_QUEUES #define INVALID_PID (pid_t)-1 #define DDR_80_MHZ 0 @@ -300,12 +295,7 @@ typedef enum _E_PHS_DSC_ACTION /* Idle Mode Related Registers */ #define DEBUG_INTERRUPT_GENERATOR_REGISTOR 0x0F00007C -#ifdef BCM_SHM_INTERFACE -#define SW_ABORT_IDLEMODE_LOC 0xbfc02f9c -#define CPE_VIRTUAL_MAILBOX_REG 0xBFC02E58 -#else #define SW_ABORT_IDLEMODE_LOC 0x0FF01FFC -#endif #define SW_ABORT_IDLEMODE_PATTERN 0xd0ea1d1e #define DEVICE_INT_OUT_EP_REG0 0x0F011870 @@ -355,12 +345,7 @@ typedef enum ePMU_MODES HYBRID_MODE_6 = 2 }PMU_MODE; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) -#define MAX_RDM_WRM_RETIRES 16 -#else #define MAX_RDM_WRM_RETIRES 1 -#endif - enum eAbortPattern { ABORT_SHUTDOWN_MODE = 1, @@ -369,27 +354,6 @@ enum eAbortPattern { ABORT_IDLE_SYNCDOWN = 3 }; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) - #define GET_BCM_ADAPTER(net_dev) ({\ - PMINI_ADAPTER __Adapter = NULL; \ - if (net_dev) { \ - __Adapter = (PMINI_ADAPTER)(net_dev->priv); \ - } \ - else { \ - __Adapter = NULL; \ - }__Adapter;} ) -#else - #define GET_BCM_ADAPTER(net_dev) ({\ - PMINI_ADAPTER __Adapter = NULL; \ - if (net_dev) { \ - __Adapter = (PMINI_ADAPTER)(*((unsigned long *)netdev_priv(net_dev))); \ - } \ - else { \ - __Adapter = NULL; \ - }__Adapter;}) - - -#endif /* Offsets used by driver in skb cb variable */ #define SKB_CB_CLASSIFICATION_OFFSET 0 diff --git a/trunk/drivers/staging/bcm/Makefile b/trunk/drivers/staging/bcm/Makefile index c3ae25af670a..652b7f87737c 100644 --- a/trunk/drivers/staging/bcm/Makefile +++ b/trunk/drivers/staging/bcm/Makefile @@ -6,7 +6,7 @@ obj-$(CONFIG_BCM_WIMAX) += bcm_wimax.o bcm_wimax-y := InterfaceDld.o InterfaceIdleMode.o InterfaceInit.o InterfaceRx.o \ InterfaceIsr.o InterfaceMisc.o InterfaceTx.o \ - Arp.o CmHost.o Debug.o IPv6Protocol.o Qos.o Transmit.o\ + CmHost.o IPv6Protocol.o Qos.o Transmit.o\ Bcmnet.o DDRInit.o HandleControlPacket.o\ LeakyBucket.o Misc.o sort.o Bcmchar.o hostmibs.o PHSModule.o\ - Osal_Misc.o led_control.o nvm.o vendorspecificextn.o + led_control.o nvm.o vendorspecificextn.o diff --git a/trunk/drivers/staging/bcm/Misc.c b/trunk/drivers/staging/bcm/Misc.c index 22550f745917..82d9f86821ca 100644 --- a/trunk/drivers/staging/bcm/Misc.c +++ b/trunk/drivers/staging/bcm/Misc.c @@ -1,5 +1,12 @@ #include "headers.h" +static int BcmFileDownload(PMINI_ADAPTER Adapter, const char *path, + unsigned int loc); +static VOID doPowerAutoCorrection(PMINI_ADAPTER psAdapter); +static void HandleShutDownModeRequest(PMINI_ADAPTER Adapter,PUCHAR pucBuffer); +static int bcm_parse_target_params(PMINI_ADAPTER Adapter); +static void beceem_protocol_reset (PMINI_ADAPTER Adapter); + static VOID default_wimax_protocol_initialize(PMINI_ADAPTER Adapter) { @@ -60,15 +67,6 @@ InitAdapter(PMINI_ADAPTER psAdapter) //init_waitqueue_head(&psAdapter->device_wake_queue); psAdapter->fw_download_done=FALSE; - psAdapter->pvOsDepData = (PLINUX_DEP_DATA) kmalloc(sizeof(LINUX_DEP_DATA), - GFP_KERNEL); - - if(psAdapter->pvOsDepData == NULL) - { - BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Linux Specific Data allocation failed"); - return -ENOMEM; - } - memset(psAdapter->pvOsDepData, 0, sizeof(LINUX_DEP_DATA)); default_wimax_protocol_initialize(psAdapter); for (i=0;icontrol_packet_handler && !IS_ERR(Adapter->control_packet_handler)) kthread_stop (Adapter->control_packet_handler); + if(Adapter->transmit_packet_thread && !IS_ERR(Adapter->transmit_packet_thread)) - kthread_stop (Adapter->transmit_packet_thread); - wake_up(&Adapter->process_read_wait_queue); + kthread_stop (Adapter->transmit_packet_thread); + + wake_up(&Adapter->process_read_wait_queue); + if(Adapter->LEDInfo.led_thread_running & (BCM_LED_THREAD_RUNNING_ACTIVELY | BCM_LED_THREAD_RUNNING_INACTIVELY)) kthread_stop (Adapter->LEDInfo.led_cntrl_threadid); - bcm_unregister_networkdev(Adapter); + + unregister_networkdev(Adapter); + + /* FIXME: use proper wait_event and refcounting */ while(atomic_read(&Adapter->ApplicationRunning)) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Waiting for Application to close.. %d\n",atomic_read(&Adapter->ApplicationRunning)); msleep(100); } unregister_control_device_interface(Adapter); - if(Adapter->dev && !IS_ERR(Adapter->dev)) - free_netdev(Adapter->dev); - if(Adapter->pstargetparams != NULL) - { - bcm_kfree(Adapter->pstargetparams); - } + + kfree(Adapter->pstargetparams); + for (count =0;count < MAX_CNTRL_PKTS;count++) - { - if(Adapter->txctlpacket[count]) - bcm_kfree(Adapter->txctlpacket[count]); - } + kfree(Adapter->txctlpacket[count]); + FreeAdapterDsxBuffer(Adapter); - if(Adapter->pvOsDepData) - bcm_kfree (Adapter->pvOsDepData); - if(Adapter->pvInterfaceAdapter) - bcm_kfree(Adapter->pvInterfaceAdapter); + + kfree(Adapter->pvInterfaceAdapter); //Free the PHS Interface PhsCleanup(&Adapter->stBCMPhsContext); -#ifndef BCM_SHM_INTERFACE BcmDeAllocFlashCSStructure(Adapter); -#endif - bcm_kfree (Adapter); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "<========\n"); + free_netdev(Adapter->dev); } - -int create_worker_threads(PMINI_ADAPTER psAdapter) +static int create_worker_threads(PMINI_ADAPTER psAdapter) { - BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Init Threads..."); // Rx Control Packets Processing psAdapter->control_packet_handler = kthread_run((int (*)(void *)) - control_packet_handler, psAdapter, "CtrlPktHdlr"); + control_packet_handler, psAdapter, "%s-rx", DRV_NAME); if(IS_ERR(psAdapter->control_packet_handler)) { - BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No Kernel Thread, but still returning success\n"); + pr_notice(DRV_NAME ": could not create control thread\n"); return PTR_ERR(psAdapter->control_packet_handler); } + // Tx Thread psAdapter->transmit_packet_thread = kthread_run((int (*)(void *)) - tx_pkt_handler, psAdapter, "TxPktThread"); + tx_pkt_handler, psAdapter, "%s-tx", DRV_NAME); if(IS_ERR (psAdapter->transmit_packet_thread)) { - BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No Kernel Thread, but still returning success"); + pr_notice(DRV_NAME ": could not creat transmit thread\n"); kthread_stop(psAdapter->control_packet_handler); return PTR_ERR(psAdapter->transmit_packet_thread); } return 0; } - -static inline struct file *open_firmware_file(PMINI_ADAPTER Adapter, char *path) +static struct file *open_firmware_file(PMINI_ADAPTER Adapter, const char *path) { struct file *flp=NULL; mm_segment_t oldfs; @@ -200,26 +192,20 @@ static inline struct file *open_firmware_file(PMINI_ADAPTER Adapter, char *path) set_fs(oldfs); if(IS_ERR(flp)) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Unable To Open File %s, err %lx", - path, PTR_ERR(flp)); - flp = NULL; + pr_err(DRV_NAME "Unable To Open File %s, err %ld", + path, PTR_ERR(flp)); + flp = NULL; } - else - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got file descriptor pointer of %s!", - path); - } - if(Adapter->device_removed) - { - flp = NULL; - } + + if(Adapter->device_removed) + flp = NULL; return flp; } -int BcmFileDownload(PMINI_ADAPTER Adapter,/**< Logical Adapter */ - char *path, /**< path to image file */ +static int BcmFileDownload(PMINI_ADAPTER Adapter,/**< Logical Adapter */ + const char *path, /**< path to image file */ unsigned int loc /**< Download Address on the chip*/ ) { @@ -265,29 +251,8 @@ int BcmFileDownload(PMINI_ADAPTER Adapter,/**< Logical Adapter */ if(flp && !(IS_ERR(flp))) filp_close(flp, current->files); set_fs(oldfs); - do_gettimeofday(&tv); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "file download done at %lx", ((tv.tv_sec * 1000) + - (tv.tv_usec/1000))); - return errorno; -} - -void bcm_kfree_skb(struct sk_buff *skb) -{ - if(skb) - { - kfree_skb(skb); - } - skb = NULL ; -} - -VOID bcm_kfree(VOID *ptr) -{ - if(ptr) - { - kfree(ptr); - } - ptr = NULL ; + return errorno; } /** @@ -395,13 +360,6 @@ INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter,/**LEDInfo.bIdleMode_tx_from_host = TRUE; -#if 0 - if(STATUS_SUCCESS != InterfaceIdleModeWakeup(Adapter)) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Idle Mode Wake up Failed\n"); - return STATUS_FAILURE; - } -#endif Adapter->bWakeUpDevice = TRUE; wake_up(&Adapter->process_rx_cntrlpkt); @@ -489,9 +447,6 @@ INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter,/**index_wr_txcntrlpkt); BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Calling transmit_packets"); atomic_set(&Adapter->TxPktAvail, 1); -#ifdef BCM_SHM_INTERFACE - virtual_mail_box_interrupt(); -#endif wake_up(&Adapter->tx_packet_wait_queue); } else @@ -530,18 +485,6 @@ static VOID SendStatisticsPointerRequest(PMINI_ADAPTER Adapter, #endif -void SendLinkDown(PMINI_ADAPTER Adapter) -{ - LINK_REQUEST stLinkDownRequest; - memset(&stLinkDownRequest, 0, sizeof(LINK_REQUEST)); - stLinkDownRequest.Leader.Status=LINK_UP_CONTROL_REQ; - stLinkDownRequest.Leader.PLength=sizeof(ULONG);//minimum 4 bytes - stLinkDownRequest.szData[0]=LINK_DOWN_REQ_PAYLOAD; - Adapter->bLinkDownRequested = TRUE; - - CopyBufferToControlPacket(Adapter,&stLinkDownRequest); -} - /****************************************************************** * Function - LinkMessage() * @@ -552,7 +495,7 @@ void SendLinkDown(PMINI_ADAPTER Adapter) * * Returns - None. *******************************************************************/ -__inline VOID LinkMessage(PMINI_ADAPTER Adapter) +VOID LinkMessage(PMINI_ADAPTER Adapter) { PLINK_REQUEST pstLinkRequest=NULL; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "=====>"); @@ -594,7 +537,7 @@ __inline VOID LinkMessage(PMINI_ADAPTER Adapter) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Calling CopyBufferToControlPacket"); CopyBufferToControlPacket(Adapter, pstLinkRequest); - bcm_kfree(pstLinkRequest); + kfree(pstLinkRequest); } BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "LinkMessage <====="); return; @@ -614,8 +557,8 @@ __inline VOID LinkMessage(PMINI_ADAPTER Adapter) VOID StatisticsResponse(PMINI_ADAPTER Adapter,PVOID pvBuffer) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s====>",__FUNCTION__); - Adapter->StatisticsPointer = ntohl(*(PULONG)pvBuffer); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Stats at %lx", Adapter->StatisticsPointer); + Adapter->StatisticsPointer = ntohl(*(__be32 *)pvBuffer); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Stats at %x", (UINT)Adapter->StatisticsPointer); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s <====",__FUNCTION__); return; } @@ -787,12 +730,10 @@ void SendIdleModeResponse(PMINI_ADAPTER Adapter) down(&Adapter->rdmwrmsync); Adapter->bPreparingForLowPowerMode = TRUE; up(&Adapter->rdmwrmsync); -#ifndef BCM_SHM_INTERFACE //Killing all URBS. if(Adapter->bDoSuspend == TRUE) Bcm_kill_all_URBs((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); -#endif } else { @@ -811,9 +752,7 @@ void SendIdleModeResponse(PMINI_ADAPTER Adapter) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"fail to send the Idle mode Request \n"); Adapter->bPreparingForLowPowerMode = FALSE; -#ifndef BCM_SHM_INTERFACE StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); -#endif } do_gettimeofday(&tv); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "IdleMode Msg submitter to Q :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000); @@ -980,12 +919,10 @@ VOID DumpPackInfo(PMINI_ADAPTER Adapter) } - -__inline int reset_card_proc(PMINI_ADAPTER ps_adapter) +int reset_card_proc(PMINI_ADAPTER ps_adapter) { int retval = STATUS_SUCCESS; -#ifndef BCM_SHM_INTERFACE PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); PS_INTERFACE_ADAPTER psIntfAdapter = NULL; unsigned int value = 0, uiResetValue = 0; @@ -1006,11 +943,9 @@ __inline int reset_card_proc(PMINI_ADAPTER ps_adapter) wrmalt(ps_adapter, SYS_CFG, &value, sizeof(value)); } -#ifndef BCM_SHM_INTERFACE //killing all submitted URBs. psIntfAdapter->psAdapter->StopAllXaction = TRUE ; Bcm_kill_all_URBs(psIntfAdapter); -#endif /* Reset the UMA-B Device */ if(ps_adapter->chip_id >= T3LPB) { @@ -1111,11 +1046,10 @@ __inline int reset_card_proc(PMINI_ADAPTER ps_adapter) err_exit : psIntfAdapter->psAdapter->StopAllXaction = FALSE ; -#endif return retval; } -__inline int run_card_proc(PMINI_ADAPTER ps_adapter ) +int run_card_proc(PMINI_ADAPTER ps_adapter ) { unsigned int value=0; { @@ -1148,19 +1082,15 @@ int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter) UINT status = STATUS_SUCCESS; UINT value = 0; -#ifdef BCM_SHM_INTERFACE - unsigned char *pConfigFileAddr = (unsigned char *)CPE_MACXVI_CFG_ADDR; -#endif /* * Create the threads first and then download the * Firm/DDR Settings.. */ - if((status = create_worker_threads(ps_adapter))<0) - { - BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Cannot create thread"); + status = create_worker_threads(ps_adapter); + if (status<0) return status; - } + /* * For Downloading the Firm, parse the cfg file first. */ @@ -1169,7 +1099,6 @@ int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter) return status; } -#ifndef BCM_SHM_INTERFACE if(ps_adapter->chip_id >= T3LPB) { rdmalt(ps_adapter, SYS_CFG, &value, sizeof (value)); @@ -1187,7 +1116,7 @@ int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter) status = ddr_init(ps_adapter); if(status) { - BCM_DEBUG_PRINT (ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "ddr_init Failed\n"); + pr_err(DRV_NAME "ddr_init Failed\n"); return status; } @@ -1201,7 +1130,6 @@ int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter) BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Error downloading CFG file"); goto OUT; } - BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "CFG file downloaded"); if(register_networkdev(ps_adapter)) { @@ -1266,12 +1194,6 @@ int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter) goto OUT; } } -#if 0 - else if(psAdapter->eNVMType == NVM_EEPROM) - { - PropagateCalParamsFromEEPROMToMemory(); - } -#endif /* Download Firmare */ if ((status = BcmFileDownload( ps_adapter, BIN_FILE, FIRMWARE_BEGIN_ADDR))) @@ -1280,7 +1202,6 @@ int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter) goto OUT; } - BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "BIN file downloaded"); status = run_card_proc(ps_adapter); if(status) { @@ -1299,61 +1220,12 @@ int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter) wake_up(&ps_adapter->LEDInfo.notify_led_event); } -#else - - ps_adapter->bDDRInitDone = TRUE; - //Initializing the NVM. - BcmInitNVM(ps_adapter); - - //Propagating the cal param from Flash to DDR - value = 0; - wrmalt(ps_adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value)); - wrmalt(ps_adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value)); - - if(ps_adapter->eNVMType == NVM_FLASH) - { - status = PropagateCalParamsFromFlashToMemory(ps_adapter); - if(status) - { - printk("\nPropogation of Cal param from flash to DDR failed ..\n" ); - } - } - - //Copy config file param to DDR. - memcpy(pConfigFileAddr,ps_adapter->pstargetparams, sizeof(STARGETPARAMS)); - - if(register_networkdev(ps_adapter)) - { - BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Netdevice failed. Cleanup needs to be performed."); - return -EIO; - } - - - status = InitLedSettings (ps_adapter); - if(status) - { - BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_PRINTK, 0, 0,"INIT LED FAILED\n"); - return status; - } - - - if(register_control_device_interface(ps_adapter) < 0) - { - BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Control Device failed. Cleanup needs to be performed."); - return -EIO; - } - - ps_adapter->fw_download_done = TRUE; -#endif return status; } -int bcm_parse_target_params(PMINI_ADAPTER Adapter) +static int bcm_parse_target_params(PMINI_ADAPTER Adapter) { -#ifdef BCM_SHM_INTERFACE - extern void read_cfg_file(PMINI_ADAPTER Adapter); -#endif struct file *flp=NULL; mm_segment_t oldfs={0}; char *buff = NULL; @@ -1368,14 +1240,14 @@ int bcm_parse_target_params(PMINI_ADAPTER Adapter) if((Adapter->pstargetparams = kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL)) == NULL) { - bcm_kfree(buff); + kfree(buff); return -ENOMEM; } flp=open_firmware_file(Adapter, CFG_FILE); if(!flp) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "NOT ABLE TO OPEN THE %s FILE \n", CFG_FILE); - bcm_kfree(buff); - bcm_kfree(Adapter->pstargetparams); + kfree(buff); + kfree(Adapter->pstargetparams); Adapter->pstargetparams = NULL; return -ENOENT; } @@ -1386,8 +1258,8 @@ int bcm_parse_target_params(PMINI_ADAPTER Adapter) if(len != sizeof(STARGETPARAMS)) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Mismatch in Target Param Structure!\n"); - bcm_kfree(buff); - bcm_kfree(Adapter->pstargetparams); + kfree(buff); + kfree(Adapter->pstargetparams); Adapter->pstargetparams = NULL; filp_close(flp, current->files); return -ENOENT; @@ -1399,12 +1271,8 @@ int bcm_parse_target_params(PMINI_ADAPTER Adapter) * Values in Adapter->pstargetparams are in network byte order */ memcpy(Adapter->pstargetparams, buff, sizeof(STARGETPARAMS)); - bcm_kfree (buff); + kfree (buff); beceem_parse_target_struct(Adapter); -#ifdef BCM_SHM_INTERFACE - read_cfg_file(Adapter); - -#endif return STATUS_SUCCESS; } @@ -1414,22 +1282,23 @@ void beceem_parse_target_struct(PMINI_ADAPTER Adapter) if(ntohl(Adapter->pstargetparams->m_u32PhyParameter2) & AUTO_SYNC_DISABLE) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "AutoSyncup is Disabled\n"); + pr_info(DRV_NAME ": AutoSyncup is Disabled\n"); Adapter->AutoSyncup = FALSE; } else { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "AutoSyncup is Enabled\n"); + pr_info(DRV_NAME ": AutoSyncup is Enabled\n"); Adapter->AutoSyncup = TRUE; } + if(ntohl(Adapter->pstargetparams->HostDrvrConfig6) & AUTO_LINKUP_ENABLE) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Enabling autolink up"); + pr_info(DRV_NAME ": Enabling autolink up"); Adapter->AutoLinkUp = TRUE; } else { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Disabling autolink up"); + pr_info(DRV_NAME ": Disabling autolink up"); Adapter->AutoLinkUp = FALSE; } // Setting the DDR Setting.. @@ -1438,59 +1307,54 @@ void beceem_parse_target_struct(PMINI_ADAPTER Adapter) Adapter->ulPowerSaveMode = (ntohl(Adapter->pstargetparams->HostDrvrConfig6)>>12)&0x0F; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "DDR Setting: %x\n", Adapter->DDRSetting); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT,DBG_LVL_ALL, "Power Save Mode: %lx\n", - Adapter->ulPowerSaveMode); + pr_info(DRV_NAME ": DDR Setting: %x\n", Adapter->DDRSetting); + pr_info(DRV_NAME ": Power Save Mode: %lx\n", Adapter->ulPowerSaveMode); if(ntohl(Adapter->pstargetparams->HostDrvrConfig6) & AUTO_FIRM_DOWNLOAD) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Enabling Auto Firmware Download\n"); + pr_info(DRV_NAME ": Enabling Auto Firmware Download\n"); Adapter->AutoFirmDld = TRUE; } else { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Disabling Auto Firmware Download\n"); + pr_info(DRV_NAME ": Disabling Auto Firmware Download\n"); Adapter->AutoFirmDld = FALSE; } uiHostDrvrCfg6 = ntohl(Adapter->pstargetparams->HostDrvrConfig6); Adapter->bMipsConfig = (uiHostDrvrCfg6>>20)&0x01; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"MIPSConfig : 0x%X\n",Adapter->bMipsConfig); + pr_info(DRV_NAME ": MIPSConfig : 0x%X\n",Adapter->bMipsConfig); //used for backward compatibility. Adapter->bDPLLConfig = (uiHostDrvrCfg6>>19)&0x01; Adapter->PmuMode= (uiHostDrvrCfg6 >> 24 ) & 0x03; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "PMU MODE: %x", Adapter->PmuMode); + pr_info(DRV_NAME ": PMU MODE: %x", Adapter->PmuMode); if((uiHostDrvrCfg6 >> HOST_BUS_SUSPEND_BIT ) & (0x01)) { Adapter->bDoSuspend = TRUE; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Making DoSuspend TRUE as per configFile"); + pr_info(DRV_NAME ": Making DoSuspend TRUE as per configFile"); } uiEEPROMFlag = ntohl(Adapter->pstargetparams->m_u32EEPROMFlag); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "uiEEPROMFlag : 0x%X\n",uiEEPROMFlag); + pr_info(DRV_NAME ": uiEEPROMFlag : 0x%X\n",uiEEPROMFlag); Adapter->eNVMType = (NVM_TYPE)((uiEEPROMFlag>>4)&0x3); - Adapter->bStatusWrite = (uiEEPROMFlag>>6)&0x1; - //printk(("bStatusWrite : 0x%X\n", Adapter->bStatusWrite)); Adapter->uiSectorSizeInCFG = 1024*(0xFFFF & ntohl(Adapter->pstargetparams->HostDrvrConfig4)); - //printk(("uiSectorSize : 0x%X\n", Adapter->uiSectorSizeInCFG)); Adapter->bSectorSizeOverride =(bool) ((ntohl(Adapter->pstargetparams->HostDrvrConfig4))>>16)&0x1; - //printk(MP_INIT,("bSectorSizeOverride : 0x%X\n",Adapter->bSectorSizeOverride)); if(ntohl(Adapter->pstargetparams->m_u32PowerSavingModeOptions) &0x01) Adapter->ulPowerSaveMode = DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE; - //autocorrection part + if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) doPowerAutoCorrection(Adapter); } -VOID doPowerAutoCorrection(PMINI_ADAPTER psAdapter) +static VOID doPowerAutoCorrection(PMINI_ADAPTER psAdapter) { - UINT reporting_mode = 0; + UINT reporting_mode; reporting_mode = ntohl(psAdapter->pstargetparams->m_u32PowerSavingModeOptions) &0x02 ; psAdapter->bIsAutoCorrectEnabled = !((char)(psAdapter->ulPowerSaveMode >> 3) & 0x1); @@ -1504,20 +1368,9 @@ VOID doPowerAutoCorrection(PMINI_ADAPTER psAdapter) if (psAdapter->bIsAutoCorrectEnabled && (psAdapter->chip_id >= T3LPB)) { //If reporting mode is enable, switch PMU to PMC - #if 0 - if(reporting_mode == FALSE) - { - psAdapter->ulPowerSaveMode = DEVICE_POWERSAVE_MODE_AS_PMU_SHUTDOWN; - psAdapter->bDoSuspend = TRUE; - BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"PMU selected ...."); - - } - else - #endif { psAdapter->ulPowerSaveMode = DEVICE_POWERSAVE_MODE_AS_PMU_CLOCK_GATING; psAdapter->bDoSuspend =FALSE; - BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"PMC selected.."); } @@ -1558,7 +1411,7 @@ static unsigned char *ReadMacAddrEEPROM(PMINI_ADAPTER Adapter, ulong dwAddress) if(status != STATUS_SUCCESS) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm Failed..\n"); - bcm_kfree(pucmacaddr); + kfree(pucmacaddr); pucmacaddr = NULL; goto OUT; } @@ -1568,7 +1421,7 @@ static unsigned char *ReadMacAddrEEPROM(PMINI_ADAPTER Adapter, ulong dwAddress) if(status != STATUS_SUCCESS) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm Failed..\n"); - bcm_kfree(pucmacaddr); + kfree(pucmacaddr); pucmacaddr = NULL; goto OUT; } @@ -1580,43 +1433,6 @@ static unsigned char *ReadMacAddrEEPROM(PMINI_ADAPTER Adapter, ulong dwAddress) } #endif -#if 0 -INT ReadMacAddressFromEEPROM(PMINI_ADAPTER Adapter) -{ - unsigned char *puMacAddr = NULL; - int i =0; - - puMacAddr = ReadMacAddrEEPROM(Adapter,0x200); - if(!puMacAddr) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Couldn't retrieve the Mac Address\n"); - return STATUS_FAILURE; - } - else - { - if((puMacAddr[0] == 0x0 && puMacAddr[1] == 0x0 && - puMacAddr[2] == 0x0 && puMacAddr[3] == 0x0 && - puMacAddr[4] == 0x0 && puMacAddr[5] == 0x0) || - (puMacAddr[0] == 0xFF && puMacAddr[1] == 0xFF && - puMacAddr[2] == 0xFF && puMacAddr[3] == 0xFF && - puMacAddr[4] == 0xFF && puMacAddr[5] == 0xFF)) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Invalid Mac Address\n"); - bcm_kfree(puMacAddr); - return STATUS_FAILURE; - } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "The Mac Address received is: \n"); - memcpy(Adapter->dev->dev_addr, puMacAddr, MAC_ADDRESS_SIZE); - for(i=0;idev->dev_addr[i]); - } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"\n"); - bcm_kfree(puMacAddr); - } - return STATUS_SUCCESS; -} -#endif static void convertEndian(B_UINT8 rwFlag, PUINT puiBuffer, UINT uiByteCount) { @@ -1640,81 +1456,21 @@ int rdm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) { INT uiRetVal =0; -#ifndef BCM_SHM_INTERFACE uiRetVal = Adapter->interface_rdm(Adapter->pvInterfaceAdapter, uiAddress, pucBuff, sSize); if(uiRetVal < 0) return uiRetVal; -#else - int indx; - uiRetVal = STATUS_SUCCESS; - if(uiAddress & 0x10000000) { - // DDR Memory Access - uiAddress |= CACHE_ADDRESS_MASK; - memcpy(pucBuff,(unsigned char *)uiAddress ,sSize); - } - else { - // Register, SPRAM, Flash - uiAddress |= UNCACHE_ADDRESS_MASK; - if ((uiAddress & FLASH_ADDR_MASK) == (FLASH_CONTIGIOUS_START_ADDR_BCS350 & FLASH_ADDR_MASK)) - { - #if defined(FLASH_DIRECT_ACCESS) - memcpy(pucBuff,(unsigned char *)uiAddress ,sSize); - #else - printk("\nInvalid GSPI ACCESS :Addr :%#X", uiAddress); - uiRetVal = STATUS_FAILURE; - #endif - } - else if(((unsigned int )uiAddress & 0x3) || - ((unsigned int )pucBuff & 0x3) || - ((unsigned int )sSize & 0x3)) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"rdmalt :unalligned register access uiAddress = %x,pucBuff = %x size = %x\n",(unsigned int )uiAddress,(unsigned int )pucBuff,(unsigned int )sSize); - uiRetVal = STATUS_FAILURE; - } - else { - for (indx=0;indxinterface_wrm(Adapter->pvInterfaceAdapter, uiAddress, pucBuff, sSize); -#else - int indx; - if(uiAddress & 0x10000000) { - // DDR Memory Access - uiAddress |= CACHE_ADDRESS_MASK; - memcpy((unsigned char *)(uiAddress),pucBuff,sSize); - } - else { - // Register, SPRAM, Flash - uiAddress |= UNCACHE_ADDRESS_MASK; - - if(((unsigned int )uiAddress & 0x3) || - ((unsigned int )pucBuff & 0x3) || - ((unsigned int )sSize & 0x3)) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"wrmalt: unalligned register access uiAddress = %x,pucBuff = %x size = %x\n",(unsigned int )uiAddress,(unsigned int )pucBuff,(unsigned int )sSize); - iRetVal = STATUS_FAILURE; - } - else { - for (indx=0;indxrdmwrmsync); - if((Adapter->IdleMode == TRUE) || - (Adapter->bShutStatus ==TRUE) || - (Adapter->bPreparingForLowPowerMode ==TRUE)) - { - status = -EACCES; - goto exit; - } - - status = rdm(Adapter, uiAddress, pucBuff, sSize); - -exit: - up(&Adapter->rdmwrmsync); - return status ; -} int wrmWithLock(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) { INT status = STATUS_SUCCESS ; @@ -1921,10 +1658,8 @@ static VOID SendShutModeResponse(PMINI_ADAPTER Adapter) Adapter->bPreparingForLowPowerMode = TRUE; up(&Adapter->rdmwrmsync); //Killing all URBS. -#ifndef BCM_SHM_INTERFACE if(Adapter->bDoSuspend == TRUE) Bcm_kill_all_URBs((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); -#endif } else { @@ -1943,14 +1678,12 @@ static VOID SendShutModeResponse(PMINI_ADAPTER Adapter) BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL,"fail to send the Idle mode Request \n"); Adapter->bPreparingForLowPowerMode = FALSE; -#ifndef BCM_SHM_INTERFACE StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); -#endif } } -void HandleShutDownModeRequest(PMINI_ADAPTER Adapter,PUCHAR pucBuffer) +static void HandleShutDownModeRequest(PMINI_ADAPTER Adapter,PUCHAR pucBuffer) { B_UINT32 uiResetValue = 0; @@ -2077,11 +1810,7 @@ void update_per_sf_desc_cnts( PMINI_ADAPTER Adapter) if(!atomic_read (&Adapter->uiMBupdate)) return; -#ifdef BCM_SHM_INTERFACE - if(rdmalt(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (PUINT)uibuff, sizeof(UINT) * MAX_TARGET_DSX_BUFFERS)<0) -#else if(rdmaltWithLock(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (PUINT)uibuff, sizeof(UINT) * MAX_TARGET_DSX_BUFFERS)<0) -#endif { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed\n"); return; @@ -2107,9 +1836,7 @@ void update_per_sf_desc_cnts( PMINI_ADAPTER Adapter) void flush_queue(PMINI_ADAPTER Adapter, UINT iQIndex) { struct sk_buff* PacketToDrop=NULL; - struct net_device_stats* netstats=NULL; - - netstats = &((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats; + struct net_device_stats* netstats = &Adapter->dev->stats; spin_lock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock); @@ -2130,25 +1857,23 @@ void flush_queue(PMINI_ADAPTER Adapter, UINT iQIndex) Adapter->PackInfo[iQIndex].uiDroppedCountBytes += PacketToDrop->len; Adapter->PackInfo[iQIndex].uiDroppedCountPackets++; - bcm_kfree_skb(PacketToDrop); + dev_kfree_skb(PacketToDrop); atomic_dec(&Adapter->TotalPacketCount); - atomic_inc(&Adapter->TxDroppedPacketCount); - } } spin_unlock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock); } -void beceem_protocol_reset (PMINI_ADAPTER Adapter) +static void beceem_protocol_reset (PMINI_ADAPTER Adapter) { - int i =0; + int i; - if(NULL != Adapter->dev) - { - netif_carrier_off(Adapter->dev); - netif_stop_queue(Adapter->dev); - } + if (netif_msg_link(Adapter)) + pr_notice(PFX "%s: protocol reset\n", Adapter->dev->name); + + netif_carrier_off(Adapter->dev); + netif_stop_queue(Adapter->dev); Adapter->IdleMode = FALSE; Adapter->LinkUpStatus = FALSE; @@ -2166,78 +1891,18 @@ void beceem_protocol_reset (PMINI_ADAPTER Adapter) Adapter->TimerActive = FALSE; memset(Adapter->astFragmentedPktClassifierTable, 0, - sizeof(S_FRAGMENTED_PACKET_INFO) * - MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES); + sizeof(S_FRAGMENTED_PACKET_INFO) * MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES); for(i = 0;iPackInfo[i],0,sizeof(S_MIBS_SERVICEFLOW_TABLE)); + memset(&Adapter->PackInfo[i].stMibsExtServiceFlowTable, + 0, sizeof(S_MIBS_EXTSERVICEFLOW_PARAMETERS)); } } -#ifdef BCM_SHM_INTERFACE - - -#define GET_GTB_DIFF(start, end) \ -( (start) < (end) )? ( (end) - (start) ) : ( ~0x0 - ( (start) - (end)) +1 ) - -void usdelay ( unsigned int a) { - unsigned int start= *(unsigned int *)0xaf8051b4; - unsigned int end = start+1; - unsigned int diff = 0; - - while(1) { - end = *(unsigned int *)0xaf8051b4; - diff = (GET_GTB_DIFF(start,end))/80; - if (diff >= a) - break; - } -} -void read_cfg_file(PMINI_ADAPTER Adapter) { - - - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Config File Version = 0x%x \n",Adapter->pstargetparams->m_u32CfgVersion ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Center Frequency = 0x%x \n",Adapter->pstargetparams->m_u32CenterFrequency ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Band A Scan = 0x%x \n",Adapter->pstargetparams->m_u32BandAScan ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Band B Scan = 0x%x \n",Adapter->pstargetparams->m_u32BandBScan ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Band C Scan = 0x%x \n",Adapter->pstargetparams->m_u32BandCScan ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"ERTPS Options = 0x%x \n",Adapter->pstargetparams->m_u32ErtpsOptions ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"PHS Enable = 0x%x \n",Adapter->pstargetparams->m_u32PHSEnable ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Handoff Enable = 0x%x \n",Adapter->pstargetparams->m_u32HoEnable ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"HO Reserved1 = 0x%x \n",Adapter->pstargetparams->m_u32HoReserved1 ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"HO Reserved2 = 0x%x \n",Adapter->pstargetparams->m_u32HoReserved2 ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"MIMO Enable = 0x%x \n",Adapter->pstargetparams->m_u32MimoEnable ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"PKMv2 Enable = 0x%x \n",Adapter->pstargetparams->m_u32SecurityEnable ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Powersaving Modes Enable = 0x%x \n",Adapter->pstargetparams->m_u32PowerSavingModesEnable ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Power Saving Mode Options = 0x%x \n",Adapter->pstargetparams->m_u32PowerSavingModeOptions ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"ARQ Enable = 0x%x \n",Adapter->pstargetparams->m_u32ArqEnable ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Harq Enable = 0x%x \n",Adapter->pstargetparams->m_u32HarqEnable ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"EEPROM Flag = 0x%x \n",Adapter->pstargetparams->m_u32EEPROMFlag ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Customize = 0x%x \n",Adapter->pstargetparams->m_u32Customize ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Bandwidth = 0x%x \n",Adapter->pstargetparams->m_u32ConfigBW ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"ShutDown Timer Value = 0x%x \n",Adapter->pstargetparams->m_u32ShutDownInitThresholdTimer ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"RadioParameter = 0x%x \n",Adapter->pstargetparams->m_u32RadioParameter ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"PhyParameter1 = 0x%x \n",Adapter->pstargetparams->m_u32PhyParameter1 ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"PhyParameter2 = 0x%x \n",Adapter->pstargetparams->m_u32PhyParameter2 ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"PhyParameter3 = 0x%x \n",Adapter->pstargetparams->m_u32PhyParameter3 ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"m_u32TestOptions = 0x%x \n",Adapter->pstargetparams->m_u32TestOptions ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"MaxMACDataperDLFrame = 0x%x \n",Adapter->pstargetparams->m_u32MaxMACDataperDLFrame ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"MaxMACDataperULFrame = 0x%x \n",Adapter->pstargetparams->m_u32MaxMACDataperULFrame ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Corr2MacFlags = 0x%x \n",Adapter->pstargetparams->m_u32Corr2MacFlags ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"HostDrvrConfig1 = 0x%x \n",Adapter->pstargetparams->HostDrvrConfig1 ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"HostDrvrConfig2 = 0x%x \n",Adapter->pstargetparams->HostDrvrConfig2 ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"HostDrvrConfig3 = 0x%x \n",Adapter->pstargetparams->HostDrvrConfig3 ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"HostDrvrConfig4 = 0x%x \n",Adapter->pstargetparams->HostDrvrConfig4 ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"HostDrvrConfig5 = 0x%x \n",Adapter->pstargetparams->HostDrvrConfig5 ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"HostDrvrConfig6 = 0x%x \n",Adapter->pstargetparams->HostDrvrConfig6 ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Segmented PUSC Enable = 0x%x \n",Adapter->pstargetparams->m_u32SegmentedPUSCenable ); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"BamcEnable = 0x%x \n",Adapter->pstargetparams->m_u32BandAMCEnable ); -} - -#endif diff --git a/trunk/drivers/staging/bcm/Osal_Misc.c b/trunk/drivers/staging/bcm/Osal_Misc.c deleted file mode 100644 index feefd20a5291..000000000000 --- a/trunk/drivers/staging/bcm/Osal_Misc.c +++ /dev/null @@ -1,27 +0,0 @@ - /*++ - - Copyright (c) Beceem Communications Inc. - - Module Name: - WIN_Misc.c - - Abstract: - Implements the Miscelanneous OS Construts - Linked Lists - Dispatcher Objects(Events,Semaphores,Spin Locks and the like) - Files - - Revision History: - Who When What - -------- -------- ---------------------------------------------- - Name Date Created/reviewed/modified - Rajeev 24/1/08 Created - Notes: - - --*/ -#include "headers.h" - -bool OsalMemCompare(void *dest, void *src, UINT len) -{ - return (memcmp(src, dest, len)); -} diff --git a/trunk/drivers/staging/bcm/PHSModule.c b/trunk/drivers/staging/bcm/PHSModule.c index 8a38cf43e795..d1ca1912a74b 100644 --- a/trunk/drivers/staging/bcm/PHSModule.c +++ b/trunk/drivers/staging/bcm/PHSModule.c @@ -1,10 +1,54 @@ #include "headers.h" +static UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid,B_UINT16 uiClsId,S_SERVICEFLOW_TABLE *psServiceFlowTable,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI); + +static UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid,B_UINT16 uiClsId,S_SERVICEFLOW_ENTRY *pstServiceFlowEntry,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI); + +static UINT CreateClassifierPHSRule(B_UINT16 uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,B_UINT8 u8AssociatedPHSI); + +static UINT UpdateClassifierPHSRule(B_UINT16 uiClsId,S_CLASSIFIER_ENTRY *pstClassifierEntry,S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI); + +static BOOLEAN ValidatePHSRuleComplete(S_PHS_RULE *psPhsRule); + +static BOOLEAN DerefPhsRule(B_UINT16 uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable,S_PHS_RULE *pstPhsRule); + +static UINT GetClassifierEntry(S_CLASSIFIER_TABLE *pstClassifierTable,B_UINT32 uiClsid,E_CLASSIFIER_ENTRY_CONTEXT eClsContext, S_CLASSIFIER_ENTRY **ppstClassifierEntry); + +static UINT GetPhsRuleEntry(S_CLASSIFIER_TABLE *pstClassifierTable,B_UINT32 uiPHSI,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,S_PHS_RULE **ppstPhsRule); + +static void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable); + +static int phs_compress(S_PHS_RULE *phs_members,unsigned char *in_buf, + unsigned char *out_buf,unsigned int *header_size,UINT *new_header_size ); + + +static int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer, + unsigned char *phsf,unsigned char *phsm,unsigned int phss,unsigned int phsv,UINT *new_header_size ); + +static int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,\ + S_PHS_RULE *phs_rules,UINT *header_size); + + +static ULONG PhsCompress(void* pvContext, + B_UINT16 uiVcid, + B_UINT16 uiClsId, + void *pvInputBuffer, + void *pvOutputBuffer, + UINT *pOldHeaderSize, + UINT *pNewHeaderSize ); + +static ULONG PhsDeCompress(void* pvContext, + B_UINT16 uiVcid, + void *pvInputBuffer, + void *pvOutputBuffer, + UINT *pInHeaderSize, + UINT *pOutHeaderSize); + + + #define IN #define OUT -void DumpDataPacketHeader(PUCHAR pPkt); - /* Function: PHSTransmit @@ -81,8 +125,6 @@ int PHSTransmit(PMINI_ADAPTER Adapter, { - //DumpDataPacketHeader(pucPHSPktHdrInBuf); - // Step 2 Supress Header using PHS and fill into intermediate ucaPHSPktHdrOutBuf. // Suppress only if IP Header and PHS Enabled For the Service Flow if(((usPacketType == ETHERNET_FRAMETYPE_IPV4) || @@ -120,15 +162,15 @@ int PHSTransmit(PMINI_ADAPTER Adapter, if(newPacket == NULL) return STATUS_FAILURE; - bcm_kfree_skb(Packet); + dev_kfree_skb(Packet); *pPacket = Packet = newPacket; pucPHSPktHdrInBuf = Packet->data + BytesToRemove; } numBytesCompressed = unPhsOldHdrSize - (unPHSNewPktHeaderLen+PHSI_LEN); - OsalMemMove(pucPHSPktHdrInBuf + numBytesCompressed, pucPHSPktHdrOutBuf, unPHSNewPktHeaderLen + PHSI_LEN); - OsalMemMove(Packet->data + numBytesCompressed, Packet->data, BytesToRemove); + memcpy(pucPHSPktHdrInBuf + numBytesCompressed, pucPHSPktHdrOutBuf, unPHSNewPktHeaderLen + PHSI_LEN); + memcpy(Packet->data + numBytesCompressed, Packet->data, BytesToRemove); skb_pull(Packet, numBytesCompressed); return STATUS_SUCCESS; @@ -223,23 +265,12 @@ int PHSRecieve(PMINI_ADAPTER Adapter, } } - OsalMemMove(packet->data, Adapter->ucaPHSPktRestoreBuf, nStandardPktHdrLen); + memcpy(packet->data, Adapter->ucaPHSPktRestoreBuf, nStandardPktHdrLen); } return STATUS_SUCCESS; } -void DumpDataPacketHeader(PUCHAR pPkt) -{ - struct iphdr *iphd = (struct iphdr*)pPkt; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Phs Send/Recieve : IP Packet Hdr \n"); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"TOS : %x \n",iphd->tos); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Src IP : %x \n",iphd->saddr); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Dest IP : %x \n \n",iphd->daddr); - -} - void DumpFullPacket(UCHAR *pBuf,UINT nPktLen) { PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); @@ -270,15 +301,9 @@ int phs_init(PPHS_DEVICE_EXTENSION pPhsdeviceExtension,PMINI_ADAPTER Adapter) return -EINVAL; pPhsdeviceExtension->pstServiceFlowPhsRulesTable = - (S_SERVICEFLOW_TABLE*)OsalMemAlloc(sizeof(S_SERVICEFLOW_TABLE), - PHS_MEM_TAG); + kzalloc(sizeof(S_SERVICEFLOW_TABLE), GFP_KERNEL); - if(pPhsdeviceExtension->pstServiceFlowPhsRulesTable) - { - OsalZeroMemory(pPhsdeviceExtension->pstServiceFlowPhsRulesTable, - sizeof(S_SERVICEFLOW_TABLE)); - } - else + if(!pPhsdeviceExtension->pstServiceFlowPhsRulesTable) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation ServiceFlowPhsRulesTable failed"); return -ENOMEM; @@ -288,14 +313,8 @@ int phs_init(PPHS_DEVICE_EXTENSION pPhsdeviceExtension,PMINI_ADAPTER Adapter) for(i=0;istSFList[i]; - sServiceFlow.pstClassifierTable = (S_CLASSIFIER_TABLE*)OsalMemAlloc( - sizeof(S_CLASSIFIER_TABLE), PHS_MEM_TAG); - if(sServiceFlow.pstClassifierTable) - { - OsalZeroMemory(sServiceFlow.pstClassifierTable,sizeof(S_CLASSIFIER_TABLE)); - pstServiceFlowTable->stSFList[i].pstClassifierTable = sServiceFlow.pstClassifierTable; - } - else + sServiceFlow.pstClassifierTable = kzalloc(sizeof(S_CLASSIFIER_TABLE), GFP_KERNEL); + if(!sServiceFlow.pstClassifierTable) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed"); free_phs_serviceflow_rules(pPhsdeviceExtension-> @@ -305,9 +324,7 @@ int phs_init(PPHS_DEVICE_EXTENSION pPhsdeviceExtension,PMINI_ADAPTER Adapter) } } - - pPhsdeviceExtension->CompressedTxBuffer = - OsalMemAlloc(PHS_BUFFER_SIZE,PHS_MEM_TAG); + pPhsdeviceExtension->CompressedTxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL); if(pPhsdeviceExtension->CompressedTxBuffer == NULL) { @@ -317,12 +334,11 @@ int phs_init(PPHS_DEVICE_EXTENSION pPhsdeviceExtension,PMINI_ADAPTER Adapter) return -ENOMEM; } - pPhsdeviceExtension->UnCompressedRxBuffer = - OsalMemAlloc(PHS_BUFFER_SIZE,PHS_MEM_TAG); + pPhsdeviceExtension->UnCompressedRxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL); if(pPhsdeviceExtension->UnCompressedRxBuffer == NULL) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed"); - OsalMemFree(pPhsdeviceExtension->CompressedTxBuffer,PHS_BUFFER_SIZE); + kfree(pPhsdeviceExtension->CompressedTxBuffer); free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable); pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL; return -ENOMEM; @@ -343,16 +359,11 @@ int PhsCleanup(IN PPHS_DEVICE_EXTENSION pPHSDeviceExt) pPHSDeviceExt->pstServiceFlowPhsRulesTable = NULL; } - if(pPHSDeviceExt->CompressedTxBuffer) - { - OsalMemFree(pPHSDeviceExt->CompressedTxBuffer,PHS_BUFFER_SIZE); - pPHSDeviceExt->CompressedTxBuffer = NULL; - } - if(pPHSDeviceExt->UnCompressedRxBuffer) - { - OsalMemFree(pPHSDeviceExt->UnCompressedRxBuffer,PHS_BUFFER_SIZE); - pPHSDeviceExt->UnCompressedRxBuffer = NULL; - } + kfree(pPHSDeviceExt->CompressedTxBuffer); + pPHSDeviceExt->CompressedTxBuffer = NULL; + + kfree(pPHSDeviceExt->UnCompressedRxBuffer); + pPHSDeviceExt->UnCompressedRxBuffer = NULL; return 0; } @@ -478,20 +489,12 @@ ULONG PhsDeletePHSRule(IN void* pvContext,IN B_UINT16 uiVcid,IN B_UINT8 u8PHSI) { if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].bUsed && pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule) { - if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex] - .pstPhsRule->u8PHSI == u8PHSI) - { - if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule - ->u8RefCnt) - pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule - ->u8RefCnt--; - if(0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex] - .pstPhsRule->u8RefCnt) - OsalMemFree(pstClassifierRulesTable - ->stActivePhsRulesList[nClsidIndex].pstPhsRule, - sizeof(S_PHS_RULE)); - OsalZeroMemory(&pstClassifierRulesTable - ->stActivePhsRulesList[nClsidIndex], + if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8PHSI == u8PHSI) { + if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt) + pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--; + if(0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt) + kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule); + memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0, sizeof(S_CLASSIFIER_ENTRY)); } } @@ -548,10 +551,10 @@ ULONG PhsDeleteClassifierRule(IN void* pvContext,IN B_UINT16 uiVcid ,IN B_UINT16 if(pstClassifierEntry->pstPhsRule->u8RefCnt) pstClassifierEntry->pstPhsRule->u8RefCnt--; if(0==pstClassifierEntry->pstPhsRule->u8RefCnt) - OsalMemFree(pstClassifierEntry->pstPhsRule,sizeof(S_PHS_RULE)); + kfree(pstClassifierEntry->pstPhsRule); } - OsalZeroMemory(pstClassifierEntry,sizeof(S_CLASSIFIER_ENTRY)); + memset(pstClassifierEntry, 0, sizeof(S_CLASSIFIER_ENTRY)); } nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable, @@ -559,10 +562,8 @@ ULONG PhsDeleteClassifierRule(IN void* pvContext,IN B_UINT16 uiVcid ,IN B_UINT16 if((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule)) { - if(pstClassifierEntry->pstPhsRule) - //Delete the classifier entry - OsalMemFree(pstClassifierEntry->pstPhsRule,sizeof(S_PHS_RULE)); - OsalZeroMemory(pstClassifierEntry,sizeof(S_CLASSIFIER_ENTRY)); + kfree(pstClassifierEntry->pstPhsRule); + memset(pstClassifierEntry, 0, sizeof(S_CLASSIFIER_ENTRY)); } } return lStatus; @@ -619,14 +620,11 @@ ULONG PhsDeleteSFRules(IN void* pvContext,IN B_UINT16 uiVcid) .pstPhsRule->u8RefCnt--; if(0==pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex] .pstPhsRule->u8RefCnt) - OsalMemFree(pstClassifierRulesTable - ->stActivePhsRulesList[nClsidIndex].pstPhsRule, - sizeof(S_PHS_RULE)); + kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule); pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex] .pstPhsRule = NULL; } - OsalZeroMemory(&pstClassifierRulesTable - ->stActivePhsRulesList[nClsidIndex],sizeof(S_CLASSIFIER_ENTRY)); + memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0, sizeof(S_CLASSIFIER_ENTRY)); if(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule) { if(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex] @@ -635,15 +633,12 @@ ULONG PhsDeleteSFRules(IN void* pvContext,IN B_UINT16 uiVcid) .pstPhsRule->u8RefCnt--; if(0 == pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex] .pstPhsRule->u8RefCnt) - OsalMemFree(pstClassifierRulesTable - ->stOldPhsRulesList[nClsidIndex].pstPhsRule, - sizeof(S_PHS_RULE)); + kfree(pstClassifierRulesTable + ->stOldPhsRulesList[nClsidIndex].pstPhsRule); pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex] .pstPhsRule = NULL; } - OsalZeroMemory(&pstClassifierRulesTable - ->stOldPhsRulesList[nClsidIndex], - sizeof(S_CLASSIFIER_ENTRY)); + memset(&pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex], 0, sizeof(S_CLASSIFIER_ENTRY)); } } pstServiceFlowEntry->bUsed = FALSE; @@ -849,7 +844,7 @@ ULONG PhsDeCompress(IN void* pvContext, // Does not return any value. //----------------------------------------------------------------------------- -void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable) +static void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable) { int i,j; PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); @@ -876,8 +871,7 @@ void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable) ->u8RefCnt--; if(0==pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule ->u8RefCnt) - OsalMemFree(pstClassifierRulesTable->stActivePhsRulesList[j]. - pstPhsRule, sizeof(S_PHS_RULE)); + kfree(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule); pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule = NULL; } if(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule) @@ -888,24 +882,23 @@ void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable) ->u8RefCnt--; if(0==pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule ->u8RefCnt) - OsalMemFree(pstClassifierRulesTable->stOldPhsRulesList[j] - .pstPhsRule,sizeof(S_PHS_RULE)); + kfree(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule); pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule = NULL; } } - OsalMemFree(pstClassifierRulesTable,sizeof(S_CLASSIFIER_TABLE)); + kfree(pstClassifierRulesTable); stServiceFlowEntry.pstClassifierTable = pstClassifierRulesTable = NULL; } } } - OsalMemFree(psServiceFlowRulesTable,sizeof(S_SERVICEFLOW_TABLE)); - psServiceFlowRulesTable = NULL; + kfree(psServiceFlowRulesTable); + psServiceFlowRulesTable = NULL; } -BOOLEAN ValidatePHSRuleComplete(IN S_PHS_RULE *psPhsRule) +static BOOLEAN ValidatePHSRuleComplete(IN S_PHS_RULE *psPhsRule) { if(psPhsRule) { @@ -988,9 +981,9 @@ UINT GetClassifierEntry(IN S_CLASSIFIER_TABLE *pstClassifierTable, return PHS_INVALID_TABLE_INDEX; } -UINT GetPhsRuleEntry(IN S_CLASSIFIER_TABLE *pstClassifierTable, - IN B_UINT32 uiPHSI,E_CLASSIFIER_ENTRY_CONTEXT eClsContext, - OUT S_PHS_RULE **ppstPhsRule) +static UINT GetPhsRuleEntry(IN S_CLASSIFIER_TABLE *pstClassifierTable, + IN B_UINT32 uiPHSI,E_CLASSIFIER_ENTRY_CONTEXT eClsContext, + OUT S_PHS_RULE **ppstPhsRule) { int i; S_CLASSIFIER_ENTRY *pstClassifierRule = NULL; @@ -1102,7 +1095,7 @@ UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid, if(psPhsRule->u8PHSFLength) { //update PHSF - OsalMemMove(pstClassifierEntry->pstPhsRule->u8PHSF, + memcpy(pstClassifierEntry->pstPhsRule->u8PHSF, psPhsRule->u8PHSF , MAX_PHS_LENGTHS); } if(psPhsRule->u8PHSFLength) @@ -1114,7 +1107,7 @@ UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid, if(psPhsRule->u8PHSMLength) { //update PHSM - OsalMemMove(pstClassifierEntry->pstPhsRule->u8PHSM, + memcpy(pstClassifierEntry->pstPhsRule->u8PHSM, psPhsRule->u8PHSM, MAX_PHS_LENGTHS); } if(psPhsRule->u8PHSMLength) @@ -1147,7 +1140,7 @@ UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid, return uiStatus; } -UINT CreateClassifierPHSRule(IN B_UINT16 uiClsId, +static UINT CreateClassifierPHSRule(IN B_UINT16 uiClsId, S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule, E_CLASSIFIER_ENTRY_CONTEXT eClsContext,B_UINT8 u8AssociatedPHSI) { @@ -1234,8 +1227,7 @@ UINT CreateClassifierPHSRule(IN B_UINT16 uiClsId, { if(psClassifierRules->pstPhsRule == NULL) { - psClassifierRules->pstPhsRule = (S_PHS_RULE*)OsalMemAlloc - (sizeof(S_PHS_RULE),PHS_MEM_TAG); + psClassifierRules->pstPhsRule = kmalloc(sizeof(S_PHS_RULE),GFP_KERNEL); if(NULL == psClassifierRules->pstPhsRule) return ERR_PHSRULE_MEMALLOC_FAIL; @@ -1247,7 +1239,7 @@ UINT CreateClassifierPHSRule(IN B_UINT16 uiClsId, psClassifierRules->bUnclassifiedPHSRule = psPhsRule->bUnclassifiedPHSRule; /* Update The PHS rule */ - OsalMemMove(psClassifierRules->pstPhsRule, + memcpy(psClassifierRules->pstPhsRule, psPhsRule, sizeof(S_PHS_RULE)); } else @@ -1259,7 +1251,7 @@ UINT CreateClassifierPHSRule(IN B_UINT16 uiClsId, } -UINT UpdateClassifierPHSRule(IN B_UINT16 uiClsId, +static UINT UpdateClassifierPHSRule(IN B_UINT16 uiClsId, IN S_CLASSIFIER_ENTRY *pstClassifierEntry, S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule, B_UINT8 u8AssociatedPHSI) @@ -1289,13 +1281,13 @@ UINT UpdateClassifierPHSRule(IN B_UINT16 uiClsId, //Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for uiClsId if(FALSE == bPHSRuleOrphaned) { - pstClassifierEntry->pstPhsRule = (S_PHS_RULE*)OsalMemAlloc(sizeof(S_PHS_RULE),PHS_MEM_TAG); + pstClassifierEntry->pstPhsRule = kmalloc(sizeof(S_PHS_RULE), GFP_KERNEL); if(NULL == pstClassifierEntry->pstPhsRule) { return ERR_PHSRULE_MEMALLOC_FAIL; } } - OsalMemMove(pstClassifierEntry->pstPhsRule, psPhsRule, sizeof(S_PHS_RULE)); + memcpy(pstClassifierEntry->pstPhsRule, psPhsRule, sizeof(S_PHS_RULE)); } else @@ -1304,14 +1296,8 @@ UINT UpdateClassifierPHSRule(IN B_UINT16 uiClsId, BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nTying Classifier to Existing PHS Rule"); if(bPHSRuleOrphaned) { - if(pstClassifierEntry->pstPhsRule) - { - //Just Free the PHS Rule as Ref Count is Zero - OsalMemFree(pstClassifierEntry->pstPhsRule,sizeof(S_PHS_RULE)); + kfree(pstClassifierEntry->pstPhsRule); pstClassifierEntry->pstPhsRule = NULL; - - } - } pstClassifierEntry->pstPhsRule = pstAddPhsRule; @@ -1326,7 +1312,7 @@ UINT UpdateClassifierPHSRule(IN B_UINT16 uiClsId, } -BOOLEAN DerefPhsRule(IN B_UINT16 uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable,S_PHS_RULE *pstPhsRule) +static BOOLEAN DerefPhsRule(IN B_UINT16 uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable,S_PHS_RULE *pstPhsRule) { if(pstPhsRule==NULL) return FALSE; @@ -1345,22 +1331,6 @@ BOOLEAN DerefPhsRule(IN B_UINT16 uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable } } -static void DumpBuffer(PVOID BuffVAddress, int xferSize) -{ - int i; - int iPrintLength; - PUCHAR temp=(PUCHAR)BuffVAddress; - PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); - iPrintLength=(xferSize<32?xferSize:32); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n"); - - for (i=0;i < iPrintLength;i++) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "%x|",temp[i]); - } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n"); -} - - void DumpPhsRules(PPHS_DEVICE_EXTENSION pDeviceExtension) { int i,j,k,l; @@ -1520,8 +1490,8 @@ int phs_decompress(unsigned char *in_buf,unsigned char *out_buf, // size-The number of bytes copied into the output buffer i.e dynamic fields // 0 -If PHS rule is NULL.If PHSV field is not set.If the verification fails. //----------------------------------------------------------------------------- -int phs_compress(S_PHS_RULE *phs_rule,unsigned char *in_buf - ,unsigned char *out_buf,UINT *header_size,UINT *new_header_size) +static int phs_compress(S_PHS_RULE *phs_rule,unsigned char *in_buf + ,unsigned char *out_buf,UINT *header_size,UINT *new_header_size) { unsigned char *old_addr = out_buf; int supress = 0; @@ -1581,9 +1551,9 @@ int phs_compress(S_PHS_RULE *phs_rule,unsigned char *in_buf // 0 -Packet has failed the verification. //----------------------------------------------------------------------------- - int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer, - unsigned char *phsf,unsigned char *phsm,unsigned int phss, - unsigned int phsv,UINT* new_header_size) +static int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer, + unsigned char *phsf,unsigned char *phsm,unsigned int phss, + unsigned int phsv,UINT* new_header_size) { unsigned int size=0; int bit,i=0; diff --git a/trunk/drivers/staging/bcm/PHSModule.h b/trunk/drivers/staging/bcm/PHSModule.h index bf2b5763252c..0dd05a7c55d9 100644 --- a/trunk/drivers/staging/bcm/PHSModule.h +++ b/trunk/drivers/staging/bcm/PHSModule.h @@ -27,19 +27,6 @@ void DumpPhsRules(PPHS_DEVICE_EXTENSION pDeviceExtension); int phs_init(PPHS_DEVICE_EXTENSION pPhsdeviceExtension,PMINI_ADAPTER Adapter); -void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable); - -int phs_compress(S_PHS_RULE *phs_members,unsigned char *in_buf, - unsigned char *out_buf,unsigned int *header_size,UINT *new_header_size ); - - -int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer, - unsigned char *phsf,unsigned char *phsm,unsigned int phss,unsigned int phsv,UINT *new_header_size ); - -int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,\ - S_PHS_RULE *phs_rules,UINT *header_size); - - int PhsCleanup(PPHS_DEVICE_EXTENSION pPHSDeviceExt); //Utility Functions @@ -52,42 +39,10 @@ ULONG PhsDeleteClassifierRule(void* pvContext, B_UINT16 uiVcid ,B_UINT16 uiClsI ULONG PhsDeleteSFRules(void* pvContext,B_UINT16 uiVcid) ; -ULONG PhsCompress(void* pvContext, - B_UINT16 uiVcid, - B_UINT16 uiClsId, - void *pvInputBuffer, - void *pvOutputBuffer, - UINT *pOldHeaderSize, - UINT *pNewHeaderSize ); - -ULONG PhsDeCompress(void* pvContext, - B_UINT16 uiVcid, - void *pvInputBuffer, - void *pvOutputBuffer, - UINT *pInHeaderSize, - UINT *pOutHeaderSize); - - BOOLEAN ValidatePHSRule(S_PHS_RULE *psPhsRule); -BOOLEAN ValidatePHSRuleComplete(S_PHS_RULE *psPhsRule); - UINT GetServiceFlowEntry(S_SERVICEFLOW_TABLE *psServiceFlowTable,B_UINT16 uiVcid,S_SERVICEFLOW_ENTRY **ppstServiceFlowEntry); -UINT GetClassifierEntry(S_CLASSIFIER_TABLE *pstClassifierTable,B_UINT32 uiClsid,E_CLASSIFIER_ENTRY_CONTEXT eClsContext, S_CLASSIFIER_ENTRY **ppstClassifierEntry); - -UINT GetPhsRuleEntry(S_CLASSIFIER_TABLE *pstClassifierTable,B_UINT32 uiPHSI,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,S_PHS_RULE **ppstPhsRule); - - -UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid,B_UINT16 uiClsId,S_SERVICEFLOW_TABLE *psServiceFlowTable,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI); - -UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid,B_UINT16 uiClsId,S_SERVICEFLOW_ENTRY *pstServiceFlowEntry,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI); - -UINT CreateClassifierPHSRule(B_UINT16 uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,B_UINT8 u8AssociatedPHSI); - -UINT UpdateClassifierPHSRule(B_UINT16 uiClsId,S_CLASSIFIER_ENTRY *pstClassifierEntry,S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI); - -BOOLEAN DerefPhsRule(B_UINT16 uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable,S_PHS_RULE *pstPhsRule); void DumpPhsRules(PPHS_DEVICE_EXTENSION pDeviceExtension); diff --git a/trunk/drivers/staging/bcm/Protocol.h b/trunk/drivers/staging/bcm/Protocol.h index 00f1cc12356a..b8a4009bdf0c 100644 --- a/trunk/drivers/staging/bcm/Protocol.h +++ b/trunk/drivers/staging/bcm/Protocol.h @@ -85,10 +85,10 @@ typedef struct _ETH_CS_ETH2_FRAME ETH_HEADER_STRUC EThHdr; } __attribute__((packed)) ETH_CS_ETH2_FRAME; +#define ETHERNET_FRAMETYPE_IPV4 ntohs(0x0800) +#define ETHERNET_FRAMETYPE_IPV6 ntohs(0x86dd) +#define ETHERNET_FRAMETYPE_802QVLAN ntohs(0x8100) -#define ETHERNET_FRAMETYPE_IPV4 ntohs(0x0800) -#define ETHERNET_FRAMETYPE_IPV6 ntohs(0x86dd) -#define ETHERNET_FRAMETYPE_802QVLAN 0x8100 //Per SF CS Specification Encodings typedef enum _E_SERVICEFLOW_CS_SPEC_ { diff --git a/trunk/drivers/staging/bcm/Prototypes.h b/trunk/drivers/staging/bcm/Prototypes.h index 70ec8bcafd1e..b80b806c90a3 100644 --- a/trunk/drivers/staging/bcm/Prototypes.h +++ b/trunk/drivers/staging/bcm/Prototypes.h @@ -1,23 +1,12 @@ #ifndef _PROTOTYPES_H_ #define _PROTOTYPES_H_ -int BcmFileDownload(PMINI_ADAPTER Adapter,/**< Logical Adapter */ - char *path, /**< path to image file */ - unsigned int loc /**< Download Address on the chip*/ - ); VOID LinkControlResponseMessage(PMINI_ADAPTER Adapter, PUCHAR pucBuffer); VOID StatisticsResponse(PMINI_ADAPTER Adapter,PVOID pvBuffer); VOID IdleModeResponse(PMINI_ADAPTER Adapter,PUINT puiBuffer); -void bcm_kfree_skb(struct sk_buff *skb); -VOID bcm_kfree(VOID *ptr); - - -VOID handle_rx_control_packet(PMINI_ADAPTER Adapter, /**protocol!=TCP && iphd->protocol!=UDP) break; -#if 0 - //check if memory is available of src and Dest port - if(ETH_AND_IP_HEADER_LEN + L4_SRC_PORT_LEN + L4_DEST_PORT_LEN > Packet->len) - { - //This is not an erroneous condition and pkt will be checked for next classification. - bClassificationSucceed = FALSE; - break; - } -#endif //******************Checking Transport Layer Header field if present *****************// BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source Port %04x", (iphd->protocol==UDP)?xprt_hdr->uhdr.source:xprt_hdr->thdr.source); @@ -312,29 +301,6 @@ USHORT IpVersion4(PMINI_ADAPTER Adapter, /**< Pointer to the driver control stru return bClassificationSucceed; } -/** -@ingroup tx_functions -@return Queue Index based on priority. -*/ -USHORT GetPacketQueueIndex(PMINI_ADAPTER Adapter, /**"); - - if(NULL==Adapter || NULL==Packet) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, QUEUE_INDEX, DBG_LVL_ALL, "Got NULL Values<======"); - return -1; - } - - usIndex = ClassifyPacket(Adapter,Packet); - - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, QUEUE_INDEX, DBG_LVL_ALL, "Got Queue Index %x",usIndex); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, QUEUE_INDEX, DBG_LVL_ALL, "GetPacketQueueIndex <=============="); - return usIndex; -} VOID PruneQueueAllSF(PMINI_ADAPTER Adapter) { @@ -357,23 +323,21 @@ is less than number of bytes in the queue. If so - drops packets from the Head till the number of bytes is less than or equal to max queue size for the queue. */ -VOID PruneQueue(PMINI_ADAPTER Adapter,/** Index %d",iIndex); if(iIndex == HiPriority) - return; + return; if(!Adapter || (iIndex < 0) || (iIndex > HiPriority)) return; /* To Store the netdevice statistic */ - netstats = &((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats; + netstats = &Adapter->dev->stats; spin_lock_bh(&Adapter->PackInfo[iIndex].SFQueueLock); @@ -395,9 +359,13 @@ VOID PruneQueue(PMINI_ADAPTER Adapter,/**tx_dropped++; - atomic_inc(&Adapter->TxDroppedPacketCount); + struct netdev_queue *txq = netdev_get_tx_queue(Adapter->dev, iIndex); + if (netif_msg_tx_err(Adapter)) + pr_info(PFX "%s: tx queue %d overlimit\n", + Adapter->dev->name, iIndex); + + txq->tx_dropped++; + DEQUEUEPACKET(Adapter->PackInfo[iIndex].FirstTxQueue, Adapter->PackInfo[iIndex].LastTxQueue); /// update current bytes and packets count @@ -407,7 +375,7 @@ VOID PruneQueue(PMINI_ADAPTER Adapter,/**PackInfo[iIndex].uiDroppedCountBytes += PacketToDrop->len; Adapter->PackInfo[iIndex].uiDroppedCountPackets++; - bcm_kfree_skb(PacketToDrop); + dev_kfree_skb(PacketToDrop); } @@ -416,7 +384,6 @@ VOID PruneQueue(PMINI_ADAPTER Adapter,/**PackInfo[iIndex].uiDroppedCountPackets); atomic_dec(&Adapter->TotalPacketCount); - Adapter->bcm_jiffies = jiffies; } spin_unlock_bh(&Adapter->PackInfo[iIndex].SFQueueLock); @@ -430,16 +397,15 @@ VOID flush_all_queues(PMINI_ADAPTER Adapter) { INT iQIndex; UINT uiTotalPacketLength; - struct sk_buff* PacketToDrop=NULL; - struct net_device_stats* netstats=NULL; + struct sk_buff* PacketToDrop=NULL; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "=====>"); - /* To Store the netdevice statistic */ - netstats = &((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats; // down(&Adapter->data_packet_queue_lock); for(iQIndex=LowPriority; iQIndexdev, iQIndex); + spin_lock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock); while(Adapter->PackInfo[iQIndex].FirstTxQueue) { @@ -447,8 +413,7 @@ VOID flush_all_queues(PMINI_ADAPTER Adapter) if(PacketToDrop) { uiTotalPacketLength = PacketToDrop->len; - netstats->tx_dropped++; - atomic_inc(&Adapter->TxDroppedPacketCount); + txq->tx_dropped++; } else uiTotalPacketLength = 0; @@ -457,7 +422,7 @@ VOID flush_all_queues(PMINI_ADAPTER Adapter) Adapter->PackInfo[iQIndex].LastTxQueue); /* Free the skb */ - bcm_kfree_skb(PacketToDrop); + dev_kfree_skb(PacketToDrop); /// update current bytes and packets count Adapter->PackInfo[iQIndex].uiCurrentBytesOnHost -= uiTotalPacketLength; @@ -559,12 +524,6 @@ USHORT ClassifyPacket(PMINI_ADAPTER Adapter,struct sk_buff* skb) for(uiLoopIndex = MAX_CLASSIFIERS - 1; uiLoopIndex >= 0; uiLoopIndex--) { - if (Adapter->device_removed) - { - bClassificationSucceed = FALSE; - break; - } - if(bClassificationSucceed) break; //Iterate through all classifiers which are already in order of priority @@ -810,7 +769,10 @@ static BOOLEAN EthCSMatchVLANRules(S_CLASSIFIER_RULE *pstClassifierRule,struct s } -BOOLEAN EThCSClassifyPkt(PMINI_ADAPTER Adapter,struct sk_buff* skb,PS_ETHCS_PKT_INFO pstEthCsPktInfo,S_CLASSIFIER_RULE *pstClassifierRule, B_UINT8 EthCSCupport) +static BOOLEAN EThCSClassifyPkt(PMINI_ADAPTER Adapter,struct sk_buff* skb, + PS_ETHCS_PKT_INFO pstEthCsPktInfo, + S_CLASSIFIER_RULE *pstClassifierRule, + B_UINT8 EthCSCupport) { BOOLEAN bClassificationSucceed = FALSE; bClassificationSucceed = EthCSMatchSrcMACAddress(pstClassifierRule,((ETH_HEADER_STRUC *)(skb->data))->au8SourceAddress); @@ -840,9 +802,11 @@ BOOLEAN EThCSClassifyPkt(PMINI_ADAPTER Adapter,struct sk_buff* skb,PS_ETHCS_PKT_ return bClassificationSucceed; } -void EThCSGetPktInfo(PMINI_ADAPTER Adapter,PVOID pvEthPayload,PS_ETHCS_PKT_INFO pstEthCsPktInfo) +static void EThCSGetPktInfo(PMINI_ADAPTER Adapter,PVOID pvEthPayload, + PS_ETHCS_PKT_INFO pstEthCsPktInfo) { USHORT u16Etype = ntohs(((ETH_HEADER_STRUC*)pvEthPayload)->u16Etype); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCSGetPktInfo : Eth Hdr Type : %X\n",u16Etype); if(u16Etype > 0x5dc) { diff --git a/trunk/drivers/staging/bcm/TODO b/trunk/drivers/staging/bcm/TODO index 366634be5fe1..cd3e9f2ed87a 100644 --- a/trunk/drivers/staging/bcm/TODO +++ b/trunk/drivers/staging/bcm/TODO @@ -1,15 +1,22 @@ +This driver is barely functional in its current state. + +BIG: + - existing API is (/dev/tarang) should be replaced + Is it possible to use same API as Intel Wimax stack and + have same user level components. + - Qos and queue model is non-standard and inflexible. + Use existing TC Qos? + TODO: + - support more than one board - eliminate global variables + - remove developer debug BCM_DEBUG() macros + add a limited number of messages through netif_msg() - fix non-standard kernel style - - sparse warnings - checkpatch warnings - - remove compatiablity code for older kernels - - remove #ifdef's - - fix bogus device nameing and reference counting (see bcm_notify_event) - - fix use of file I/O to load config - - request firmware - - update to current network device API - - merge some files together + - use request firmware + - fix use of file I/O to load config with better API + - merge some files together? - cleanup/eliminate debug messages - - integrate with existing Wimax stack? + diff --git a/trunk/drivers/staging/bcm/Transmit.c b/trunk/drivers/staging/bcm/Transmit.c index 12f9e13457db..0f7000960d50 100644 --- a/trunk/drivers/staging/bcm/Transmit.c +++ b/trunk/drivers/staging/bcm/Transmit.c @@ -6,7 +6,7 @@ digraph transmit1 { node[shape=box] edge[weight=5;color=red] -bcm_transmit->reply_to_arp_request[label="ARP"] + bcm_transmit->GetPacketQueueIndex[label="IP Packet"] GetPacketQueueIndex->IpVersion4[label="IPV4"] GetPacketQueueIndex->IpVersion6[label="IPV6"] @@ -35,169 +35,16 @@ SendPacketFromQueue->SetupNextSend->bcm_cmd53 #include "headers.h" -/******************************************************************* -* Function - bcm_transmit() -* -* Description - This is the main transmit function for our virtual -* interface(veth0). It handles the ARP packets. It -* clones this packet and then Queue it to a suitable -* Queue. Then calls the transmit_packet(). -* -* Parameter - skb - Pointer to the socket buffer structure -* dev - Pointer to the virtual net device structure -* -* Returns - zero (success) or -ve value (failure) -* -*********************************************************************/ - -INT bcm_transmit(struct sk_buff *skb, /**< skb */ - struct net_device *dev /**< net device pointer */ - ) -{ - PMINI_ADAPTER Adapter = NULL; - USHORT qindex=0; - struct timeval tv; - UINT pkt_type = 0; - UINT calltransmit = 0; - - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "\n%s====>\n",__FUNCTION__); - - memset(&tv, 0, sizeof(tv)); - /* Check for valid parameters */ - if(skb == NULL || dev==NULL) - { - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX,TX_OSAL_DBG, DBG_LVL_ALL, "Got NULL skb or dev\n"); - return -EINVAL; - } - - Adapter = GET_BCM_ADAPTER(dev); - if(!Adapter) - { - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Got Invalid Adapter\n"); - return -EINVAL; - } - if(Adapter->device_removed == TRUE || !Adapter->LinkUpStatus) - { - if(!netif_queue_stopped(dev)) { - netif_carrier_off(dev); - netif_stop_queue(dev); - } - return STATUS_FAILURE; - } - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Packet size : %d\n", skb->len); - - /*Add Ethernet CS check here*/ - if(Adapter->TransferMode == IP_PACKET_ONLY_MODE ) - { - pkt_type = ntohs(*(PUSHORT)(skb->data + 12)); - /* Get the queue index where the packet is to be queued */ - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Getting the Queue Index....."); - - qindex = GetPacketQueueIndex(Adapter,skb); - - if((SHORT)INVALID_QUEUE_INDEX==(SHORT)qindex) - { - if(pkt_type == ETH_ARP_FRAME) - { - /* - Reply directly to ARP request packet - ARP Spoofing only if NO ETH CS rule matches for it - */ - BCM_DEBUG_PRINT (Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,"ARP OPCODE = %02x", - - (*(PUCHAR)(skb->data + 21))); - - reply_to_arp_request(skb); - - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX,TX_OSAL_DBG, DBG_LVL_ALL,"After reply_to_arp_request \n"); - - } - else - { - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, - "Invalid queue index, dropping pkt\n"); - - bcm_kfree_skb(skb); - } - return STATUS_SUCCESS; - } - - if(Adapter->PackInfo[qindex].uiCurrentPacketsOnHost >= SF_MAX_ALLOWED_PACKETS_TO_BACKUP) - { - atomic_inc(&Adapter->TxDroppedPacketCount); - bcm_kfree_skb(skb); - return STATUS_SUCCESS; - } - - /* Now Enqueue the packet */ - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "bcm_transmit Enqueueing the Packet To Queue %d",qindex); - spin_lock(&Adapter->PackInfo[qindex].SFQueueLock); - Adapter->PackInfo[qindex].uiCurrentBytesOnHost += skb->len; - Adapter->PackInfo[qindex].uiCurrentPacketsOnHost++; - - *((B_UINT32 *)skb->cb + SKB_CB_LATENCY_OFFSET ) = jiffies; - ENQUEUEPACKET(Adapter->PackInfo[qindex].FirstTxQueue, - Adapter->PackInfo[qindex].LastTxQueue, skb); - atomic_inc(&Adapter->TotalPacketCount); - spin_unlock(&Adapter->PackInfo[qindex].SFQueueLock); - do_gettimeofday(&tv); - - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,"ENQ: \n"); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Pkt Len = %d, sec: %ld, usec: %ld\n", - (skb->len-ETH_HLEN), tv.tv_sec, tv.tv_usec); - -#ifdef BCM_SHM_INTERFACE - spin_lock(&Adapter->txtransmitlock); - if(Adapter->txtransmit_running == 0) - { - Adapter->txtransmit_running = 1; - calltransmit = 1; - } - else - calltransmit = 0; - - spin_unlock(&Adapter->txtransmitlock); -#endif - if(calltransmit == 1) - transmit_packets(Adapter); - else - { - if(!atomic_read(&Adapter->TxPktAvail)) - { - atomic_set(&Adapter->TxPktAvail, 1); -#ifdef BCM_SHM_INTERFACE - virtual_mail_box_interrupt(); -#endif - wake_up(&Adapter->tx_packet_wait_queue); - } - } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "<===="); - } - else - bcm_kfree_skb(skb); - - return STATUS_SUCCESS; -} - /** @ingroup ctrl_pkt_functions This function dispatches control packet to the h/w interface @return zero(success) or -ve value(failure) */ -INT SendControlPacket(PMINI_ADAPTER Adapter, /**"); + PLEADER PLeader = (PLEADER)pControlPacket; - PLeader=(PLEADER)pControlPacket; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Tx"); if(!pControlPacket || !Adapter) { @@ -208,12 +55,6 @@ INT SendControlPacket(PMINI_ADAPTER Adapter, /**PLength-1)/MAX_DEVICE_DESC_SIZE)+1)) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "NO FREE DESCRIPTORS TO SEND CONTROL PACKET"); - if(Adapter->bcm_jiffies == 0) - { - Adapter->bcm_jiffies = jiffies; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "UPDATED TIME(hex): %lu", - Adapter->bcm_jiffies); - } return STATUS_FAILURE; } @@ -224,76 +65,33 @@ INT SendControlPacket(PMINI_ADAPTER Adapter, /**PLength); if(Adapter->device_removed) return 0; -#ifndef BCM_SHM_INTERFACE - Adapter->interface_transmit(Adapter->pvInterfaceAdapter, - pControlPacket, (PLeader->PLength + LEADER_SIZE)); -#else - tx_pkts_to_firmware(pControlPacket,(PLeader->PLength + LEADER_SIZE),1); - if(PLeader->Status==IDLE_MESSAGE) - { - if(((CONTROL_MESSAGE*)PLeader)->szData[0] == GO_TO_IDLE_MODE_PAYLOAD && - ((CONTROL_MESSAGE*)PLeader)->szData[1] == TARGET_CAN_GO_TO_IDLE_MODE) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Idle Mode Ack Sent to the Device\n"); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Host Entering into Idle Mode\n"); - do_gettimeofday(&tv); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "IdleMode Msg sent to f/w at time :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000); - if(Adapter->bDoSuspend != TRUE) - { - Adapter->IdleMode = TRUE; - Adapter->bPreparingForLowPowerMode = FALSE ; - } - } - } - if((PLeader->Status == LINK_UP_CONTROL_REQ) && - ((PUCHAR)pControlPacket)[sizeof(LEADER)] == LINK_UP_ACK && - ((PUCHAR)pControlPacket)[sizeof(LEADER)+1] == - LINK_SHUTDOWN_REQ_FROM_FIRMWARE && - ((PUCHAR)pControlPacket)[sizeof(LEADER)+2] == SHUTDOWN_ACK_FROM_DRIVER) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Shut Down ACK Sent and Host entering Shut State \n"); - if(Adapter->bDoSuspend != TRUE) - { - Adapter->bShutStatus = TRUE; - Adapter->bPreparingForLowPowerMode = FALSE; - Adapter->bTriedToWakeUpFromlowPowerMode = FALSE; - } + if (netif_msg_pktdata(Adapter)) + print_hex_dump(KERN_DEBUG, PFX "tx control: ", DUMP_PREFIX_NONE, + 16, 1, pControlPacket, PLeader->PLength + LEADER_SIZE, 0); - } -#endif + Adapter->interface_transmit(Adapter->pvInterfaceAdapter, + pControlPacket, (PLeader->PLength + LEADER_SIZE)); - ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.tx_packets++; - ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.tx_bytes+= - PLeader->PLength; atomic_dec(&Adapter->CurrNumFreeTxDesc); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<========="); return STATUS_SUCCESS; } -static LEADER Leader={0}; + /** @ingroup tx_functions This function despatches the IP packets with the given vcid to the target via the host h/w interface. @return zero(success) or -ve value(failure) */ -INT SetupNextSend(PMINI_ADAPTER Adapter, /**len > MAX_DEVICE_DESC_SIZE) { status = STATUS_FAILURE; @@ -302,14 +100,10 @@ INT SetupNextSend(PMINI_ADAPTER Adapter, /**cb)+SKB_CB_CLASSIFICATION_OFFSET); - QueueIndex = SearchVcid( Adapter,Vcid); - if(QueueIndex < NO_OF_QUEUES) - { - bHeaderSupressionEnabled = - Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled; - bHeaderSupressionEnabled = - bHeaderSupressionEnabled & Adapter->bPHSEnabled; - } + + bHeaderSupressionEnabled = Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled + & Adapter->bPHSEnabled; + if(Adapter->device_removed) { status = STATUS_FAILURE; @@ -327,15 +121,10 @@ INT SetupNextSend(PMINI_ADAPTER Adapter, /**cb) + SKB_CB_TCPACK_OFFSET )) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Sending TCP ACK\n"); + if(TCP_ACK == *((UINT32*) (Packet->cb) + SKB_CB_TCPACK_OFFSET )) Leader.Status = LEADER_STATUS_TCP_ACK; - } else - { Leader.Status = LEADER_STATUS; - } if(Adapter->PackInfo[QueueIndex].bEthCSSupport) { @@ -351,68 +140,53 @@ INT SetupNextSend(PMINI_ADAPTER Adapter, /**data, &Leader, LEADER_SIZE); } - else { Leader.PLength = Packet->len - ETH_HLEN; memcpy((LEADER*)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE); } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Packet->len = %d", Packet->len); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Vcid = %d", Vcid); - -#ifndef BCM_SHM_INTERFACE status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter, Packet->data, (Leader.PLength + LEADER_SIZE)); -#else - status = tx_pkts_to_firmware(Packet,Packet->len,0); -#endif if(status) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Tx Failed..\n"); + ++Adapter->dev->stats.tx_errors; + if (netif_msg_tx_err(Adapter)) + pr_info(PFX "%s: transmit error %d\n", Adapter->dev->name, + status); } else { + struct netdev_queue *txq = netdev_get_tx_queue(Adapter->dev, QueueIndex); Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength; - atomic_add(Leader.PLength, &Adapter->GoodTxByteCount); - atomic_inc(&Adapter->TxTotalPacketCount); -#ifdef GDMA_INTERFACE - dontfree = 1; -#endif - } - atomic_dec(&Adapter->CurrNumFreeTxDesc); - -errExit: + txq->tx_bytes += Leader.PLength; + ++txq->tx_packets; - if(STATUS_SUCCESS == status) - { Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3; Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len); Adapter->PackInfo[QueueIndex].uiSentPackets++; Adapter->PackInfo[QueueIndex].NumOfPacketsSent++; atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount); -#ifdef BCM_SHM_INTERFACE - if(atomic_read(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount) < 0) - { - atomic_set(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount, 0); - } -#endif Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength; } + atomic_dec(&Adapter->CurrNumFreeTxDesc); -#ifdef GDMA_INTERFACE - if(!dontfree){ - bcm_kfree_skb(Packet); - } -#else - bcm_kfree_skb(Packet); -#endif +errExit: + + dev_kfree_skb(Packet); return status; } +static int tx_pending(PMINI_ADAPTER Adapter) +{ + return (atomic_read(&Adapter->TxPktAvail) + && MINIMUM_PENDING_DESCRIPTORS < atomic_read(&Adapter->CurrNumFreeTxDesc)) + || Adapter->device_removed || (1 == Adapter->downloadDDR); +} + /** @ingroup tx_functions Transmit thread @@ -420,57 +194,26 @@ Transmit thread int tx_pkt_handler(PMINI_ADAPTER Adapter /**< pointer to adapter object*/ ) { -#ifndef BCM_SHM_INTERFACE int status = 0; -#endif - - UINT calltransmit = 1; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Entring to wait for signal from the interrupt service thread!Adapter = %p",Adapter); - - while(1) - { - if(Adapter->LinkUpStatus){ + while(! kthread_should_stop()) { + /* FIXME - the timeout looks like workaround for racey usage of TxPktAvail */ + if(Adapter->LinkUpStatus) wait_event_timeout(Adapter->tx_packet_wait_queue, - ((atomic_read(&Adapter->TxPktAvail) && - (MINIMUM_PENDING_DESCRIPTORS < - atomic_read(&Adapter->CurrNumFreeTxDesc)) && - (Adapter->device_removed == FALSE))) || - (1 == Adapter->downloadDDR) || kthread_should_stop() -#ifndef BCM_SHM_INTERFACE - || (TRUE == Adapter->bEndPointHalted) -#endif - , msecs_to_jiffies(10)); - } - else{ - wait_event(Adapter->tx_packet_wait_queue, - ((atomic_read(&Adapter->TxPktAvail) && - (MINIMUM_PENDING_DESCRIPTORS < - atomic_read(&Adapter->CurrNumFreeTxDesc)) && - (Adapter->device_removed == FALSE))) || - (1 == Adapter->downloadDDR) || kthread_should_stop() -#ifndef BCM_SHM_INTERFACE - || (TRUE == Adapter->bEndPointHalted) -#endif - ); - } - - if(kthread_should_stop() || Adapter->device_removed) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n"); - Adapter->transmit_packet_thread = NULL; - return 0; - } + tx_pending(Adapter), msecs_to_jiffies(10)); + else + wait_event_interruptible(Adapter->tx_packet_wait_queue, + tx_pending(Adapter)); -#ifndef BCM_SHM_INTERFACE + if (Adapter->device_removed) + break; if(Adapter->downloadDDR == 1) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Downloading DDR Settings\n"); Adapter->downloadDDR +=1; status = download_ddr_settings(Adapter); if(status) - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "DDR DOWNLOAD FAILED!\n"); + pr_err(PFX "DDR DOWNLOAD FAILED! %d\n", status); continue; } @@ -489,7 +232,6 @@ int tx_pkt_handler(PMINI_ADAPTER Adapter /**< pointer to adapter object*/ update_per_sf_desc_cnts(Adapter); } } -#endif if( atomic_read(&Adapter->CurrNumFreeTxDesc) && Adapter->LinkStatus == SYNC_UP_REQUEST && @@ -507,49 +249,12 @@ int tx_pkt_handler(PMINI_ADAPTER Adapter /**< pointer to adapter object*/ wake_up(&Adapter->process_rx_cntrlpkt); } -#ifdef BCM_SHM_INTERFACE - spin_lock_bh(&Adapter->txtransmitlock); - if(Adapter->txtransmit_running == 0) - { - Adapter->txtransmit_running = 1; - calltransmit = 1; - } - else - calltransmit = 0; - spin_unlock_bh(&Adapter->txtransmitlock); -#endif - - if(calltransmit) - transmit_packets(Adapter); + transmit_packets(Adapter); atomic_set(&Adapter->TxPktAvail, 0); } - return 0; -} - -#ifdef BCM_SHM_INTERFACE -extern PMINI_ADAPTER psAdaptertest; -void virtual_mail_box_interrupt(void) -{ - -#ifndef GDMA_INTERFACE - PUINT ptr = (PUINT)CPE_VIRTUAL_MAILBOX_REG; - UINT intval = (UINT)((*ptr & 0xFF00) >> 8); - if (intval != 0) - { - atomic_set(&psAdaptertest->CurrNumFreeTxDesc, intval); - atomic_set (&psAdaptertest->uiMBupdate, TRUE); - //make it to 0 - *ptr = *ptr & 0xffff00ff; - } -#endif -} -unsigned int total_tx_pkts_pending(void) -{ - return atomic_read(&psAdaptertest->TotalPacketCount); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n"); + Adapter->transmit_packet_thread = NULL; + return 0; } - -#endif - - diff --git a/trunk/drivers/staging/bcm/cntrl_SignalingInterface.h b/trunk/drivers/staging/bcm/cntrl_SignalingInterface.h index 4cbe30022248..890778450a86 100644 --- a/trunk/drivers/staging/bcm/cntrl_SignalingInterface.h +++ b/trunk/drivers/staging/bcm/cntrl_SignalingInterface.h @@ -2,19 +2,6 @@ #define CNTRL_SIGNALING_INTERFACE_ -#ifdef BECEEM_TARGET - -#include -#include -#include -#include -#include -using namespace Beceem; -#ifdef ENABLE_CORRIGENDUM2_UPDATE -extern B_UINT32 g_u32Corr2MacFlags; -#endif - -#else #define DSA_REQ 11 @@ -28,7 +15,6 @@ extern B_UINT32 g_u32Corr2MacFlags; #define DSD_ACK 19 #define MAX_CLASSIFIERS_IN_SF 4 -#endif #define MAX_STRING_LEN 20 #define MAX_PHS_LENGTHS 255 @@ -57,37 +43,7 @@ extern B_UINT32 g_u32Corr2MacFlags; ////////////////////////structure Definitions/////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// \brief class cCPacketClassificationRule -#ifdef BECEEM_TARGET -class CCPacketClassificationRuleSI{ - public: - /// \brief Constructor for the class - CCPacketClassificationRuleSI(): - u8ClassifierRulePriority(mClassifierRulePriority), - u8IPTypeOfServiceLength(mIPTypeOfService), - u8Protocol(mProtocol), - u8IPMaskedSourceAddressLength(0), - u8IPDestinationAddressLength(0), - u8ProtocolSourcePortRangeLength(0), - u8ProtocolDestPortRangeLength(0), - u8EthernetDestMacAddressLength(0), - u8EthernetSourceMACAddressLength(0), - u8EthertypeLength(0), - u16UserPriority(mUserPriority), - u16VLANID(mVLANID), - u8AssociatedPHSI(mAssociatedPHSI), - u16PacketClassificationRuleIndex(mPacketClassifierRuleIndex), - u8VendorSpecificClassifierParamLength(mVendorSpecificClassifierParamLength), - u8IPv6FlowLableLength(mIPv6FlowLableLength), - u8ClassifierActionRule(mClassifierActionRule) - - {} - void Reset() - { - CCPacketClassificationRuleSI(); - } -#else struct _stCPacketClassificationRuleSI{ -#endif /** 16bit UserPriority Of The Service Flow*/ B_UINT16 u16UserPriority; @@ -145,29 +101,10 @@ struct _stCPacketClassificationRuleSI{ B_UINT8 u8ClassifierActionRule; B_UINT16 u16ValidityBitMap; }; -#ifndef BECEEM_TARGET typedef struct _stCPacketClassificationRuleSI CCPacketClassificationRuleSI,stCPacketClassificationRuleSI, *pstCPacketClassificationRuleSI; -#endif /// \brief class CPhsRuleSI -#ifdef BECEEM_TARGET -class CPhsRuleSI{ - public: - /// \brief Constructor for the class - CPhsRuleSI(): - u8PHSI(mPHSI), - u8PHSFLength(0), - u8PHSMLength(0), - u8PHSS(mPHSS), - u8PHSV(mPHSV), - u8VendorSpecificPHSParamsLength(mVendorSpecificPHSParamLength){} - void Reset() - { - CPhsRuleSI(); - } -#else typedef struct _stPhsRuleSI { -#endif /** 8bit PHS Index Of The Service Flow*/ B_UINT8 u8PHSI; /** PHSF Length Of The Service Flow*/ @@ -188,31 +125,11 @@ typedef struct _stPhsRuleSI { B_UINT8 u8VendorSpecificPHSParams[VENDOR_PHS_PARAM_LENGTH]; B_UINT8 u8Padding[2]; -#ifdef BECEEM_TARGET -}; -#else }stPhsRuleSI,*pstPhsRuleSI; typedef stPhsRuleSI CPhsRuleSI; -#endif /// \brief structure cConvergenceSLTypes -#ifdef BECEEM_TARGET -class CConvergenceSLTypes{ - public: - /// \brief Constructor for the class - CConvergenceSLTypes(): - u8ClassfierDSCAction(mClassifierDSCAction), - u8PhsDSCAction (mPhsDSCAction) - {} - void Reset() - { - CConvergenceSLTypes(); - cCPacketClassificationRule.Reset(); - cPhsRule.Reset(); - } -#else struct _stConvergenceSLTypes{ -#endif /** 8bit Phs Classfier Action Of The Service Flow*/ B_UINT8 u8ClassfierDSCAction; /** 8bit Phs DSC Action Of The Service Flow*/ @@ -220,111 +137,15 @@ struct _stConvergenceSLTypes{ /** 16bit Padding */ B_UINT8 u8Padding[2]; /// \brief class cCPacketClassificationRule -#ifdef BECEEM_TARGET - CCPacketClassificationRuleSI cCPacketClassificationRule; -#else stCPacketClassificationRuleSI cCPacketClassificationRule; -#endif /// \brief class CPhsRuleSI -#ifdef BECEEM_TARGET - CPhsRuleSI cPhsRule; -#else struct _stPhsRuleSI cPhsRule; -#endif }; -#ifndef BECEEM_TARGET typedef struct _stConvergenceSLTypes stConvergenceSLTypes,CConvergenceSLTypes, *pstConvergenceSLTypes; -#endif /// \brief structure CServiceFlowParamSI -#ifdef BECEEM_TARGET -class CServiceFlowParamSI{ - public: - /// \brief Constructor for the class - CServiceFlowParamSI(): - u32SFID(mSFid), - u16CID(mCid), - u8ServiceClassNameLength(mServiceClassNameLength), - u8MBSService(mMBSService), - u8QosParamSet(mQosParamSetType), - u8TrafficPriority(mTrafficPriority), - u32MaxSustainedTrafficRate(mMaximumSustainedTrafficRate), - u32MaxTrafficBurst(mMaximumTrafficBurst), - u32MinReservedTrafficRate(mMinimumReservedTrafficRate), - u8ServiceFlowSchedulingType(mServiceFlowSchedulingType), - u8RequesttransmissionPolicy(mRequestTransmissionPolicy), - u32ToleratedJitter(mToleratedJitter), - u32MaximumLatency(mMaximumLatency), - u8FixedLengthVSVariableLengthSDUIndicator - (mFixedLengthVSVariableLength), - u8SDUSize(mSDUSize), - u16TargetSAID(mTargetSAID), - u8ARQEnable(mARQEnable), - u16ARQWindowSize(mARQWindowSize), - u16ARQBlockLifeTime(mARQBlockLifeTime), - u16ARQSyncLossTimeOut(mARQSyncLossTimeOut), - u8ARQDeliverInOrder(mARQDeliverInOrder), - u16ARQRxPurgeTimeOut(mARQRXPurgeTimeOut), - //Add ARQ BLOCK SIZE, ARQ TX and RX delay initializations here - //after we move to only CORR2 - u8RxARQAckProcessingTime(mRxARQAckProcessingTime), - u8CSSpecification(mCSSpecification), - u8TypeOfDataDeliveryService(mTypeOfDataDeliveryService), - u16SDUInterArrivalTime(mSDUInterArrivalTime), - u16TimeBase(mTimeBase), - u8PagingPreference(mPagingPreference), - u8MBSZoneIdentifierassignment(mMBSZoneIdentifierassignmentLength), - u8TrafficIndicationPreference(mTrafficIndicationPreference), - u8GlobalServicesClassNameLength(mGlobalServicesClassNameLength), - u8SNFeedbackEnabled(mSNFeedbackEnabled), - u8FSNSize(mFSNSize), - u8CIDAllocation4activeBSsLength(mCIDAllocation4activeBSsLength), - u16UnsolicitedGrantInterval(mUnsolicitedGrantInterval), - u16UnsolicitedPollingInterval(mUnsolicitedPollingInterval), - u8PDUSNExtendedSubheader4HarqReordering(mPDUSNExtendedSubheader4HarqReordering), - u8MBSContentsIDLength(mMBSContentsIDLength), - u8HARQServiceFlows(mHARQServiceFlows), - u8AuthTokenLength(mAuthTokenLength), - u8HarqChannelMappingLength(mHarqChannelMappingLength), - u8VendorSpecificQoSParamLength(mVendorSpecificQoSParamLength), - bValid(FALSE), - u8TotalClassifiers() -{ -//Remove the bolck after we move to Corr2 only code -#ifdef ENABLE_CORRIGENDUM2_UPDATE - if((g_u32Corr2MacFlags & CORR_2_DSX) || (g_u32Corr2MacFlags & CORR_2_ARQ)) - { - /* IEEE Comment #627 / MTG Comment #426 */ - u16ARQBlockSize = mARQBlockSize; - if(g_u32Corr2MacFlags & CORR_2_ARQ) { - u16ARQRetryTxTimeOut = mARQRetryTimeOutTxDelay; - if(g_u32VENDOR_TYPE == VENDOR_ALCATEL) { - u16ARQRetryRxTimeOut = mARQRetryTimeOutRxDelay_ALU; - } else { - u16ARQRetryRxTimeOut = mARQRetryTimeOutRxDelay; - } - } - else - { - u16ARQRetryTxTimeOut = mARQRetryTimeOutTxDelayCorr1; - u16ARQRetryRxTimeOut = mARQRetryTimeOutRxDelayCorr1; - } - } - else -#endif - { - u16ARQBlockSize = mARQBlockSizeCorr1; - u16ARQRetryTxTimeOut = mARQRetryTimeOutTxDelayCorr1; - u16ARQRetryRxTimeOut = mARQRetryTimeOutRxDelayCorr1; - } -} - - void ComputeMacOverhead(B_UINT8 u8SecOvrhead); - B_UINT16 GetMacOverhead() { return u16MacOverhead; } -#else typedef struct _stServiceFlowParamSI{ -#endif //end of ifdef BECEEM_TARGET /** 32bitSFID Of The Service Flow*/ B_UINT32 u32SFID; @@ -367,11 +188,6 @@ typedef struct _stServiceFlowParamSI{ /** 16bit ARQ Purge timeout */ B_UINT16 u16ARQRxPurgeTimeOut; -#if 0 //def ENABLE_CORRIGENDUM2_UPDATE -/* IEEE Comment #627 / MTG Comment #426 */ - /// \brief Size of an ARQ block, changed from 2 bytes to 1 - B_UINT8 u8ARQBlockSize; -#endif //TODO::Remove this once we move to a new CORR2 driver /// \brief Size of an ARQ block B_UINT16 u16ARQBlockSize; @@ -496,35 +312,18 @@ typedef struct _stServiceFlowParamSI{ B_UINT8 bValid; /**< Validity flag */ B_UINT8 u8Padding; /**< Padding byte*/ -#ifdef BECEEM_TARGET -/** -Structure for Convergence SubLayer Types with a maximum of 4 classifiers -*/ - CConvergenceSLTypes cConvergenceSLTypes[MAX_CLASSIFIERS_IN_SF]; -#else /** Structure for Convergence SubLayer Types with a maximum of 4 classifiers */ stConvergenceSLTypes cConvergenceSLTypes[MAX_CLASSIFIERS_IN_SF]; -#endif -#ifdef BECEEM_TARGET -}; -#else } stServiceFlowParamSI, *pstServiceFlowParamSI; typedef stServiceFlowParamSI CServiceFlowParamSI; -#endif /** structure stLocalSFAddRequest */ typedef struct _stLocalSFAddRequest{ -#ifdef BECEEM_TARGET - _stLocalSFAddRequest( ) : - u8Type(0x00), eConnectionDir(0x00), - u16TID(0x0000), u16CID(0x0000), u16VCID(0x0000) - {} -#endif B_UINT8 u8Type; /**< Type*/ B_UINT8 eConnectionDir; /**< Connection direction*/ @@ -535,19 +334,9 @@ typedef struct _stLocalSFAddRequest{ /// \brief 16bitVCID B_UINT16 u16VCID; /**< 16bit VCID*/ /// \brief structure ParameterSet -#ifdef BECEEM_SIGNALLING_INTERFACE_API - CServiceFlowParamSI sfParameterSet; -#endif -#ifdef BECEEM_TARGET - CServiceFlowParamSI *psfParameterSet; -#else stServiceFlowParamSI *psfParameterSet; /**< structure ParameterSet*/ -#endif -#ifdef USING_VXWORKS - USE_DATA_MEMORY_MANAGER(); -#endif }stLocalSFAddRequest, *pstLocalSFAddRequest; @@ -555,12 +344,6 @@ typedef struct _stLocalSFAddRequest{ structure stLocalSFAddIndication */ typedef struct _stLocalSFAddIndication{ -#ifdef BECEEM_TARGET - _stLocalSFAddIndication( ) : - u8Type(0x00), eConnectionDir(0x00), - u16TID(0x0000), u16CID(0x0000), u16VCID(0x0000) - {} -#endif B_UINT8 u8Type; /**< Type*/ B_UINT8 eConnectionDir; /**< Connection Direction*/ @@ -571,37 +354,19 @@ typedef struct _stLocalSFAddIndication{ /// \brief 16bitVCID B_UINT16 u16VCID; /**< 16bitVCID*/ -#ifdef BECEEM_SIGNALLING_INTERFACE_API - CServiceFlowParamSI sfAuthorizedSet; - /// \brief structure AdmittedSet - CServiceFlowParamSI sfAdmittedSet; - /// \brief structure ActiveSet - CServiceFlowParamSI sfActiveSet; -#endif /// \brief structure AuthorizedSet -#ifdef BECEEM_TARGET - CServiceFlowParamSI *psfAuthorizedSet; - /// \brief structure AdmittedSet - CServiceFlowParamSI *psfAdmittedSet; - /// \brief structure ActiveSet - CServiceFlowParamSI *psfActiveSet; -#else /// \brief structure AuthorizedSet stServiceFlowParamSI *psfAuthorizedSet; /**< AuthorizedSet of type stServiceFlowParamSI*/ /// \brief structure AdmittedSet stServiceFlowParamSI *psfAdmittedSet; /**< AdmittedSet of type stServiceFlowParamSI*/ /// \brief structure ActiveSet stServiceFlowParamSI *psfActiveSet; /**< sfActiveSet of type stServiceFlowParamSI*/ -#endif B_UINT8 u8CC; /**< Confirmation Code*/ B_UINT8 u8Padd; /**< 8-bit Padding */ B_UINT16 u16Padd; /**< 16 bit Padding */ -#ifdef USING_VXWORKS - USE_DATA_MEMORY_MANAGER(); -#endif }stLocalSFAddIndication; @@ -619,33 +384,17 @@ typedef struct _stLocalSFAddIndication stLocalSFChangeIndication, *pstLocalSFCha structure stLocalSFDeleteRequest */ typedef struct _stLocalSFDeleteRequest{ -#ifdef BECEEM_TARGET - _stLocalSFDeleteRequest( ) : - u8Type(0x00), u8Padding(0x00), - u16TID(0x0000), u32SFID (0x00000000) - {} -#endif B_UINT8 u8Type; /**< Type*/ B_UINT8 u8Padding; /**< Padding byte*/ B_UINT16 u16TID; /**< TID*/ /// \brief 32bitSFID B_UINT32 u32SFID; /**< SFID*/ -#ifdef USING_VXWORKS - USE_DATA_MEMORY_MANAGER(); -#endif }stLocalSFDeleteRequest, *pstLocalSFDeleteRequest; /** structure stLocalSFDeleteIndication */ typedef struct stLocalSFDeleteIndication{ -#ifdef BECEEM_TARGET - stLocalSFDeleteIndication( ) : - u8Type(0x00), u8Padding(0x00), - u16TID(0x0000), u16CID(0x0000), - u16VCID(0x0000),u32SFID (0x00000000) - {} -#endif B_UINT8 u8Type; /**< Type */ B_UINT8 u8Padding; /**< Padding */ B_UINT16 u16TID; /**< TID */ @@ -658,9 +407,6 @@ typedef struct stLocalSFDeleteIndication{ /// \brief 8bit Confirmation code B_UINT8 u8ConfirmationCode; /**< Confirmation code */ B_UINT8 u8Padding1[3]; /**< 3 byte Padding */ -#ifdef USING_VXWORKS - USE_DATA_MEMORY_MANAGER(); -#endif }stLocalSFDeleteIndication; typedef struct _stIM_SFHostNotify diff --git a/trunk/drivers/staging/bcm/headers.h b/trunk/drivers/staging/bcm/headers.h index 9d4e3aca1b34..473f11eebf7c 100644 --- a/trunk/drivers/staging/bcm/headers.h +++ b/trunk/drivers/staging/bcm/headers.h @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -41,21 +40,7 @@ #endif #include #include -#ifndef BCM_SHM_INTERFACE #include -#endif -#ifdef BECEEM_TARGET - -#include -#include -#include -#include -#include -using namespace Beceem; -#ifdef ENABLE_CORRIGENDUM2_UPDATE -extern B_UINT32 g_u32Corr2MacFlags; -#endif -#endif #include "Typedefs.h" #include "Version.h" @@ -71,39 +56,28 @@ extern B_UINT32 g_u32Corr2MacFlags; #include "CmHost.h" #include "DDRInit.h" #include "Debug.h" -#include "HostMibs.h" #include "IPv6ProtocolHdr.h" -#include "osal_misc.h" #include "PHSModule.h" #include "Protocol.h" #include "Prototypes.h" #include "Queue.h" #include "vendorspecificextn.h" -#ifndef BCM_SHM_INTERFACE #include "InterfaceMacros.h" #include "InterfaceAdapter.h" #include "InterfaceIsr.h" -#include "Interfacemain.h" #include "InterfaceMisc.h" #include "InterfaceRx.h" #include "InterfaceTx.h" -#endif #include "InterfaceIdleMode.h" #include "InterfaceInit.h" -#ifdef BCM_SHM_INTERFACE -#include - -#ifdef GDMA_INTERFACE -#include "GdmaInterface.h" -#include "symphony.h" -#else -#include "virtual_interface.h" - -#endif - -#endif +#define DRV_NAME "beceem" +#define DEV_NAME "tarang" +#define DRV_DESCRIPTION "Beceem Communications Inc. WiMAX driver" +#define DRV_COPYRIGHT "Copyright 2010. Beceem Communications Inc" +#define DRV_VERSION VER_FILEVERSION_STR +#define PFX DRV_NAME " " #endif diff --git a/trunk/drivers/staging/bcm/hostmibs.c b/trunk/drivers/staging/bcm/hostmibs.c index e9da513b3c24..c13ea5c9a2aa 100644 --- a/trunk/drivers/staging/bcm/hostmibs.c +++ b/trunk/drivers/staging/bcm/hostmibs.c @@ -10,12 +10,8 @@ */ #include "headers.h" -INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, - PVOID ioBuffer, - ULONG inputBufferLength) +INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, S_MIBS_HOST_STATS_MIBS *pstHostMibs) { - - S_MIBS_HOST_STATS_MIBS *pstHostMibs = NULL; S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; S_PHS_RULE *pstPhsRule = NULL; S_CLASSIFIER_TABLE *pstClassifierTable = NULL; @@ -30,15 +26,6 @@ INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, return STATUS_FAILURE; } - if(ioBuffer == NULL) - { - return -EINVAL; - } - memset(ioBuffer,0,sizeof(S_MIBS_HOST_STATS_MIBS)); - - pstHostMibs = (S_MIBS_HOST_STATS_MIBS *)ioBuffer; - - //Copy the classifier Table for(nClassifierIndex=0; nClassifierIndex < MAX_CLASSIFIERS; nClassifierIndex++) @@ -54,7 +41,7 @@ INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, { if(Adapter->PackInfo[nSfIndex].bValid) { - OsalMemMove((PVOID)&pstHostMibs->astSFtable[nSfIndex],(PVOID)&Adapter->PackInfo[nSfIndex],sizeof(S_MIBS_SERVICEFLOW_TABLE)); + memcpy((PVOID)&pstHostMibs->astSFtable[nSfIndex],(PVOID)&Adapter->PackInfo[nSfIndex],sizeof(S_MIBS_SERVICEFLOW_TABLE)); } else { @@ -83,7 +70,7 @@ INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, pstHostMibs->astPhsRulesTable[nPhsTableIndex].ulSFID = Adapter->PackInfo[nSfIndex].ulSFID; - OsalMemMove(&pstHostMibs->astPhsRulesTable[nPhsTableIndex].u8PHSI, + memcpy(&pstHostMibs->astPhsRulesTable[nPhsTableIndex].u8PHSI, &pstPhsRule->u8PHSI, sizeof(S_PHS_RULE)); nPhsTableIndex++; @@ -95,12 +82,9 @@ INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, } - //copy other Host Statistics parameters - pstHostMibs->stHostInfo.GoodTransmits = - atomic_read(&Adapter->TxTotalPacketCount); - pstHostMibs->stHostInfo.GoodReceives = - atomic_read(&Adapter->GoodRxPktCount); + pstHostMibs->stHostInfo.GoodTransmits = Adapter->dev->stats.tx_packets; + pstHostMibs->stHostInfo.GoodReceives = Adapter->dev->stats.rx_packets; pstHostMibs->stHostInfo.CurrNumFreeDesc = atomic_read(&Adapter->CurrNumFreeTxDesc); pstHostMibs->stHostInfo.BEBucketSize = Adapter->BEBucketSize; @@ -115,13 +99,10 @@ INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, } -INT GetDroppedAppCntrlPktMibs(PVOID ioBuffer, PPER_TARANG_DATA pTarang) +VOID GetDroppedAppCntrlPktMibs(S_MIBS_HOST_STATS_MIBS *pstHostMibs, const PPER_TARANG_DATA pTarang) { - S_MIBS_HOST_STATS_MIBS *pstHostMibs = (S_MIBS_HOST_STATS_MIBS *)ioBuffer; - - memcpy((PVOID)&(pstHostMibs->stDroppedAppCntrlMsgs),(PVOID)&(pTarang->stDroppedAppCntrlMsgs),sizeof(S_MIBS_DROPPED_APP_CNTRL_MESSAGES)); - - return STATUS_SUCCESS ; + memcpy(&(pstHostMibs->stDroppedAppCntrlMsgs), + &(pTarang->stDroppedAppCntrlMsgs),sizeof(S_MIBS_DROPPED_APP_CNTRL_MESSAGES)); } diff --git a/trunk/drivers/staging/bcm/led_control.c b/trunk/drivers/staging/bcm/led_control.c index 97adaae7dfc0..16e939fa15d6 100644 --- a/trunk/drivers/staging/bcm/led_control.c +++ b/trunk/drivers/staging/bcm/led_control.c @@ -108,52 +108,16 @@ static INT LED_Proportional_Blink(PMINI_ADAPTER Adapter, UCHAR GPIO_Num_tx, ulong timeout = 0; /*Read initial value of packets sent/received */ - Initial_num_of_packts_tx = atomic_read(&Adapter->TxTotalPacketCount); - Initial_num_of_packts_rx = atomic_read(&Adapter->GoodRxPktCount); + Initial_num_of_packts_tx = Adapter->dev->stats.tx_packets; + Initial_num_of_packts_rx = Adapter->dev->stats.rx_packets; + /*Scale the rate of transfer to no of blinks.*/ num_of_time_tx= ScaleRateofTransfer((ULONG)rate_of_transfer_tx); num_of_time_rx= ScaleRateofTransfer((ULONG)rate_of_transfer_rx); while((Adapter->device_removed == FALSE)) { - #if 0 - if(0 == num_of_time_tx && 0 == num_of_time_rx) - { - timeout = 1000; - Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event, - currdriverstate!= Adapter->DriverState || kthread_should_stop(), - msecs_to_jiffies (timeout)); - if(kthread_should_stop()) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting"); - Adapter->LEDInfo.led_thread_running= BCM_LED_THREAD_DISABLED; - return EVENT_SIGNALED; - } - if(Status) - return EVENT_SIGNALED; - - } - #endif - timeout = 50; - #if 0 - /*Turn on LED if Tx is high bandwidth*/ - if(num_of_time_tx > MAX_NUM_OF_BLINKS) - { - TURN_ON_LED(1< MAX_NUM_OF_BLINKS) - { - TURN_ON_LED(1<TxTotalPacketCount); + Final_num_of_packts_tx = Adapter->dev->stats.tx_packets; + Final_num_of_packts_rx = Adapter->dev->stats.rx_packets; + rate_of_transfer_tx = Final_num_of_packts_tx - Initial_num_of_packts_tx; - Final_num_of_packts_rx = atomic_read(&Adapter->GoodRxPktCount); rate_of_transfer_rx = Final_num_of_packts_rx - Initial_num_of_packts_rx; /*Read initial value of packets sent/received */ @@ -293,7 +258,7 @@ static INT ValidateDSDParamsChecksum( BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread:ValidateDSDParamsChecksum: 0x%lx 0x%X",ulParamOffset, usParamLen); - puBuffer = OsalMemAlloc(usParamLen,"!MEM"); + puBuffer = kmalloc(usParamLen, GFP_KERNEL); if(!puBuffer) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum Allocation failed"); @@ -341,10 +306,7 @@ static INT ValidateDSDParamsChecksum( } exit: - if(puBuffer) - { - OsalMemFree(puBuffer, usParamLen); - } + kfree(puBuffer); return Status; } @@ -497,12 +459,10 @@ static int ReadConfigFileStructure(PMINI_ADAPTER Adapter, BOOLEAN *bEnableThread { int Status = STATUS_SUCCESS; UCHAR GPIO_Array[NUM_OF_LEDS+1]; /*Array to store GPIO numbers from EEPROM*/ -#ifndef BCM_SHM_INTERFACE UINT uiIndex = 0; UINT uiNum_of_LED_Type = 0; PUCHAR puCFGData = NULL; UCHAR bData = 0; -#endif memset(GPIO_Array, DISABLE_GPIO_NUM, NUM_OF_LEDS+1); if(!Adapter->pstargetparams || IS_ERR(Adapter->pstargetparams)) @@ -524,10 +484,6 @@ static int ReadConfigFileStructure(PMINI_ADAPTER Adapter, BOOLEAN *bEnableThread *bEnableThread = FALSE; return Status; } -#ifdef BCM_SHM_INTERFACE - *bEnableThread = FALSE; - return Status ; -#else /* * CONFIG file read successfully. Deallocate the memory of * uiFileNameBufferSize @@ -578,23 +534,7 @@ static int ReadConfigFileStructure(PMINI_ADAPTER Adapter, BOOLEAN *bEnableThread } if(uiNum_of_LED_Type >= NUM_OF_LEDS) *bEnableThread = FALSE; -#endif -#if 0 - for(uiIndex=0; uiIndexLEDInfo.LEDState[uiIndex].LED_Type); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LEDState[%d].LED_On_State = %x\n", uiIndex, - Adapter->LEDInfo.LEDState[uiIndex].LED_On_State); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LEDState[%d].LED_Blink_State = %x\n", uiIndex, - Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LEDState[%d].GPIO_Num = %x\n", uiIndex, - Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num); - } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: Polarity = %d\n", - Adapter->LEDInfo.BitPolarty); -#endif return Status; } //-------------------------------------------------------------------------- @@ -721,20 +661,6 @@ static VOID LEDControlThread(PMINI_ADAPTER Adapter) TURN_OFF_LED(1<device_removed) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"Device removed hence exiting from Led Thread.."); - return ; //-ENODEV; - } - #endif - #if 0 - if((GPIO_num != DISABLE_GPIO_NUM) && - ((currdriverstate != FW_DOWNLOAD) && - (currdriverstate != NORMAL_OPERATION) && - (currdriverstate != IDLEMODE_EXIT))) - TURN_OFF_LED(1<DriverState; - #if 0 - LedGpioInit(Adapter); - Adapter->LEDInfo.bLedInitDone = TRUE; - #endif BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex, &dummyIndex, currdriverstate); if(GPIO_num != DISABLE_GPIO_NUM) @@ -768,13 +690,6 @@ static VOID LEDControlThread(PMINI_ADAPTER Adapter) { //BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: FW_DN_DONE called\n"); currdriverstate = FW_DOWNLOAD; - #if 0 - if(Adapter->LEDInfo.bLedInitDone == FALSE) - { - LedGpioInit(Adapter); - Adapter->LEDInfo.bLedInitDone = TRUE; - } - #endif BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex, &dummyIndex, currdriverstate); if(GPIO_num != DISABLE_GPIO_NUM) @@ -796,12 +711,6 @@ static VOID LEDControlThread(PMINI_ADAPTER Adapter) break; case SHUTDOWN_EXIT: - #if 0 - if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_PMU_SHUTDOWN) - { - LedGpioInit(Adapter); - } - #endif //no break, continue to NO_NETWORK_ENTRY state as well. case NO_NETWORK_ENTRY: @@ -875,34 +784,6 @@ static VOID LEDControlThread(PMINI_ADAPTER Adapter) break; case IDLEMODE_EXIT: { -#if 0 - UCHAR GPIO_num_tx = DISABLE_GPIO_NUM; - UCHAR GPIO_num_rx = DISABLE_GPIO_NUM; - UCHAR uiTxLedIndex = 0; - UCHAR uiRxLedIndex = 0; - - currdriverstate = IDLEMODE_EXIT; - if(DEVICE_POWERSAVE_MODE_AS_PMU_SHUTDOWN == Adapter->ulPowerSaveMode) - { - LedGpioInit(Adapter); - } - BcmGetGPIOPinInfo(Adapter, &GPIO_num_tx, &GPIO_num_rx, &uiTxLedIndex,&uiRxLedIndex,currdriverstate); - - Adapter->LEDInfo.bIdle_led_off = FALSE; - - if((GPIO_num_tx == DISABLE_GPIO_NUM) && (GPIO_num_rx == DISABLE_GPIO_NUM)) - { - GPIO_num = DISABLE_GPIO_NUM ; - } - else - { - timeout = 50; - if(Adapter->LEDInfo.bIdleMode_tx_from_host) - LED_Blink(Adapter, 1<> 14) & 1) == 1) - { - // EEPROM_SPI_Q_STATUS1_REG will be cleared only if write back to that. - value = (0x1 << 14); - wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG,&value, sizeof(value)); - udelay(1000); - uiRetries--; - if(uiRetries == 0) - { - return FALSE; - } - value = 0; - rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); - } - return TRUE; - - -} - - -//----------------------------------------------------------------------------- -// Procedure: ReadBeceemEEPROMBulk -// -// Description: This routine reads 16Byte data from EEPROM -// -// Arguments: -// Adapter - ptr to Adapter object instance -// dwAddress - EEPROM Offset to read the data from. -// pdwData - Pointer to double word where data needs to be stored in. -// -// Returns: -// OSAL_STATUS_CODE: -//----------------------------------------------------------------------------- - -INT ReadBeceemEEPROMBulk(PMINI_ADAPTER Adapter,DWORD dwAddress, DWORD *pdwData) -{ - DWORD dwRetries = 16; - DWORD dwIndex = 0; - UINT value, tmpVal; - - - value = 0; - rdmalt (Adapter, 0x0f003008, &value, sizeof(value)); - - //read 0x0f003020 untill bit 1 of 0x0f003008 is set. - while(((value >> 1) & 1) == 0) - { - - rdmalt (Adapter, 0x0f003020, &tmpVal, sizeof(tmpVal)); - dwRetries--; - if(dwRetries == 0) - { - return -1; - } - value = 0; - rdmalt (Adapter, 0x0f003008, &value, sizeof(value)); - } - - value = dwAddress | 0xfb000000; - wrmalt (Adapter, 0x0f003018, &value, sizeof(value)); - - udelay(1000); - value = 0; - for(dwIndex = 0;dwIndex < 4 ; dwIndex++) - { - value = 0; - rdmalt (Adapter, 0x0f003020, &value, sizeof(value)); - pdwData[dwIndex] = value; - - value = 0; - rdmalt (Adapter, 0x0f003020, &value, sizeof(value)); - pdwData[dwIndex] |= (value << 8); - - value = 0; - rdmalt (Adapter, 0x0f003020, &value, sizeof(value)); - pdwData[dwIndex] |= (value << 16); - - value = 0; - rdmalt (Adapter, 0x0f003020, &value, sizeof(value)); - pdwData[dwIndex] |= (value << 24); - - } - return 0; -} - -//----------------------------------------------------------------------------- -// Procedure: ReadBeceemEEPROM -// -// Description: This routine reads 4Byte data from EEPROM -// -// Arguments: -// Adapter - ptr to Adapter object instance -// dwAddress - EEPROM Offset to read the data from. -// pdwData - Pointer to double word where data needs to be stored in. -// -// Returns: -// OSAL_STATUS_CODE: -//----------------------------------------------------------------------------- - -INT ReadBeceemEEPROM(PMINI_ADAPTER Adapter,DWORD dwAddress, DWORD *pdwData) -{ - - DWORD dwReadValue = 0; - DWORD dwRetries = 16, dwCompleteWord = 0; - UINT value, tmpVal; - - rdmalt(Adapter, 0x0f003008, &value, sizeof(value)); - while (((value >> 1) & 1) == 0) { - rdmalt(Adapter, 0x0f003020, &tmpVal, sizeof(tmpVal)); - - if (dwRetries == 0) { - return -1; - } - rdmalt(Adapter, 0x0f003008, &value, sizeof(value)); - } - - - //wrm (0x0f003018, 0xNbXXXXXX) // N is the number of bytes u want to read (0 means 1, f means 16, b is the opcode for page read) - // Follow it up by N executions of rdm(0x0f003020) to read the rxed bytes from rx queue. - dwAddress |= 0x3b000000; - wrmalt(Adapter, 0x0f003018,&dwAddress,4); - mdelay(10); - rdmalt(Adapter, 0x0f003020,&dwReadValue,4); - dwCompleteWord=dwReadValue; - rdmalt(Adapter, 0x0f003020,&dwReadValue,4); - dwCompleteWord|=(dwReadValue<<8); - rdmalt(Adapter, 0x0f003020,&dwReadValue,4); - dwCompleteWord|=(dwReadValue<<16); - rdmalt(Adapter, 0x0f003020,&dwReadValue,4); - dwCompleteWord|=(dwReadValue<<24); - - *pdwData = dwCompleteWord; - - return 0; -} -#endif INT ReadMacAddressFromNVM(PMINI_ADAPTER Adapter) { - INT Status=0, i; - unsigned char puMacAddr[6] = {0}; - INT AllZeroMac = 0; - INT AllFFMac = 0; + INT Status; + unsigned char puMacAddr[6]; Status = BeceemNVMRead(Adapter, (PUINT)&puMacAddr[0], INIT_PARAMS_1_MACADDRESS_ADDRESS, MAC_ADDRESS_SIZE); - if(Status != STATUS_SUCCESS) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Error in Reading the mac Addres with status :%d", Status); - return Status; - } - - memcpy(Adapter->dev->dev_addr, puMacAddr, MAC_ADDRESS_SIZE); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Modem MAC Addr :"); - BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_PRINTK, 0, DBG_LVL_ALL,&Adapter->dev->dev_addr[0],MAC_ADDRESS_SIZE); - for(i=0;idev->dev_addr[i] == 0x00) - AllZeroMac++; - if(Adapter->dev->dev_addr[i] == 0xFF) - AllFFMac++; - - } - //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "\n"); - if(AllZeroMac == MAC_ADDRESS_SIZE) - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Warning :: MAC Address has all 00's"); - if(AllFFMac == MAC_ADDRESS_SIZE) - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Warning :: MAC Address has all FF's"); + if(Status == STATUS_SUCCESS) + memcpy(Adapter->dev->dev_addr, puMacAddr, MAC_ADDRESS_SIZE); return Status; - } //----------------------------------------------------------------------------- @@ -476,7 +340,7 @@ INT BeceemEEPROMBulkRead( ReadBeceemEEPROMBulk(Adapter,uiTempOffset,(PUINT)&uiData[0],4); if(uiBytesRemaining >= (MAX_RW_SIZE - uiExtraBytes)) { - OsalMemMove(pBuffer,(((PUCHAR)&uiData[0])+uiExtraBytes),MAX_RW_SIZE - uiExtraBytes); + memcpy(pBuffer,(((PUCHAR)&uiData[0])+uiExtraBytes),MAX_RW_SIZE - uiExtraBytes); uiBytesRemaining -= (MAX_RW_SIZE - uiExtraBytes); uiIndex += (MAX_RW_SIZE - uiExtraBytes); @@ -484,7 +348,7 @@ INT BeceemEEPROMBulkRead( } else { - OsalMemMove(pBuffer,(((PUCHAR)&uiData[0])+uiExtraBytes),uiBytesRemaining); + memcpy(pBuffer,(((PUCHAR)&uiData[0])+uiExtraBytes),uiBytesRemaining); uiIndex += uiBytesRemaining; uiOffset += uiBytesRemaining; uiBytesRemaining = 0; @@ -508,7 +372,7 @@ INT BeceemEEPROMBulkRead( * We read 4 Dwords of data */ if(0 == ReadBeceemEEPROMBulk(Adapter,uiOffset,&uiData[0],4)) { - OsalMemMove(pcBuff+uiIndex,&uiData[0],MAX_RW_SIZE); + memcpy(pcBuff+uiIndex,&uiData[0],MAX_RW_SIZE); uiOffset += MAX_RW_SIZE; uiBytesRemaining -= MAX_RW_SIZE; uiIndex += MAX_RW_SIZE; @@ -523,7 +387,7 @@ INT BeceemEEPROMBulkRead( { if(0 == ReadBeceemEEPROM(Adapter,uiOffset,&uiData[0])) { - OsalMemMove(pcBuff+uiIndex,&uiData[0],4); + memcpy(pcBuff+uiIndex,&uiData[0],4); uiOffset += 4; uiBytesRemaining -= 4; uiIndex +=4; @@ -540,7 +404,7 @@ INT BeceemEEPROMBulkRead( pCharBuff += uiIndex; if(0 == ReadBeceemEEPROM(Adapter,uiOffset,&uiData[0])) { - OsalMemMove(pCharBuff,&uiData[0],uiBytesRemaining);//copy only bytes requested. + memcpy(pCharBuff,&uiData[0],uiBytesRemaining);//copy only bytes requested. uiBytesRemaining = 0; } else @@ -571,7 +435,7 @@ INT BeceemEEPROMBulkRead( // - if failed. //----------------------------------------------------------------------------- -INT BeceemFlashBulkRead( +static INT BeceemFlashBulkRead( PMINI_ADAPTER Adapter, PUINT pBuffer, UINT uiOffset, @@ -653,16 +517,8 @@ INT BeceemFlashBulkRead( // //----------------------------------------------------------------------------- -UINT BcmGetFlashSize(PMINI_ADAPTER Adapter) +static UINT BcmGetFlashSize(PMINI_ADAPTER Adapter) { -#if 0 - if(Adapter->bDDRInitDone) - { - return rdm(Adapter,FLASH_CONTIGIOUS_START_ADDR_AFTER_INIT|FLASH_SIZE_ADDR); - } - - return rdm(Adapter,FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT|FLASH_SIZE_ADDR); -#endif if(IsFlash2x(Adapter)) return (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER)); else @@ -684,7 +540,7 @@ UINT BcmGetFlashSize(PMINI_ADAPTER Adapter) // //----------------------------------------------------------------------------- -UINT BcmGetEEPROMSize(PMINI_ADAPTER Adapter) +static UINT BcmGetEEPROMSize(PMINI_ADAPTER Adapter) { UINT uiData = 0; UINT uiIndex = 0; @@ -733,60 +589,6 @@ UINT BcmGetEEPROMSize(PMINI_ADAPTER Adapter) return 0; } -#if 0 -/***********************************************************************************/ -// -// WriteBeceemEEPROM: Writes 4 byte data to EEPROM offset. -// -// uiEEPROMOffset - Offset to be written to. -// uiData - Data to be written. -// -/***********************************************************************************/ - -INT WriteBeceemEEPROM(PMINI_ADAPTER Adapter,UINT uiEEPROMOffset, UINT uiData) -{ - INT Status = 0; - ULONG ulRdBk = 0; - ULONG ulRetryCount = 3; - UINT value; - - if(uiEEPROMOffset > EEPROM_END) - { - - return -1; - } - - uiData = htonl(uiData); - while(ulRetryCount--) - { - value = 0x06000000; - wrmalt(Adapter, 0x0F003018,&value, sizeof(value));//flush the EEPROM FIFO. - wrmalt(Adapter, 0x0F00301C,&uiData, sizeof(uiData)); - value = 0x3A000000 | uiEEPROMOffset; - wrmalt(Adapter, 0x0F003018,&value, sizeof(value)); - __udelay(100000); - //read back and verify. - Status = ReadBeceemEEPROM(Adapter,uiEEPROMOffset,(UINT *)&ulRdBk); - if(Status == 0) - { - if(ulRdBk == uiData) - { - return Status; - } - else - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "WriteBeceemEEPROM: Readback does not match\n"); - } - } - else - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "WriteBeceemEEPROM: Readback failed\n"); - } - } - - return 0; -} -#endif //----------------------------------------------------------------------------- // Procedure: FlashSectorErase @@ -973,7 +775,7 @@ static INT flashWrite( // need not write 0xFFFFFFFF because write requires an erase and erase will // make whole sector 0xFFFFFFFF. // - if (!OsalMemCompare(pData, uiErasePattern, MAX_RW_SIZE)) + if (!memcmp(pData, uiErasePattern, MAX_RW_SIZE)) { return 0; } @@ -1138,7 +940,7 @@ static INT flashWriteStatus( // need not write 0xFFFFFFFF because write requires an erase and erase will // make whole sector 0xFFFFFFFF. // - if (!OsalMemCompare(pData,uiErasePattern,MAX_RW_SIZE)) + if (!memcmp(pData,uiErasePattern,MAX_RW_SIZE)) { return 0; } @@ -1332,7 +1134,7 @@ static ULONG BcmFlashUnProtectBlock(PMINI_ADAPTER Adapter,UINT uiOffset, UINT ui // //----------------------------------------------------------------------------- -INT BeceemFlashBulkWrite( +static INT BeceemFlashBulkWrite( PMINI_ADAPTER Adapter, PUINT pBuffer, UINT uiOffset, @@ -1353,15 +1155,6 @@ INT BeceemFlashBulkWrite( UINT uiTemp = 0; UINT index = 0; UINT uiPartOffset = 0; - #if 0 - struct timeval tv1 = {0}; - struct timeval tv2 = {0}; - - struct timeval tr = {0}; - struct timeval te = {0}; - struct timeval tw = {0}; - struct timeval twv = {0}; - #endif #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) Status = bcmflash_raw_write((uiOffset/FLASH_PART_SIZE),(uiOffset % FLASH_PART_SIZE),( unsigned char *)pBuffer,uiNumBytes); @@ -1377,12 +1170,9 @@ INT BeceemFlashBulkWrite( uiCurrSectOffsetAddr = uiOffset & (Adapter->uiSectorSize - 1); uiSectBoundary = uiSectAlignAddr + Adapter->uiSectorSize; - //pTempBuff = OsalMemAlloc(MAX_SECTOR_SIZE,'!MVN'); - pTempBuff = OsalMemAlloc(Adapter->uiSectorSize ,"!MVN"); + pTempBuff = kmalloc(Adapter->uiSectorSize, GFP_KERNEL); if(NULL == pTempBuff) - { goto BeceemFlashBulkWrite_EXIT; - } // // check if the data to be written is overlapped accross sectors // @@ -1399,7 +1189,6 @@ INT BeceemFlashBulkWrite( uiNumSectTobeRead++; } } - #if 1 //Check whether Requested sector is writable or not in case of flash2x write. But if write call is // for DSD calibration, allow it without checking of sector permission @@ -1420,7 +1209,6 @@ INT BeceemFlashBulkWrite( index = index + 1 ; } } - #endif Adapter->SelectedChip = RESET_CHIP_SELECT; while(uiNumSectTobeRead) { @@ -1448,13 +1236,13 @@ INT BeceemFlashBulkWrite( if(uiNumSectTobeRead > 1) { - OsalMemMove(&pTempBuff[uiCurrSectOffsetAddr],pcBuffer,uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr)); + memcpy(&pTempBuff[uiCurrSectOffsetAddr],pcBuffer,uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr)); pcBuffer += ((uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr))); uiNumBytes -= (uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr)); } else { - OsalMemMove(&pTempBuff[uiCurrSectOffsetAddr],pcBuffer,uiNumBytes); + memcpy(&pTempBuff[uiCurrSectOffsetAddr],pcBuffer,uiNumBytes); } if(IsFlash2x(Adapter)) @@ -1503,7 +1291,7 @@ INT BeceemFlashBulkWrite( } else { - if(OsalMemCompare(ucReadBk,&pTempBuff[uiIndex],MAX_RW_SIZE)) + if(memcmp(ucReadBk,&pTempBuff[uiIndex],MAX_RW_SIZE)) { if(STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter,uiPartOffset+uiIndex,&pTempBuff[uiIndex])) { @@ -1541,10 +1329,8 @@ INT BeceemFlashBulkWrite( { BcmRestoreBlockProtectStatus(Adapter,ulStatus); } - if(pTempBuff) - { - OsalMemFree(pTempBuff,Adapter->uiSectorSize); - } + + kfree(pTempBuff); Adapter->SelectedChip = RESET_CHIP_SELECT; return Status; @@ -1599,14 +1385,10 @@ static INT BeceemFlashBulkWriteStatus( uiCurrSectOffsetAddr = uiOffset & (Adapter->uiSectorSize - 1); uiSectBoundary = uiSectAlignAddr + Adapter->uiSectorSize; - - -// pTempBuff = OsalMemAlloc(MAX_SECTOR_SIZE,'!MVN'); - pTempBuff = OsalMemAlloc(Adapter->uiSectorSize,"!MVN"); + pTempBuff = kmalloc(Adapter->uiSectorSize, GFP_KERNEL); if(NULL == pTempBuff) - { goto BeceemFlashBulkWriteStatus_EXIT; - } + // // check if the data to be written is overlapped accross sectors // @@ -1662,13 +1444,13 @@ static INT BeceemFlashBulkWriteStatus( if(uiNumSectTobeRead > 1) { - OsalMemMove(&pTempBuff[uiCurrSectOffsetAddr],pcBuffer,uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr)); + memcpy(&pTempBuff[uiCurrSectOffsetAddr],pcBuffer,uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr)); pcBuffer += ((uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr))); uiNumBytes -= (uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr)); } else { - OsalMemMove(&pTempBuff[uiCurrSectOffsetAddr],pcBuffer,uiNumBytes); + memcpy(&pTempBuff[uiCurrSectOffsetAddr],pcBuffer,uiNumBytes); } if(IsFlash2x(Adapter)) @@ -1698,25 +1480,10 @@ static INT BeceemFlashBulkWriteStatus( { for(uiIndex = 0;uiIndex < Adapter->uiSectorSize;uiIndex += MAX_RW_SIZE) { -#if 0 - if(0 == BeceemFlashBulkRead(Adapter,uiReadBk,uiOffsetFromSectStart+uiIndex + Adapter->ulFlashCalStart ,MAX_RW_SIZE)) - { - for(uiReadIndex = 0;uiReadIndex < 4; uiReadIndex++) - { - if(*((PUINT)&pTempBuff[uiIndex+uiReadIndex*4]) != uiReadBk[uiReadIndex]) - { - Status = -1; - goto BeceemFlashBulkWriteStatus_EXIT; - - } - } - - } -#endif if(STATUS_SUCCESS == BeceemFlashBulkRead(Adapter,(PUINT)ucReadBk,uiOffsetFromSectStart+uiIndex,MAX_RW_SIZE)) { - if(OsalMemCompare(ucReadBk,&pTempBuff[uiIndex],MAX_RW_SIZE)) + if(memcmp(ucReadBk,&pTempBuff[uiIndex],MAX_RW_SIZE)) { Status = STATUS_FAILURE; goto BeceemFlashBulkWriteStatus_EXIT; @@ -1747,10 +1514,8 @@ static INT BeceemFlashBulkWriteStatus( { BcmRestoreBlockProtectStatus(Adapter,ulStatus); } - if(pTempBuff) - { - OsalMemFree(pTempBuff,Adapter->uiSectorSize); - } + + kfree(pTempBuff); Adapter->SelectedChip = RESET_CHIP_SELECT; return Status; @@ -1771,7 +1536,7 @@ static INT BeceemFlashBulkWriteStatus( INT PropagateCalParamsFromEEPROMToMemory(PMINI_ADAPTER Adapter) { - PCHAR pBuff = OsalMemAlloc(BUFFER_4K,"3MVN"); + PCHAR pBuff = kmalloc(BUFFER_4K, GFP_KERNEL); UINT uiEepromSize = 0; UINT uiIndex = 0; UINT uiBytesToCopy = 0; @@ -1787,14 +1552,14 @@ INT PropagateCalParamsFromEEPROMToMemory(PMINI_ADAPTER Adapter) if(0 != BeceemEEPROMBulkRead(Adapter,&uiEepromSize,EEPROM_SIZE_OFFSET,4)) { - OsalMemFree(pBuff,BUFFER_4K); + kfree(pBuff); return -1; } uiEepromSize >>= 16; if(uiEepromSize > 1024*1024) { - OsalMemFree(pBuff,BUFFER_4K); + kfree(pBuff); return -1; } @@ -1820,7 +1585,7 @@ INT PropagateCalParamsFromEEPROMToMemory(PMINI_ADAPTER Adapter) wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC-4,&value, sizeof(value)); value = 0xbeadbead; wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC-8,&value, sizeof(value)); - OsalMemFree(pBuff,MAX_RW_SIZE); + kfree(pBuff); return Status; @@ -1873,16 +1638,13 @@ INT PropagateCalParamsFromFlashToMemory(PMINI_ADAPTER Adapter) return -1; } - pBuff = OsalMemAlloc(uiEepromSize, 0); - + pBuff = kmalloc(uiEepromSize, GFP_KERNEL); if ( pBuff == NULL ) - { return -1; - } if(0 != BeceemNVMRead(Adapter,(PUINT)pBuff,uiCalStartAddr, uiEepromSize)) { - OsalMemFree(pBuff, 0); + kfree(pBuff); return -1; } @@ -1905,7 +1667,7 @@ INT PropagateCalParamsFromFlashToMemory(PMINI_ADAPTER Adapter) uiBytesToCopy = MIN(BUFFER_4K,uiEepromSize); } - OsalMemFree(pBuff, 0); + kfree(pBuff); return Status; } @@ -1947,14 +1709,14 @@ static INT BeceemEEPROMReadBackandVerify( {// for the requests more than or equal to MAX_RW_SIZE bytes, use bulk read function to make the access faster. BeceemEEPROMBulkRead(Adapter,&auiData[0],uiOffset,MAX_RW_SIZE); - if(OsalMemCompare(&pBuffer[uiIndex],&auiData[0],MAX_RW_SIZE)) + if(memcmp(&pBuffer[uiIndex],&auiData[0],MAX_RW_SIZE)) { // re-write BeceemEEPROMBulkWrite(Adapter,(PUCHAR)(pBuffer+uiIndex),uiOffset,MAX_RW_SIZE,FALSE); mdelay(3); BeceemEEPROMBulkRead(Adapter,&auiData[0],uiOffset,MAX_RW_SIZE); - if(OsalMemCompare(&pBuffer[uiIndex],&auiData[0],MAX_RW_SIZE)) + if(memcmp(&pBuffer[uiIndex],&auiData[0],MAX_RW_SIZE)) { return -1; } @@ -1986,7 +1748,7 @@ static INT BeceemEEPROMReadBackandVerify( else { // Handle the reads less than 4 bytes... uiData = 0; - OsalMemMove(&uiData,((PUCHAR)pBuffer)+(uiIndex*sizeof(UINT)),uiNumBytes); + memcpy(&uiData,((PUCHAR)pBuffer)+(uiIndex*sizeof(UINT)),uiNumBytes); BeceemEEPROMBulkRead(Adapter,&uiRdbk,uiOffset,4); if(memcmp(&uiData, &uiRdbk, uiNumBytes)) @@ -2186,7 +1948,7 @@ INT BeceemEEPROMBulkWrite( if(uiBytesToCopy >= (16 -uiExtraBytes)) { - OsalMemMove((((PUCHAR)&uiData[0])+uiExtraBytes),pBuffer,MAX_RW_SIZE- uiExtraBytes); + memcpy((((PUCHAR)&uiData[0])+uiExtraBytes),pBuffer,MAX_RW_SIZE- uiExtraBytes); if ( STATUS_FAILURE == BeceemEEPROMWritePage( Adapter, uiData, uiTempOffset ) ) return STATUS_FAILURE; @@ -2197,7 +1959,7 @@ INT BeceemEEPROMBulkWrite( } else { - OsalMemMove((((PUCHAR)&uiData[0])+uiExtraBytes),pBuffer,uiBytesToCopy); + memcpy((((PUCHAR)&uiData[0])+uiExtraBytes),pBuffer,uiBytesToCopy); if ( STATUS_FAILURE == BeceemEEPROMWritePage( Adapter, uiData, uiTempOffset ) ) return STATUS_FAILURE; @@ -2233,7 +1995,7 @@ INT BeceemEEPROMBulkWrite( // To program non 16byte aligned data, read 16byte and then update. // BeceemEEPROMBulkRead(Adapter,&uiData[0],uiOffset,16); - OsalMemMove(&uiData[0],pBuffer+uiIndex,uiBytesToCopy); + memcpy(&uiData[0],pBuffer+uiIndex,uiBytesToCopy); if ( STATUS_FAILURE == BeceemEEPROMWritePage( Adapter, uiData, uiOffset ) ) @@ -2535,7 +2297,7 @@ INT BcmUpdateSectorSize(PMINI_ADAPTER Adapter,UINT uiSectorSize) // //----------------------------------------------------------------------------- -UINT BcmGetFlashSectorSize(PMINI_ADAPTER Adapter, UINT FlashSectorSizeSig, UINT FlashSectorSize) +static UINT BcmGetFlashSectorSize(PMINI_ADAPTER Adapter, UINT FlashSectorSizeSig, UINT FlashSectorSize) { UINT uiSectorSize = 0; UINT uiSectorSig = 0; @@ -2642,20 +2404,8 @@ static INT BcmInitEEPROMQueues(PMINI_ADAPTER Adapter) INT BcmInitNVM(PMINI_ADAPTER ps_adapter) { -#ifdef BCM_SHM_INTERFACE -#ifdef FLASH_DIRECT_ACCESS - unsigned int data,data1,data2 = 1; - wrm(ps_adapter, PAD_SELECT_REGISTER, &data2, 4); - data1 = rdm(ps_adapter,SYS_CFG,&data,4); - data1 = rdm(ps_adapter,SYS_CFG,&data,4); - data2 = (data | 0x80 | 0x8000); - wrm(ps_adapter,SYS_CFG, &data2,4); // over-write as Flash boot mode -#endif - ps_adapter->eNVMType = NVM_FLASH; -#else BcmValidateNvmType(ps_adapter); BcmInitEEPROMQueues(ps_adapter); -#endif if(ps_adapter->eNVMType == NVM_AUTODETECT) { @@ -2684,7 +2434,7 @@ INT BcmInitNVM(PMINI_ADAPTER ps_adapter) */ /***************************************************************************/ -INT BcmGetNvmSize(PMINI_ADAPTER Adapter) +static INT BcmGetNvmSize(PMINI_ADAPTER Adapter) { if(Adapter->eNVMType == NVM_EEPROM) { @@ -2708,7 +2458,7 @@ INT BcmGetNvmSize(PMINI_ADAPTER Adapter) // Returns: // //----------------------------------------------------------------------------- -VOID BcmValidateNvmType(PMINI_ADAPTER Adapter) +static VOID BcmValidateNvmType(PMINI_ADAPTER Adapter) { // @@ -2775,7 +2525,7 @@ INT BcmAllocFlashCSStructure(PMINI_ADAPTER psAdapter) if(psAdapter->psFlash2xCSInfo == NULL) { BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0,"Can't Allocate memory for Flash 2.x"); - bcm_kfree(psAdapter->psFlashCSInfo); + kfree(psAdapter->psFlashCSInfo); return -ENOMEM; } @@ -2783,8 +2533,8 @@ INT BcmAllocFlashCSStructure(PMINI_ADAPTER psAdapter) if(psAdapter->psFlash2xVendorInfo == NULL) { BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0,"Can't Allocate Vendor Info Memory for Flash 2.x"); - bcm_kfree(psAdapter->psFlashCSInfo); - bcm_kfree(psAdapter->psFlash2xCSInfo); + kfree(psAdapter->psFlashCSInfo); + kfree(psAdapter->psFlash2xCSInfo); return -ENOMEM; } @@ -2798,9 +2548,9 @@ INT BcmDeAllocFlashCSStructure(PMINI_ADAPTER psAdapter) BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0," Adapter structure point is NULL"); return -EINVAL; } - bcm_kfree(psAdapter->psFlashCSInfo); - bcm_kfree(psAdapter->psFlash2xCSInfo); - bcm_kfree(psAdapter->psFlash2xVendorInfo); + kfree(psAdapter->psFlashCSInfo); + kfree(psAdapter->psFlash2xCSInfo); + kfree(psAdapter->psFlash2xVendorInfo); return STATUS_SUCCESS ; } @@ -2954,7 +2704,7 @@ static INT ConvertEndianOfCSStructure(PFLASH_CS_INFO psFlashCSInfo) return STATUS_SUCCESS; } -INT IsSectionExistInVendorInfo(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL section) +static INT IsSectionExistInVendorInfo(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL section) { return ( Adapter->uiVendorExtnFlag && (Adapter->psFlash2xVendorInfo->VendorSection[section].AccessFlags & FLASH2X_SECTION_PRESENT) && @@ -3052,7 +2802,7 @@ static VOID UpdateVendorInfo(PMINI_ADAPTER Adapter) // //----------------------------------------------------------------------------- -INT BcmGetFlashCSInfo(PMINI_ADAPTER Adapter) +static INT BcmGetFlashCSInfo(PMINI_ADAPTER Adapter) { //FLASH_CS_INFO sFlashCsInfo = {0}; @@ -3070,7 +2820,6 @@ INT BcmGetFlashCSInfo(PMINI_ADAPTER Adapter) memset(Adapter->psFlashCSInfo, 0 ,sizeof(FLASH_CS_INFO)); memset(Adapter->psFlash2xCSInfo, 0 ,sizeof(FLASH2X_CS_INFO)); -#ifndef BCM_SHM_INTERFACE if(!Adapter->bDDRInitDone) { { @@ -3079,7 +2828,6 @@ INT BcmGetFlashCSInfo(PMINI_ADAPTER Adapter) } } -#endif // Reading first 8 Bytes to get the Flash Layout // MagicNumber(4 bytes) +FlashLayoutMinorVersion(2 Bytes) +FlashLayoutMajorVersion(2 Bytes) @@ -3147,9 +2895,7 @@ INT BcmGetFlashCSInfo(PMINI_ADAPTER Adapter) return STATUS_FAILURE; } ConvertEndianOf2XCSStructure(Adapter->psFlash2xCSInfo); -#ifndef BCM_SHM_INTERFACE BcmDumpFlash2XCSStructure(Adapter->psFlash2xCSInfo,Adapter); -#endif if((FLASH_CONTROL_STRUCT_SIGNATURE == Adapter->psFlash2xCSInfo->MagicNumber) && (SCSI_FIRMWARE_MINOR_VERSION <= MINOR_VERSION(Adapter->psFlash2xCSInfo->SCSIFirmwareVersion)) && (FLASH_SECTOR_SIZE_SIG == Adapter->psFlash2xCSInfo->FlashSectorSizeSig) && @@ -3181,21 +2927,10 @@ INT BcmGetFlashCSInfo(PMINI_ADAPTER Adapter) Concerns: what if CS sector size does not match with this sector size ??? what is the indication of AccessBitMap in CS in flash 2.x ???? */ -#ifndef BCM_SHM_INTERFACE Adapter->ulFlashID = BcmReadFlashRDID(Adapter); -#endif Adapter->uiFlashLayoutMajorVersion = uiFlashLayoutMajorVersion; - #if 0 - if(FLASH_PART_SST25VF080B == Adapter->ulFlashID) - { - // - // 1MB flash has been selected. we have to use 64K as sector size no matter what is kept in FLASH_CS. - // - Adapter->uiSectorSize = 0x10000; - } - #endif return STATUS_SUCCESS ; } @@ -3214,7 +2949,7 @@ INT BcmGetFlashCSInfo(PMINI_ADAPTER Adapter) // //----------------------------------------------------------------------------- -NVM_TYPE BcmGetNvmType(PMINI_ADAPTER Adapter) +static NVM_TYPE BcmGetNvmType(PMINI_ADAPTER Adapter) { UINT uiData = 0; @@ -3568,39 +3303,6 @@ INT BcmFlash2xBulkWrite( } -/** -* ReadDSDHeader : Read the DSD map for the DSD Section val provided in Argument. -* @Adapter : Beceem Private Data Structure -* @psDSDHeader :Pointer of the buffer where header has to be read -* @dsd :value of the Dyanmic DSD like DSD0 of DSD1 or DSD2 -* -* Return Value:- -* if suceeds return STATUS_SUCCESS or negative error code. -**/ -INT ReadDSDHeader(PMINI_ADAPTER Adapter, PDSD_HEADER psDSDHeader, FLASH2X_SECTION_VAL dsd) -{ - INT Status = STATUS_SUCCESS; - - Status =BcmFlash2xBulkRead(Adapter, - (PUINT)psDSDHeader, - dsd, - Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader, - sizeof(DSD_HEADER)); - if(Status == STATUS_SUCCESS) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSDImageMagicNumber :0X%x", ntohl(psDSDHeader->DSDImageMagicNumber)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSDImageSize :0X%x ",ntohl(psDSDHeader->DSDImageSize)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSDImageCRC :0X%x",ntohl(psDSDHeader->DSDImageCRC)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSDImagePriority :0X%x",ntohl(psDSDHeader->DSDImagePriority)); - } - else - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"DSD Header read is failed with status :%d", Status); - } - - return Status; -} - /** * BcmGetActiveDSD : Set the Active DSD in Adapter Structure which has to be dumped in DDR * @Adapter :-Drivers private Data Structure @@ -3609,7 +3311,7 @@ INT ReadDSDHeader(PMINI_ADAPTER Adapter, PDSD_HEADER psDSDHeader, FLASH2X_SECTIO * Return STATUS_SUCESS if get sucess in setting the right DSD else negaive error code * **/ -INT BcmGetActiveDSD(PMINI_ADAPTER Adapter) +static INT BcmGetActiveDSD(PMINI_ADAPTER Adapter) { FLASH2X_SECTION_VAL uiHighestPriDSD = 0 ; @@ -3647,39 +3349,6 @@ INT BcmGetActiveDSD(PMINI_ADAPTER Adapter) return STATUS_SUCCESS; } -/** -* ReadISOUnReservedBytes : Read the ISO map for the ISO Section val provided in Argument. -* @Adapter : Driver Private Data Structure -* @psISOHeader :Pointer of the location where header has to be read -* @IsoImage :value of the Dyanmic ISO like ISO_IMAGE1 of ISO_IMAGE2 -* -* Return Value:- -* if suceeds return STATUS_SUCCESS or negative error code. -**/ - -INT ReadISOHeader(PMINI_ADAPTER Adapter, PISO_HEADER psISOHeader, FLASH2X_SECTION_VAL IsoImage) -{ - INT Status = STATUS_SUCCESS; - - Status = BcmFlash2xBulkRead(Adapter, - (PUINT)psISOHeader, - IsoImage, - 0, - sizeof(ISO_HEADER)); - - if(Status == STATUS_SUCCESS) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISOImageMagicNumber :0X%x", ntohl(psISOHeader->ISOImageMagicNumber)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISOImageSize :0X%x ",ntohl(psISOHeader->ISOImageSize)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISOImageCRC :0X%x",ntohl(psISOHeader->ISOImageCRC)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISOImagePriority :0X%x",ntohl(psISOHeader->ISOImagePriority)); - } - else - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "ISO Header Read failed"); - } - return Status; -} /** * BcmGetActiveISO :- Set the Active ISO in Adapter Data Structue @@ -3691,7 +3360,7 @@ INT ReadISOHeader(PMINI_ADAPTER Adapter, PISO_HEADER psISOHeader, FLASH2X_SECTIO * **/ -INT BcmGetActiveISO(PMINI_ADAPTER Adapter) +static INT BcmGetActiveISO(PMINI_ADAPTER Adapter) { INT HighestPriISO = 0 ; @@ -4588,7 +4257,7 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut) } - bcm_kfree(Buff); + kfree(Buff); return Status; } @@ -4789,7 +4458,7 @@ Return Value:- Success :- Base Address of the Flash **/ -INT GetFlashBaseAddr(PMINI_ADAPTER Adapter) +static INT GetFlashBaseAddr(PMINI_ADAPTER Adapter) { UINT uiBaseAddr = 0; @@ -4866,20 +4535,6 @@ INT BcmCopySection(PMINI_ADAPTER Adapter, return -EINVAL; } - #if 0 - else - { - if((SrcSection == VSA0) || (SrcSection == VSA1) || (SrcSection == VSA2)) - { - if((DstSection != VSA0) && (DstSection != VSA1) && (DstSection != VSA2)) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Source and Destion secton is not of same type"); - return -EINVAL; - } - } - - } - #endif //if offset zero means have to copy complete secton if(numOfBytes == 0) @@ -4954,7 +4609,7 @@ INT BcmCopySection(PMINI_ADAPTER Adapter, BytesToBeCopied = numOfBytes; } }while(numOfBytes > 0) ; - bcm_kfree(pBuff); + kfree(pBuff); Adapter->bHeaderChangeAllowed = FALSE ; return Status; } @@ -4979,14 +4634,6 @@ INT SaveHeaderIfPresent(PMINI_ADAPTER Adapter, PUCHAR pBuff, UINT uiOffset) UINT uiSectAlignAddr = 0; UINT sig = 0; - #if 0 - //if Chenges in Header is allowed, Return back - if(Adapter->bHeaderChangeAllowed == TRUE) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Header Change is allowed"); - return STATUS_SUCCESS ; - } - #endif //making the offset sector alligned uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); @@ -5024,7 +4671,7 @@ INT SaveHeaderIfPresent(PMINI_ADAPTER Adapter, PUCHAR pBuff, UINT uiOffset) //Replace Buffer content with Header memcpy(pBuff +offsetToProtect,pTempBuff,HeaderSizeToProtect); - bcm_kfree(pTempBuff); + kfree(pTempBuff); } if(bHasHeader && Adapter->bSigCorrupted) { @@ -5044,29 +4691,7 @@ INT SaveHeaderIfPresent(PMINI_ADAPTER Adapter, PUCHAR pBuff, UINT uiOffset) return STATUS_SUCCESS ; } -INT BcmMakeFlashCSActive(PMINI_ADAPTER Adapter, UINT offset) -{ - UINT GPIOConfig = 0 ; - - - if(Adapter->bFlashRawRead == FALSE) - { - //Applicable for Flash2.x - if(IsFlash2x(Adapter) == FALSE) - return STATUS_SUCCESS; - } - if(offset/FLASH_PART_SIZE) - { - //bit[14..12] -> will select make Active CS1, CS2 or CS3 - // Select CS1, CS2 and CS3 (CS0 is dedicated pin) - rdmalt(Adapter,FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4); - GPIOConfig |= (7 << 12); - wrmalt(Adapter,FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4); - } - - return STATUS_SUCCESS ; -} /** BcmDoChipSelect : This will selcet the appropriate chip for writing. @Adapater :- Bcm Driver Private Data Structure @@ -5074,7 +4699,7 @@ BcmDoChipSelect : This will selcet the appropriate chip for writing. OutPut:- Select the Appropriate chip and retrn status Sucess **/ -INT BcmDoChipSelect(PMINI_ADAPTER Adapter, UINT offset) +static INT BcmDoChipSelect(PMINI_ADAPTER Adapter, UINT offset) { UINT FlashConfig = 0; INT ChipNum = 0; @@ -5365,39 +4990,6 @@ INT WriteToFlashWithoutSectorErase(PMINI_ADAPTER Adapter, return Status; } -#if 0 -UINT getNumOfSubSectionWithWRPermisson(PMINI_ADAPTER Adapter, SECTION_TYPE secType) -{ - - UINT numOfWRSubSec = 0; - switch(secType) - { - case ISO : - if(IsSectionWritable(Adapter,ISO_IMAGE1)) - numOfWRSubSec = numOfWRSubSec + 1; - if(IsSectionWritable(Adapter,ISO_IMAGE2)) - numOfWRSubSec = numOfWRSubSec + 1; - break; - - case DSD : - if(IsSectionWritable(Adapter,DSD2)) - numOfWRSubSec = numOfWRSubSec + 1; - if(IsSectionWritable(Adapter,DSD1)) - numOfWRSubSec = numOfWRSubSec + 1; - if(IsSectionWritable(Adapter,DSD0)) - numOfWRSubSec = numOfWRSubSec + 1; - break ; - - case VSA : - //for VSA Add code Here - default : - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Invalid secton<%d> is passed", secType);\ - numOfWRSubSec = 0; - - } - return numOfWRSubSec; -} -#endif BOOLEAN IsSectionExistInFlash(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL section) { @@ -5479,7 +5071,7 @@ INT IsSectionWritable(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL Section) return Status ; } -INT CorruptDSDSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) +static INT CorruptDSDSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) { PUCHAR pBuff = NULL; @@ -5543,16 +5135,16 @@ INT CorruptDSDSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) else { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"BCM Signature is not present in header"); - bcm_kfree(pBuff); + kfree(pBuff); return STATUS_FAILURE; } - bcm_kfree(pBuff); + kfree(pBuff); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Corrupted the signature"); return STATUS_SUCCESS ; } -INT CorruptISOSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) +static INT CorruptISOSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) { PUCHAR pBuff = NULL; @@ -5593,14 +5185,14 @@ INT CorruptISOSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) else { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"BCM Signature is not present in header"); - bcm_kfree(pBuff); + kfree(pBuff); return STATUS_FAILURE; } BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Corrupted the signature"); BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,pBuff,MAX_RW_SIZE); - bcm_kfree(pBuff); + kfree(pBuff); return STATUS_SUCCESS ; } diff --git a/trunk/drivers/staging/bcm/nvm.h b/trunk/drivers/staging/bcm/nvm.h index 6ec6ca85b501..651b5a455b32 100644 --- a/trunk/drivers/staging/bcm/nvm.h +++ b/trunk/drivers/staging/bcm/nvm.h @@ -323,15 +323,6 @@ typedef struct _ISO_HEADER -#ifdef BCM_SHM_INTERFACE - -#define FLASH_ADDR_MASK 0x1F000000 -extern int bcmflash_raw_read(unsigned int flash_id, unsigned int offset, unsigned char *inbuf, unsigned int len); -extern int bcmflash_raw_write(unsigned int flash_id, unsigned int offset, unsigned char *outbuf, unsigned int len); -extern int bcmflash_raw_writenoerase(unsigned int flash_id, unsigned int offset, unsigned char *outbuf, unsigned int len); - - -#endif #define FLASH_CONTIGIOUS_START_ADDR_AFTER_INIT 0x1C000000 #define FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT 0x1F000000 @@ -414,76 +405,5 @@ extern int bcmflash_raw_writenoerase(unsigned int flash_id, unsigned int offset, #define FIELD_OFFSET_IN_HEADER(HeaderPointer,Field) ((PUCHAR)&((HeaderPointer)(NULL))->Field - (PUCHAR)(NULL)) -#if 0 -INT BeceemEEPROMBulkRead( - PMINI_ADAPTER Adapter, - PUINT pBuffer, - UINT uiOffset, - UINT uiNumBytes); - - -INT BeceemFlashBulkRead( - PMINI_ADAPTER Adapter, - PUINT pBuffer, - UINT uiOffset, - UINT uiNumBytes); - -UINT BcmGetEEPROMSize(PMINI_ADAPTER Adapter); - -UINT BcmGetFlashSize(PMINI_ADAPTER Adapter); - -UINT BcmGetFlashSectorSize(PMINI_ADAPTER Adapter); - - - -INT BeceemFlashBulkWrite( - PMINI_ADAPTER Adapter, - PUINT pBuffer, - UINT uiOffset, - UINT uiNumBytes, - BOOLEAN bVerify); - -INT PropagateCalParamsFromFlashToMemory(PMINI_ADAPTER Adapter); - -INT PropagateCalParamsFromEEPROMToMemory(PMINI_ADAPTER Adapter); - - -INT BeceemEEPROMBulkWrite( - PMINI_ADAPTER Adapter, - PUCHAR pBuffer, - UINT uiOffset, - UINT uiNumBytes, - BOOLEAN bVerify); - - -INT ReadBeceemEEPROM(PMINI_ADAPTER Adapter,UINT dwAddress, UINT *pdwData); - -NVM_TYPE BcmGetNvmType(PMINI_ADAPTER Adapter); - -INT BeceemNVMRead( - PMINI_ADAPTER Adapter, - PUINT pBuffer, - UINT uiOffset, - UINT uiNumBytes); - -INT BeceemNVMWrite( - PMINI_ADAPTER Adapter, - PUINT pBuffer, - UINT uiOffset, - UINT uiNumBytes, - BOOLEAN bVerify); - -INT ReadMacAddressFromEEPROM(PMINI_ADAPTER Adapter); - -INT BcmUpdateSectorSize(PMINI_ADAPTER Adapter,UINT uiSectorSize); - -INT BcmInitNVM(PMINI_ADAPTER Adapter); - -VOID BcmValidateNvmType(PMINI_ADAPTER Adapter); - -VOID BcmGetFlashCSInfo(PMINI_ADAPTER Adapter); - -#endif - #endif diff --git a/trunk/drivers/staging/bcm/osal_misc.h b/trunk/drivers/staging/bcm/osal_misc.h deleted file mode 100644 index ff4adde17cd8..000000000000 --- a/trunk/drivers/staging/bcm/osal_misc.h +++ /dev/null @@ -1,49 +0,0 @@ - /*++ - - Copyright (c) Beceem Communications Inc. - - Module Name: - OSAL_Misc.h - - Abstract: - Provides the OS Abstracted macros to access: - Linked Lists - Dispatcher Objects(Events,Semaphores,Spin Locks and the like) - Files - - - Revision History: - Who When What - -------- -------- ---------------------------------------------- - Name Date Created/reviewed/modified - Rajeev 24/1/08 Created - Notes: - - --*/ -#ifndef _OSAL_MISC_H_ -#define _OSAL_MISC_H_ -//OSAL Macros -//OSAL Primitives -typedef PUCHAR POSAL_NW_PACKET ; //Nw packets - - -#define OsalMemAlloc(n,t) kmalloc(n,GFP_KERNEL) - -#define OsalMemFree(x,n) bcm_kfree(x) - -#define OsalMemMove(dest, src, len) \ -{ \ - memcpy(dest,src, len); \ -} - -#define OsalZeroMemory(pDest, Len) \ -{ \ - memset(pDest,0,Len); \ -} - -//#define OsalMemSet(pSrc,Char,Len) memset(pSrc,Char,Len) - -bool OsalMemCompare(void *dest, void *src, UINT len); - -#endif - diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh.c b/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh.c index 4c613da3553a..6738983e2d5c 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh.c +++ b/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh.c @@ -16,13 +16,14 @@ /* ****************** BCMSDH Interface Functions *************************** */ #include +#include #include #include #include +#include #include #include #include -#include #include /* BRCM API for SDIO clients (such as wl, dhd) */ diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c b/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c index 9028cd01d9d0..be33696b8f74 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c +++ b/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c @@ -20,8 +20,7 @@ #define __UNDEF_NO_VERSION__ -#include - +#include #include #include @@ -189,7 +188,7 @@ int bcmsdh_probe(struct device *dev) } #endif /* defined(OOB_INTR_ONLY) */ /* allocate SDIO Host Controller state info */ - osh = osl_attach(dev, PCI_BUS, false); + osh = osl_attach(dev, PCI_BUS); if (!osh) { SDLX_MSG(("%s: osl_attach failed\n", __func__)); goto err; @@ -385,7 +384,7 @@ bcmsdh_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) SDLX_MSG(("%s: Disabling TI FlashMedia Controller.\n", __func__)); - osh = osl_attach(pdev, PCI_BUS, false); + osh = osl_attach(pdev, PCI_BUS); if (!osh) { SDLX_MSG(("%s: osl_attach failed\n", __func__)); goto err; @@ -420,7 +419,7 @@ bcmsdh_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) */ /* allocate SDIO Host Controller state info */ - osh = osl_attach(pdev, PCI_BUS, false); + osh = osl_attach(pdev, PCI_BUS); if (!osh) { SDLX_MSG(("%s: osl_attach failed\n", __func__)); goto err; diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c index f6c9c4541813..039f114130d2 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -14,11 +14,12 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include +#include #include #include #include -#include #include +#include #include /* SDIO Device and Protocol Specs */ #include /* SDIO Host Controller Specification */ #include /* bcmsdh to/from specific controller APIs */ diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c b/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c index ae7b566b11d7..14f73fd28760 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c +++ b/trunk/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c @@ -15,7 +15,9 @@ */ #include #include /* request_irq() */ +#include #include +#include #include #include /* SDIO Specs */ #include /* bcmsdh to/from specific controller APIs */ diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c b/trunk/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c index bcbaac9bcdcc..0d14f6c1fcfa 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c +++ b/trunk/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c @@ -15,6 +15,7 @@ */ #include +#include #include #include diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/dhd_common.c b/trunk/drivers/staging/brcm80211/brcmfmac/dhd_common.c index 703188fc28ec..f7ffea69233c 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/dhd_common.c +++ b/trunk/drivers/staging/brcm80211/brcmfmac/dhd_common.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c b/trunk/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c index f647034f36d6..bb3c7b8c4b98 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c +++ b/trunk/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c @@ -14,7 +14,7 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +#include #include #include diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/dhd_linux.c b/trunk/drivers/staging/brcm80211/brcmfmac/dhd_linux.c index bbbe7c5f7492..d7ad3e44dd78 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/dhd_linux.c +++ b/trunk/drivers/staging/brcm80211/brcmfmac/dhd_linux.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -1190,7 +1189,7 @@ void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt) /* Process special event packets and then discard them */ if (ntoh16(skb->protocol) == ETHER_TYPE_BRCM) dhd_wl_host_event(dhd, &ifidx, - skb->mac_header, + skb_mac_header(skb), &event, &data); ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]); @@ -1621,6 +1620,51 @@ static int dhd_ethtool(dhd_info_t *dhd, void *uaddr) return 0; } +static s16 linuxbcmerrormap[] = { 0, /* 0 */ + -EINVAL, /* BCME_ERROR */ + -EINVAL, /* BCME_BADARG */ + -EINVAL, /* BCME_BADOPTION */ + -EINVAL, /* BCME_NOTUP */ + -EINVAL, /* BCME_NOTDOWN */ + -EINVAL, /* BCME_NOTAP */ + -EINVAL, /* BCME_NOTSTA */ + -EINVAL, /* BCME_BADKEYIDX */ + -EINVAL, /* BCME_RADIOOFF */ + -EINVAL, /* BCME_NOTBANDLOCKED */ + -EINVAL, /* BCME_NOCLK */ + -EINVAL, /* BCME_BADRATESET */ + -EINVAL, /* BCME_BADBAND */ + -E2BIG, /* BCME_BUFTOOSHORT */ + -E2BIG, /* BCME_BUFTOOLONG */ + -EBUSY, /* BCME_BUSY */ + -EINVAL, /* BCME_NOTASSOCIATED */ + -EINVAL, /* BCME_BADSSIDLEN */ + -EINVAL, /* BCME_OUTOFRANGECHAN */ + -EINVAL, /* BCME_BADCHAN */ + -EFAULT, /* BCME_BADADDR */ + -ENOMEM, /* BCME_NORESOURCE */ + -EOPNOTSUPP, /* BCME_UNSUPPORTED */ + -EMSGSIZE, /* BCME_BADLENGTH */ + -EINVAL, /* BCME_NOTREADY */ + -EPERM, /* BCME_NOTPERMITTED */ + -ENOMEM, /* BCME_NOMEM */ + -EINVAL, /* BCME_ASSOCIATED */ + -ERANGE, /* BCME_RANGE */ + -EINVAL, /* BCME_NOTFOUND */ + -EINVAL, /* BCME_WME_NOT_ENABLED */ + -EINVAL, /* BCME_TSPEC_NOTFOUND */ + -EINVAL, /* BCME_ACM_NOTSUPPORTED */ + -EINVAL, /* BCME_NOT_WME_ASSOCIATION */ + -EIO, /* BCME_SDIO_ERROR */ + -ENODEV, /* BCME_DONGLE_DOWN */ + -EINVAL, /* BCME_VERSION */ + -EIO, /* BCME_TXFAIL */ + -EIO, /* BCME_RXFAIL */ + -EINVAL, /* BCME_NODEVICE */ + -EINVAL, /* BCME_NMODE_DISABLED */ + -ENODATA, /* BCME_NONRESIDENT */ +}; + static int dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) { dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net); @@ -1742,7 +1786,12 @@ static int dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) if (buf) kfree(buf); - return OSL_ERROR(bcmerror); + if (bcmerror > 0) + bcmerror = 0; + else if (bcmerror < BCME_LAST) + bcmerror = BCME_ERROR; + + return linuxbcmerrormap[-bcmerror]; } static int dhd_stop(struct net_device *net) @@ -1816,7 +1865,7 @@ static int dhd_open(struct net_device *net) osl_t *dhd_osl_attach(void *pdev, uint bustype) { - return osl_attach(pdev, bustype, true); + return osl_attach(pdev, bustype); } void dhd_osl_detach(osl_t *osh) diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/dhd_linux_sched.c b/trunk/drivers/staging/brcm80211/brcmfmac/dhd_linux_sched.c index bf8df9801030..c66f1c2941e2 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/dhd_linux_sched.c +++ b/trunk/drivers/staging/brcm80211/brcmfmac/dhd_linux_sched.c @@ -16,7 +16,6 @@ #include #include #include -#include int setScheduler(struct task_struct *p, int policy, struct sched_param *param) { diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c b/trunk/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c index b2281d9dfdcf..66884d47e834 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c +++ b/trunk/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c @@ -16,6 +16,7 @@ #include #include +#include #include #include diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c b/trunk/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c index 3f29488d9c72..6433a9241b4e 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c +++ b/trunk/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c @@ -16,7 +16,6 @@ #include #include -#include #include #include @@ -705,7 +704,7 @@ wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, u16 action) if (ssid && ssid->SSID_len) params_size += sizeof(struct wlc_ssid); - params = (struct wl_iscan_params *)kzalloc(params_size, GFP_KERNEL); + params = kzalloc(params_size, GFP_KERNEL); if (unlikely(!params)) return -ENOMEM; memset(params, 0, params_size); @@ -2794,53 +2793,52 @@ static void wl_init_eloop_handler(struct wl_event_loop *el) static s32 wl_init_priv_mem(struct wl_priv *wl) { - wl->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL); + wl->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL); if (unlikely(!wl->scan_results)) { WL_ERR(("Scan results alloc failed\n")); goto init_priv_mem_out; } - wl->conf = (void *)kzalloc(sizeof(*wl->conf), GFP_KERNEL); + wl->conf = kzalloc(sizeof(*wl->conf), GFP_KERNEL); if (unlikely(!wl->conf)) { WL_ERR(("wl_conf alloc failed\n")); goto init_priv_mem_out; } - wl->profile = (void *)kzalloc(sizeof(*wl->profile), GFP_KERNEL); + wl->profile = kzalloc(sizeof(*wl->profile), GFP_KERNEL); if (unlikely(!wl->profile)) { WL_ERR(("wl_profile alloc failed\n")); goto init_priv_mem_out; } - wl->bss_info = (void *)kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); + wl->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); if (unlikely(!wl->bss_info)) { WL_ERR(("Bss information alloc failed\n")); goto init_priv_mem_out; } - wl->scan_req_int = - (void *)kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL); + wl->scan_req_int = kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL); if (unlikely(!wl->scan_req_int)) { WL_ERR(("Scan req alloc failed\n")); goto init_priv_mem_out; } - wl->ioctl_buf = (void *)kzalloc(WL_IOCTL_LEN_MAX, GFP_KERNEL); + wl->ioctl_buf = kzalloc(WL_IOCTL_LEN_MAX, GFP_KERNEL); if (unlikely(!wl->ioctl_buf)) { WL_ERR(("Ioctl buf alloc failed\n")); goto init_priv_mem_out; } - wl->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); + wl->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); if (unlikely(!wl->extra_buf)) { WL_ERR(("Extra buf alloc failed\n")); goto init_priv_mem_out; } - wl->iscan = (void *)kzalloc(sizeof(*wl->iscan), GFP_KERNEL); + wl->iscan = kzalloc(sizeof(*wl->iscan), GFP_KERNEL); if (unlikely(!wl->iscan)) { WL_ERR(("Iscan buf alloc failed\n")); goto init_priv_mem_out; } - wl->fw = (void *)kzalloc(sizeof(*wl->fw), GFP_KERNEL); + wl->fw = kzalloc(sizeof(*wl->fw), GFP_KERNEL); if (unlikely(!wl->fw)) { WL_ERR(("fw object alloc failed\n")); goto init_priv_mem_out; } - wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL); + wl->pmk_list = kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL); if (unlikely(!wl->pmk_list)) { WL_ERR(("pmk list alloc failed\n")); goto init_priv_mem_out; diff --git a/trunk/drivers/staging/brcm80211/brcmfmac/wl_iw.c b/trunk/drivers/staging/brcm80211/brcmfmac/wl_iw.c index 979a494fda59..d583b9d65d35 100644 --- a/trunk/drivers/staging/brcm80211/brcmfmac/wl_iw.c +++ b/trunk/drivers/staging/brcm80211/brcmfmac/wl_iw.c @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include @@ -3690,8 +3690,7 @@ int wl_iw_attach(struct net_device *dev, void *dhdp) return -ENOMEM; memset(iscan, 0, sizeof(iscan_info_t)); - iscan->iscan_ex_params_p = - (wl_iscan_params_t *) kmalloc(params_size, GFP_KERNEL); + iscan->iscan_ex_params_p = kmalloc(params_size, GFP_KERNEL); if (!iscan->iscan_ex_params_p) return -ENOMEM; iscan->iscan_ex_param_size = params_size; @@ -3723,9 +3722,7 @@ int wl_iw_attach(struct net_device *dev, void *dhdp) priv_dev = dev; MUTEX_LOCK_SOFTAP_SET_INIT(iw->pub); #endif - g_scan = NULL; - - g_scan = (void *)kmalloc(G_SCAN_RESULTS, GFP_KERNEL); + g_scan = kmalloc(G_SCAN_RESULTS, GFP_KERNEL); if (!g_scan) return -ENOMEM; diff --git a/trunk/drivers/staging/brcm80211/include/bcmdefs.h b/trunk/drivers/staging/brcm80211/include/bcmdefs.h index dc52e9dbb8b5..ae6a65a64714 100644 --- a/trunk/drivers/staging/brcm80211/include/bcmdefs.h +++ b/trunk/drivers/staging/brcm80211/include/bcmdefs.h @@ -42,9 +42,6 @@ #define BCMFASTPATH #endif -/* Put some library data/code into ROM to reduce RAM requirements */ -#define BCMROMFN(_fn) _fn - /* Bus types */ #define SI_BUS 0 /* SOC Interconnect */ #define PCI_BUS 1 /* PCI target */ @@ -54,35 +51,10 @@ #define SPI_BUS 6 /* gSPI target */ #define RPC_BUS 7 /* RPC target */ -/* Allows size optimization for single-bus image */ -#ifdef BCMBUSTYPE -#define BUSTYPE(bus) (BCMBUSTYPE) -#else #define BUSTYPE(bus) (bus) -#endif - -/* Allows size optimization for single-backplane image */ -#ifdef BCMCHIPTYPE -#define CHIPTYPE(bus) (BCMCHIPTYPE) -#else #define CHIPTYPE(bus) (bus) -#endif - -/* Allows size optimization for SPROM support */ -#define SPROMBUS (PCI_BUS) - -/* Allows size optimization for single-chip image */ -#ifdef BCMCHIPID -#define CHIPID(chip) (BCMCHIPID) -#else #define CHIPID(chip) (chip) -#endif - -#ifdef BCMCHIPREV -#define CHIPREV(rev) (BCMCHIPREV) -#else #define CHIPREV(rev) (rev) -#endif /* Defines for DMA Address Width - Shared between OSL and HNDDMA */ #define DMADDR_MASK_32 0x0 /* Address mask for 32-bits */ @@ -146,31 +118,11 @@ typedef struct { #define BCMEXTRAHDROOM 172 -/* Headroom required for dongle-to-host communication. Packets allocated - * locally in the dongle (e.g. for CDC ioctls or RNDIS messages) should - * leave this much room in front for low-level message headers which may - * be needed to get across the dongle bus to the host. (These messages - * don't go over the network, so room for the full WL header above would - * be a waste.). -*/ -#define BCMDONGLEHDRSZ 12 -#define BCMDONGLEPADSZ 16 - -#define BCMDONGLEOVERHEAD (BCMDONGLEHDRSZ + BCMDONGLEPADSZ) - #ifdef BCMDBG - -#define BCMDBG_ERR - #ifndef BCMDBG_ASSERT #define BCMDBG_ASSERT -#endif /* BCMDBG_ASSERT */ - -#endif /* BCMDBG */ - -#if defined(BCMDBG_ASSERT) -#define BCMASSERT_SUPPORT -#endif +#endif /* BCMDBG_ASSERT */ +#endif /* BCMDBG */ /* Macros for doing definition and get/set of bitfields * Usage example, e.g. a three-bit field (bits 4-6): @@ -190,10 +142,6 @@ typedef struct { (((val) & (~(field ## _M << field ## _S))) | \ ((unsigned)(bits) << field ## _S)) -/* define BCMSMALL to remove misc features for memory-constrained environments */ -#define BCMSPACE -#define bcmspace true /* if (bcmspace) code is retained */ - /* Max. nvram variable table size */ #define MAXSZ_NVRAM_VARS 4096 diff --git a/trunk/drivers/staging/brcm80211/include/bcmutils.h b/trunk/drivers/staging/brcm80211/include/bcmutils.h index b53315981be0..7f1d33481ee8 100644 --- a/trunk/drivers/staging/brcm80211/include/bcmutils.h +++ b/trunk/drivers/staging/brcm80211/include/bcmutils.h @@ -30,7 +30,6 @@ }; /* ** driver-only section ** */ -#include #define GPIO_PIN_NOTDEFINED 0x20 /* Pin not defined */ diff --git a/trunk/drivers/staging/brcm80211/include/d11.h b/trunk/drivers/staging/brcm80211/include/d11.h index c07548c70e30..be2d4970407c 100644 --- a/trunk/drivers/staging/brcm80211/include/d11.h +++ b/trunk/drivers/staging/brcm80211/include/d11.h @@ -17,13 +17,6 @@ #ifndef _D11_H #define _D11_H -#include -#include -#include -#include -#include -#include - /* This marks the start of a packed structure section. */ #include diff --git a/trunk/drivers/staging/brcm80211/include/epivers.h b/trunk/drivers/staging/brcm80211/include/epivers.h deleted file mode 100644 index 2e6b5190ad6c..000000000000 --- a/trunk/drivers/staging/brcm80211/include/epivers.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2010 Broadcom Corporation - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _epivers_h_ -#define _epivers_h_ - -#define EPI_MAJOR_VERSION 5 - -#define EPI_MINOR_VERSION 75 - -#define EPI_RC_NUMBER 11 - -#define EPI_INCREMENTAL_NUMBER 0 - -#define EPI_BUILD_NUMBER 1 - -#define EPI_VERSION { 5, 75, 11, 0 } - -#ifdef BCMSDIO -/* EPI_VERSION_NUM must match FW version */ -#define EPI_VERSION_NUM 0x054b0c00 -#else -#define EPI_VERSION_NUM 0x054b0b00 -#endif - -#define EPI_VERSION_DEV 5.75.11 - -/* Driver Version String, ASCII, 32 chars max */ -#define EPI_VERSION_STR "5.75.11" - -#endif /* _epivers_h_ */ diff --git a/trunk/drivers/staging/brcm80211/include/linux_osl.h b/trunk/drivers/staging/brcm80211/include/linux_osl.h index c9c860b6e474..586e652e75c7 100644 --- a/trunk/drivers/staging/brcm80211/include/linux_osl.h +++ b/trunk/drivers/staging/brcm80211/include/linux_osl.h @@ -18,13 +18,7 @@ #define _linux_osl_h_ -/* Linux Kernel: File Operations: start */ -extern void *osl_os_open_image(char *filename); -extern int osl_os_get_image_block(char *buf, int len, void *image); -extern void osl_os_close_image(void *image); -/* Linux Kernel: File Operations: end */ - -extern osl_t *osl_attach(void *pdev, uint bustype, bool pkttag); +extern osl_t *osl_attach(void *pdev, uint bustype); extern void osl_detach(osl_t *osh); extern u32 g_assert_type; @@ -62,7 +56,6 @@ extern uint osl_pci_slot(osl_t *osh); /* Pkttag flag should be part of public information */ typedef struct { - bool pkttag; uint pktalloced; /* Number of allocated packet buffers */ bool mmbus; /* Bus supports memory-mapped register accesses */ pktfree_cb_fn_t tx_fn; /* Callback function for PKTFREE */ @@ -91,8 +84,6 @@ typedef struct { #define BUS_SWAP32(v) (v) -#define DMA_CONSISTENT_ALIGN osl_dma_consistent_align() -extern uint osl_dma_consistent_align(void); extern void *osl_dma_alloc_consistent(osl_t *osh, uint size, u16 align, uint *tot, unsigned long *pap); @@ -142,9 +133,6 @@ extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction); #define SELECT_BUS_READ(osh, mmap_op, bus_op) mmap_op #endif -#define OSL_ERROR(bcmerror) osl_error(bcmerror) -extern int osl_error(int bcmerror); - /* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */ #define PKTBUFSZ 2048 /* largest reasonable packet buffer, driver uses for ethernet MTU */ @@ -271,22 +259,6 @@ extern int osl_error(int bcmerror); #define OSL_CACHED(va) ((void *)va) #endif /* mips */ -#if defined(mips) -#define OSL_GETCYCLES(x) ((x) = read_c0_count() * 2) -#elif defined(__i386__) -#define OSL_GETCYCLES(x) rdtscl((x)) -#else -#define OSL_GETCYCLES(x) ((x) = 0) -#endif /* defined(mips) */ - -/* dereference an address that may cause a bus exception */ -#ifdef mips -#define BUSPROBE(val, addr) get_dbe((val), (addr)) -#include -#else -#define BUSPROBE(val, addr) ({ (val) = R_REG(NULL, (addr)); 0; }) -#endif /* mips */ - /* map/unmap physical to virtual I/O */ #if !defined(CONFIG_MMC_MSM7X00A) #define REG_MAP(pa, size) ioremap_nocache((unsigned long)(pa), (unsigned long)(size)) @@ -299,10 +271,6 @@ extern int osl_error(int bcmerror); #define W_SM(r, v) (*(r) = (v)) #define BZERO_SM(r, len) memset((r), '\0', (len)) -#ifdef BRCM_FULLMAC -#include /* use current 2.4.x calling conventions */ -#endif - /* packet primitives */ #define PKTGET(osh, len, send) osl_pktget((osh), (len)) #define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send)) @@ -316,7 +284,6 @@ extern int osl_error(int bcmerror); #define PKTSETLEN(skb, len) __skb_trim((struct sk_buff *)(skb), (len)) #define PKTPUSH(skb, bytes) skb_push((struct sk_buff *)(skb), (bytes)) #define PKTPULL(skb, bytes) skb_pull((struct sk_buff *)(skb), (bytes)) -#define PKTTAG(skb) ((void *)(((struct sk_buff *)(skb))->cb)) #define PKTALLOCED(osh) (((osl_pubinfo_t *)(osh))->pktalloced) #define PKTSETPOOL(osh, skb, x, y) do {} while (0) #define PKTPOOL(osh, skb) false @@ -332,9 +299,6 @@ osl_pkt_frmnative(osl_pubinfo_t *osh, struct sk_buff *skb) { struct sk_buff *nskb; - if (osh->pkttag) - bzero((void *)skb->cb, OSL_PKTTAG_SZ); - for (nskb = skb; nskb; nskb = nskb->next) osh->pktalloced++; @@ -348,9 +312,6 @@ osl_pkt_tonative(osl_pubinfo_t *osh, void *pkt) { struct sk_buff *nskb; - if (osh->pkttag) - bzero(((struct sk_buff *)pkt)->cb, OSL_PKTTAG_SZ); - for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) osh->pktalloced--; diff --git a/trunk/drivers/staging/brcm80211/include/linuxver.h b/trunk/drivers/staging/brcm80211/include/linuxver.h deleted file mode 100644 index dc721413ee29..000000000000 --- a/trunk/drivers/staging/brcm80211/include/linuxver.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2010 Broadcom Corporation - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _linuxver_h_ -#define _linuxver_h_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#undef IP_TOS -#include - -#endif /* _linuxver_h_ */ diff --git a/trunk/drivers/staging/brcm80211/include/osl.h b/trunk/drivers/staging/brcm80211/include/osl.h index c0ebb3d97220..bcb56aa5dc96 100644 --- a/trunk/drivers/staging/brcm80211/include/osl.h +++ b/trunk/drivers/staging/brcm80211/include/osl.h @@ -21,8 +21,6 @@ typedef struct osl_info osl_t; typedef struct osl_dmainfo osldma_t; -#define OSL_PKTTAG_SZ 32 /* Size of PktTag */ - /* Drivers use PKTFREESETCB to register a callback function when a packet is freed by OSL */ typedef void (*pktfree_cb_fn_t) (void *ctx, void *pkt, unsigned int status); diff --git a/trunk/drivers/staging/brcm80211/include/wlioctl.h b/trunk/drivers/staging/brcm80211/include/wlioctl.h index 96866fb8898c..45e02e5293eb 100644 --- a/trunk/drivers/staging/brcm80211/include/wlioctl.h +++ b/trunk/drivers/staging/brcm80211/include/wlioctl.h @@ -33,82 +33,9 @@ #define BWL_DEFAULT_PACKING #include -/* Legacy structure to help keep backward compatible wl tool and tray app */ - -#define LEGACY_WL_BSS_INFO_VERSION 107 /* older version of wl_bss_info struct */ - -typedef struct wl_bss_info_107 { - u32 version; /* version field */ - u32 length; /* byte length of data in this record, - * starting at version and including IEs - */ - struct ether_addr BSSID; - u16 beacon_period; /* units are Kusec */ - u16 capability; /* Capability information */ - u8 SSID_len; - u8 SSID[32]; - struct { - uint count; /* # rates in this set */ - u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ - } rateset; /* supported rates */ - u8 channel; /* Channel no. */ - u16 atim_window; /* units are Kusec */ - u8 dtim_period; /* DTIM period */ - s16 RSSI; /* receive signal strength (in dBm) */ - s8 phy_noise; /* noise (in dBm) */ - u32 ie_length; /* byte length of Information Elements */ - /* variable length Information Elements */ -} wl_bss_info_107_t; - -/* - * Per-BSS information structure. - */ - -#define LEGACY2_WL_BSS_INFO_VERSION 108 /* old version of wl_bss_info struct */ - -/* BSS info structure - * Applications MUST CHECK ie_offset field and length field to access IEs and - * next bss_info structure in a vector (in wl_scan_results_t) - */ -typedef struct wl_bss_info_108 { - u32 version; /* version field */ - u32 length; /* byte length of data in this record, - * starting at version and including IEs - */ - struct ether_addr BSSID; - u16 beacon_period; /* units are Kusec */ - u16 capability; /* Capability information */ - u8 SSID_len; - u8 SSID[32]; - struct { - uint count; /* # rates in this set */ - u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ - } rateset; /* supported rates */ - chanspec_t chanspec; /* chanspec for bss */ - u16 atim_window; /* units are Kusec */ - u8 dtim_period; /* DTIM period */ - s16 RSSI; /* receive signal strength (in dBm) */ - s8 phy_noise; /* noise (in dBm) */ - - u8 n_cap; /* BSS is 802.11N Capable */ - u32 nbss_cap; /* 802.11N BSS Capabilities (based on HT_CAP_*) */ - u8 ctl_ch; /* 802.11N BSS control channel number */ - u32 reserved32[1]; /* Reserved for expansion of BSS properties */ - u8 flags; /* flags */ - u8 reserved[3]; /* Reserved for expansion of BSS properties */ - u8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ - - u16 ie_offset; /* offset at which IEs start, from beginning */ - u32 ie_length; /* byte length of Information Elements */ - /* Add new fields here */ - /* variable length Information Elements */ -} wl_bss_info_108_t; - #ifdef BRCM_FULLMAC + #define WL_BSS_INFO_VERSION 108 /* current ver of wl_bss_info struct */ -#else -#define WL_BSS_INFO_VERSION 109 /* current ver of wl_bss_info struct */ -#endif /* BSS info structure * Applications MUST CHECK ie_offset field and length field to access IEs and @@ -148,12 +75,14 @@ typedef struct wl_bss_info { /* Add new fields here */ /* variable length Information Elements */ } wl_bss_info_t; +#endif /* BRCM_FULLMAC */ typedef struct wlc_ssid { u32 SSID_len; unsigned char SSID[32]; } wlc_ssid_t; +#ifdef BRCM_FULLMAC typedef struct chan_scandata { u8 txpower; u8 pad; @@ -308,6 +237,7 @@ typedef struct wl_probe_params { struct ether_addr bssid; struct ether_addr mac; } wl_probe_params_t; +#endif /* BRCM_FULLMAC */ #define WL_NUMRATES 16 /* max # of rates in a rateset */ typedef struct wl_rateset { @@ -315,6 +245,7 @@ typedef struct wl_rateset { u8 rates[WL_NUMRATES]; /* rates in 500kbps units w/hi bit set if basic */ } wl_rateset_t; +#ifdef BRCM_FULLMAC typedef struct wl_rateset_args { u32 count; /* # rates in this set */ u8 rates[WL_NUMRATES]; /* rates in 500kbps units w/hi bit set if basic */ @@ -352,6 +283,8 @@ typedef struct wl_join_params { } wl_join_params_t; #define WL_JOIN_PARAMS_FIXED_SIZE (sizeof(wl_join_params_t) - sizeof(chanspec_t)) +#endif /* BRCM_FULLMAC */ + /* defines used by the nrate iovar */ #define NRATE_MCS_INUSE 0x00000080 /* MSC in use,indicates b0-6 holds an mcs */ #define NRATE_RATE_MASK 0x0000007f /* rate/mcs value */ @@ -391,6 +324,7 @@ typedef struct { #define HIGHEST_SINGLE_STREAM_MCS 7 /* MCS values greater than this enable multiple streams */ +#ifdef BRCM_FULLMAC #define MAX_CCA_CHANNELS 38 /* Max number of 20 Mhz wide channels */ #define MAX_CCA_SECS 60 /* CCA keeps this many seconds history */ @@ -428,8 +362,11 @@ typedef struct { cca_congest_t secs[1]; /* Data */ } cca_congest_channel_req_t; +#endif /* BRCM_FULLMAC */ + #define WLC_CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NUL */ +#ifdef BRCM_FULLMAC typedef struct wl_country { char country_abbrev[WLC_CNTRY_BUF_SZ]; /* nul-terminated country code used in * the Country IE @@ -516,6 +453,7 @@ typedef struct wl_rm_rep { wl_rm_rep_elt_t rep[1]; /* variable length block of reports */ } wl_rm_rep_t; #define WL_RM_REP_FIXED_LEN 8 +#endif /* BRCM_FULLMAC */ /* Enumerate crypto algorithms */ #define CRYPTO_ALGO_OFF 0 @@ -621,27 +559,6 @@ typedef struct wl_led_info { u8 activehi; } wl_led_info_t; -/* flags */ -#define WLC_ASSOC_REQ_IS_REASSOC 0x01 /* assoc req was actually a reassoc */ - -/* srom read/write struct passed through ioctl */ -typedef struct { - uint byteoff; /* byte offset */ - uint nbytes; /* number of bytes */ - u16 buf[1]; -} srom_rw_t; - -/* similar cis (srom or otp) struct [iovar: may not be aligned] */ -typedef struct { - u32 source; /* cis source */ - u32 byteoff; /* byte offset */ - u32 nbytes; /* number of bytes */ - /* data follows here */ -} cis_rw_t; - -#define WLC_CIS_DEFAULT 0 /* built-in default */ -#define WLC_CIS_SROM 1 /* source is sprom */ -#define WLC_CIS_OTP 2 /* source is otp */ /* R_REG and W_REG struct passed through ioctl */ typedef struct { @@ -651,102 +568,14 @@ typedef struct { uint band; /* band (optional) */ } rw_reg_t; -/* Structure used by GET/SET_ATTEN ioctls - it controls power in b/g-band */ -/* PCL - Power Control Loop */ -/* current gain setting is replaced by user input */ -#define WL_ATTEN_APP_INPUT_PCL_OFF 0 /* turn off PCL, apply supplied input */ -#define WL_ATTEN_PCL_ON 1 /* turn on PCL */ -/* current gain setting is maintained */ -#define WL_ATTEN_PCL_OFF 2 /* turn off PCL. */ - -typedef struct { - u16 auto_ctrl; /* WL_ATTEN_XX */ - u16 bb; /* Baseband attenuation */ - u16 radio; /* Radio attenuation */ - u16 txctl1; /* Radio TX_CTL1 value */ -} atten_t; - -/* Per-AC retry parameters */ -struct wme_tx_params_s { - u8 short_retry; - u8 short_fallback; - u8 long_retry; - u8 long_fallback; - u16 max_rate; /* In units of 512 Kbps */ -}; - -typedef struct wme_tx_params_s wme_tx_params_t; - -#define WL_WME_TX_PARAMS_IO_BYTES (sizeof(wme_tx_params_t) * AC_COUNT) - -/* defines used by poweridx iovar - it controls power in a-band */ -/* current gain setting is maintained */ -#define WL_PWRIDX_PCL_OFF -2 /* turn off PCL. */ -#define WL_PWRIDX_PCL_ON -1 /* turn on PCL */ -#define WL_PWRIDX_LOWER_LIMIT -2 /* lower limit */ -#define WL_PWRIDX_UPPER_LIMIT 63 /* upper limit */ -/* value >= 0 causes - * - input to be set to that value - * - PCL to be off - */ - -/* Used to get specific link/ac parameters */ -typedef struct { - int ac; - u8 val; - struct ether_addr ea; -} link_val_t; - -#define BCM_MAC_STATUS_INDICATION (0x40010200L) - -typedef struct { - u16 ver; /* version of this struct */ - u16 len; /* length in bytes of this structure */ - u16 cap; /* sta's advertised capabilities */ - u32 flags; /* flags defined below */ - u32 idle; /* time since data pkt rx'd from sta */ - struct ether_addr ea; /* Station address */ - wl_rateset_t rateset; /* rateset in use */ - u32 in; /* seconds elapsed since associated */ - u32 listen_interval_inms; /* Min Listen interval in ms for this STA */ - u32 tx_pkts; /* # of packets transmitted */ - u32 tx_failures; /* # of packets failed */ - u32 rx_ucast_pkts; /* # of unicast packets received */ - u32 rx_mcast_pkts; /* # of multicast packets received */ - u32 tx_rate; /* Rate of last successful tx frame */ - u32 rx_rate; /* Rate of last successful rx frame */ - u32 rx_decrypt_succeeds; /* # of packet decrypted successfully */ - u32 rx_decrypt_failures; /* # of packet decrypted unsuccessfully */ -} sta_info_t; - -#define WL_OLD_STAINFO_SIZE offsetof(sta_info_t, tx_pkts) - -#define WL_STA_VER 3 - -/* Flags for sta_info_t indicating properties of STA */ -#define WL_STA_BRCM 0x1 /* Running a Broadcom driver */ -#define WL_STA_WME 0x2 /* WMM association */ -#define WL_STA_ABCAP 0x4 -#define WL_STA_AUTHE 0x8 /* Authenticated */ -#define WL_STA_ASSOC 0x10 /* Associated */ -#define WL_STA_AUTHO 0x20 /* Authorized */ -#define WL_STA_WDS 0x40 /* Wireless Distribution System */ -#define WL_STA_WDS_LINKUP 0x80 /* WDS traffic/probes flowing properly */ -#define WL_STA_PS 0x100 /* STA is in power save mode from AP's viewpoint */ -#define WL_STA_APSD_BE 0x200 /* APSD delv/trigger for AC_BE is default enabled */ -#define WL_STA_APSD_BK 0x400 /* APSD delv/trigger for AC_BK is default enabled */ -#define WL_STA_APSD_VI 0x800 /* APSD delv/trigger for AC_VI is default enabled */ -#define WL_STA_APSD_VO 0x1000 /* APSD delv/trigger for AC_VO is default enabled */ -#define WL_STA_N_CAP 0x2000 /* STA 802.11n capable */ -#define WL_STA_SCBSTATS 0x4000 /* Per STA debug stats */ - -#define WL_WDS_LINKUP WL_STA_WDS_LINKUP /* deprecated */ +#ifdef BRCM_FULLMAC /* Used to get specific STA parameters */ typedef struct { u32 val; struct ether_addr ea; } scb_val_t; +#endif /* BRCM_FULLMAC */ /* channel encoding */ typedef struct channel_info { @@ -770,6 +599,7 @@ typedef struct get_pktcnt { uint rx_ocast_good_pkt; /* unicast packets destined for others */ } get_pktcnt_t; +#ifdef BRCM_FULLMAC /* Linux network driver ioctl encoding */ typedef struct wl_ioctl { uint cmd; /* common ioctl definition */ @@ -779,11 +609,8 @@ typedef struct wl_ioctl { uint used; /* bytes read or written (optional) */ uint needed; /* bytes needed (optional) */ } wl_ioctl_t; +#endif /* BRCM_FULLMAC */ -/* reference to wl_ioctl_t struct used by usermode driver */ -#define ioctl_subtype set /* subtype param */ -#define ioctl_pid used /* pid param */ -#define ioctl_status needed /* status param */ /* * Structure for passing hardware and software @@ -810,45 +637,11 @@ typedef struct wlc_rev_info { #define WL_REV_INFO_LEGACY_LENGTH 48 -#define WL_BRAND_MAX 10 -typedef struct wl_instance_info { - uint instance; - char brand[WL_BRAND_MAX]; -} wl_instance_info_t; - -/* structure to change size of tx fifo */ -typedef struct wl_txfifo_sz { - u16 magic; - u16 fifo; - u16 size; -} wl_txfifo_sz_t; -/* magic pattern used for mismatch driver and wl */ -#define WL_TXFIFO_SZ_MAGIC 0xa5a5 - -/* Transfer info about an IOVar from the driver */ -/* Max supported IOV name size in bytes, + 1 for nul termination */ -#define WLC_IOV_NAME_LEN 30 -typedef struct wlc_iov_trx_s { - u8 module; - u8 type; - char name[WLC_IOV_NAME_LEN]; -} wlc_iov_trx_t; - -/* check this magic number */ -#define WLC_IOCTL_MAGIC 0x14e46c77 - -#define PROC_ENTRY_NAME "brcm_debug" -/* bump this number if you change the ioctl interface */ -#define WLC_IOCTL_VERSION 1 - #ifdef BRCM_FULLMAC -#define WLC_IOCTL_MAXLEN 8192 -#else -#define WLC_IOCTL_MAXLEN 3072 /* max length ioctl buffer required */ -#endif #define WLC_IOCTL_SMLEN 256 /* "small" length ioctl buffer required */ #define WLC_IOCTL_MEDLEN 1536 /* "med" length ioctl buffer required */ -#define WLC_SAMPLECOLLECT_MAXLEN 10240 /* Max Sample Collect buffer for two cores */ +#define WLC_IOCTL_MAXLEN 8192 +#endif /* common ioctl definitions */ #define WLC_GET_MAGIC 0 @@ -1399,23 +1192,6 @@ typedef struct { #define WL_TX_POWER_MCS40_FIRST 28 #define WL_TX_POWER_MCS40_NUM 17 -typedef struct { - u32 flags; - chanspec_t chanspec; /* txpwr report for this channel */ - chanspec_t local_chanspec; /* channel on which we are associated */ - u8 local_max; /* local max according to the AP */ - u8 local_constraint; /* local constraint according to the AP */ - s8 antgain[2]; /* Ant gain for each band - from SROM */ - u8 rf_cores; /* count of RF Cores being reported */ - u8 est_Pout[4]; /* Latest tx power out estimate per RF - * chain without adjustment - */ - u8 est_Pout_cck; /* Latest CCK tx power out estimate */ - u8 user_limit[WL_TX_POWER_RATES_LEGACY]; /* User limit */ - u8 reg_limit[WL_TX_POWER_RATES_LEGACY]; /* Regulatory power limit */ - u8 board_limit[WL_TX_POWER_RATES_LEGACY]; /* Max power board can support (SROM) */ - u8 target[WL_TX_POWER_RATES_LEGACY]; /* Latest target power */ -} tx_power_legacy2_t; #define WL_TX_POWER_RATES 101 #define WL_TX_POWER_CCK_FIRST 0 @@ -1848,63 +1624,6 @@ struct ampdu_retry_tid { u8 retry; /* retry value */ }; -/* structure for addts arguments */ -/* For ioctls that take a list of TSPEC */ -struct tslist { - int count; /* number of tspecs */ - struct tsinfo_arg tsinfo[1]; /* variable length array of tsinfo */ -}; - -/* structure for addts/delts arguments */ -typedef struct tspec_arg { - u16 version; /* see definition of TSPEC_ARG_VERSION */ - u16 length; /* length of entire structure */ - uint flag; /* bit field */ - /* TSPEC Arguments */ - struct tsinfo_arg tsinfo; /* TS Info bit field */ - u16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */ - u16 max_msdu_size; /* Maximum MSDU Size (bytes) */ - uint min_srv_interval; /* Minimum Service Interval (us) */ - uint max_srv_interval; /* Maximum Service Interval (us) */ - uint inactivity_interval; /* Inactivity Interval (us) */ - uint suspension_interval; /* Suspension Interval (us) */ - uint srv_start_time; /* Service Start Time (us) */ - uint min_data_rate; /* Minimum Data Rate (bps) */ - uint mean_data_rate; /* Mean Data Rate (bps) */ - uint peak_data_rate; /* Peak Data Rate (bps) */ - uint max_burst_size; /* Maximum Burst Size (bytes) */ - uint delay_bound; /* Delay Bound (us) */ - uint min_phy_rate; /* Minimum PHY Rate (bps) */ - u16 surplus_bw; /* Surplus Bandwidth Allowance (range 1.0 to 8.0) */ - u16 medium_time; /* Medium Time (32 us/s periods) */ - u8 dialog_token; /* dialog token */ -} tspec_arg_t; - -/* tspec arg for desired station */ -typedef struct tspec_per_sta_arg { - struct ether_addr ea; - struct tspec_arg ts; -} tspec_per_sta_arg_t; - -/* structure for max bandwidth for each access category */ -typedef struct wme_max_bandwidth { - u32 ac[AC_COUNT]; /* max bandwidth for each access category */ -} wme_max_bandwidth_t; - -#define WL_WME_MBW_PARAMS_IO_BYTES (sizeof(wme_max_bandwidth_t)) - -/* current version of wl_tspec_arg_t struct */ -#define TSPEC_ARG_VERSION 2 /* current version of wl_tspec_arg_t struct */ -#define TSPEC_ARG_LENGTH 55 /* argument length from tsinfo to medium_time */ -#define TSPEC_DEFAULT_DIALOG_TOKEN 42 /* default dialog token */ -#define TSPEC_DEFAULT_SBW_FACTOR 0x3000 /* default surplus bw */ - -/* define for flag */ -#define TSPEC_PENDING 0 /* TSPEC pending */ -#define TSPEC_ACCEPTED 1 /* TSPEC accepted */ -#define TSPEC_REJECTED 2 /* TSPEC rejected */ -#define TSPEC_UNKNOWN 3 /* TSPEC unknown */ -#define TSPEC_STATUS_MASK 7 /* TSPEC status mask */ /* Software feature flag defines used by wlfeatureflag */ #define WL_SWFL_NOHWRADIO 0x0004 @@ -1913,16 +1632,6 @@ typedef struct wme_max_bandwidth { #define WL_LIFETIME_MAX 0xFFFF /* Max value in ms */ -/* - * Dongle pattern matching filter. - */ - -/* Packet filter types. Currently, only pattern matching is supported. */ -typedef enum wl_pkt_filter_type { - WL_PKT_FILTER_TYPE_PATTERN_MATCH /* Pattern matching filter */ -} wl_pkt_filter_type_t; - -#define WL_PKT_FILTER_TYPE wl_pkt_filter_type_t /* Pattern matching filter. Specifies an offset within received packets to * start matching, the pattern to match, the size of the pattern, and a bitmask @@ -1957,20 +1666,6 @@ typedef struct wl_pkt_filter_enable { u32 enable; /* Enable/disable bool */ } wl_pkt_filter_enable_t; -/* IOVAR "pkt_filter_list" parameter. Used to retrieve a list of installed filters. */ -typedef struct wl_pkt_filter_list { - u32 num; /* Number of installed packet filters */ - wl_pkt_filter_t filter[1]; /* Variable array of packet filters. */ -} wl_pkt_filter_list_t; - -#define WL_PKT_FILTER_LIST_FIXED_LEN offsetof(wl_pkt_filter_list_t, filter) - -/* IOVAR "pkt_filter_stats" parameter. Used to retrieve debug statistics. */ -typedef struct wl_pkt_filter_stats { - u32 num_pkts_matched; /* # filter matches for specified filter id */ - u32 num_pkts_forwarded; /* # packets fwded from dongle to host for all filters */ - u32 num_pkts_discarded; /* # packets discarded by dongle for all filters */ -} wl_pkt_filter_stats_t; #define WLC_RSSI_INVALID 0 /* invalid RSSI value */ diff --git a/trunk/drivers/staging/brcm80211/phy/wlc_phy_cmn.c b/trunk/drivers/staging/brcm80211/phy/wlc_phy_cmn.c index 8287261120f4..9e6bbcdf8b6f 100644 --- a/trunk/drivers/staging/brcm80211/phy/wlc_phy_cmn.c +++ b/trunk/drivers/staging/brcm80211/phy/wlc_phy_cmn.c @@ -20,10 +20,14 @@ #include #include #include -#include +#include +#include #include #include #include +#include +#include +#include #include #include diff --git a/trunk/drivers/staging/brcm80211/phy/wlc_phy_lcn.c b/trunk/drivers/staging/brcm80211/phy/wlc_phy_lcn.c index 3d3112ed4e20..1fde9d5701b0 100644 --- a/trunk/drivers/staging/brcm80211/phy/wlc_phy_lcn.c +++ b/trunk/drivers/staging/brcm80211/phy/wlc_phy_lcn.c @@ -20,10 +20,14 @@ #include #include #include -#include +#include #include #include +#include +#include +#include + #include #include #include diff --git a/trunk/drivers/staging/brcm80211/phy/wlc_phy_n.c b/trunk/drivers/staging/brcm80211/phy/wlc_phy_n.c index 950008f122b1..3e1ab579c086 100644 --- a/trunk/drivers/staging/brcm80211/phy/wlc_phy_n.c +++ b/trunk/drivers/staging/brcm80211/phy/wlc_phy_n.c @@ -18,13 +18,17 @@ #include #include #include -#include +#include #include #include #include #include #include +#include +#include +#include + #include #include #include diff --git a/trunk/drivers/staging/brcm80211/phy/wlc_phytbl_lcn.c b/trunk/drivers/staging/brcm80211/phy/wlc_phytbl_lcn.c index 6ce9e5d96830..330b88152b65 100644 --- a/trunk/drivers/staging/brcm80211/phy/wlc_phytbl_lcn.c +++ b/trunk/drivers/staging/brcm80211/phy/wlc_phytbl_lcn.c @@ -15,6 +15,9 @@ */ #include +#include +#include +#include #include #include diff --git a/trunk/drivers/staging/brcm80211/phy/wlc_phytbl_n.c b/trunk/drivers/staging/brcm80211/phy/wlc_phytbl_n.c index 7cc2c563c727..a9fc193721ef 100644 --- a/trunk/drivers/staging/brcm80211/phy/wlc_phytbl_n.c +++ b/trunk/drivers/staging/brcm80211/phy/wlc_phytbl_n.c @@ -16,6 +16,9 @@ #include +#include +#include +#include #include #include diff --git a/trunk/drivers/staging/brcm80211/sys/wl_mac80211.c b/trunk/drivers/staging/brcm80211/sys/wl_mac80211.c index d060377629ac..cb5dba95fc86 100644 --- a/trunk/drivers/staging/brcm80211/sys/wl_mac80211.c +++ b/trunk/drivers/staging/brcm80211/sys/wl_mac80211.c @@ -21,13 +21,14 @@ #include #include #include -#include +#include +#include +#include #include #define WLC_MAXBSSCFG 1 /* single BSS configs */ #include #include -#include #ifndef WLC_HIGH_ONLY #include #endif @@ -35,6 +36,8 @@ #include #include #include +#include +#include #include #include #include @@ -786,8 +789,7 @@ static wl_info_t *wl_attach(u16 vendor, u16 device, unsigned long regs, return NULL; } - /* Requires pkttag feature */ - osh = osl_attach(btparam, bustype, true); + osh = osl_attach(btparam, bustype); ASSERT(osh); #ifdef WLC_HIGH_ONLY @@ -890,8 +892,8 @@ static wl_info_t *wl_attach(u16 vendor, u16 device, unsigned long regs, wl_release_fw(wl); #endif if (!wl->wlc) { - printf("%s: %s wlc_attach() failed with code %d\n", - KBUILD_MODNAME, EPI_VERSION_STR, err); + printf("%s: wlc_attach() failed with code %d\n", + KBUILD_MODNAME, err); goto fail; } wl->pub = wlc_pub(wl->wlc); @@ -958,10 +960,10 @@ static wl_info_t *wl_attach(u16 vendor, u16 device, unsigned long regs, } #ifndef WLC_HIGH_ONLY WL_ERROR(("wl%d: Broadcom BCM43xx 802.11 MAC80211 Driver " - EPI_VERSION_STR " (" PHY_VERSION_STR ")", unit)); + " (" PHY_VERSION_STR ")", unit)); #else - WL_ERROR(("wl%d: Broadcom BCM43xx 802.11 MAC80211 Driver " - EPI_VERSION_STR, unit)); + WL_ERROR(("wl%d: Broadcom BCM43xx 802.11 Splitmac MAC80211 Driver " + , unit)); #endif #ifdef BCMDBG diff --git a/trunk/drivers/staging/brcm80211/sys/wlc_alloc.c b/trunk/drivers/staging/brcm80211/sys/wlc_alloc.c index 2dc89f9c2635..8001dca44918 100644 --- a/trunk/drivers/staging/brcm80211/sys/wlc_alloc.c +++ b/trunk/drivers/staging/brcm80211/sys/wlc_alloc.c @@ -17,15 +17,20 @@ #include #include #include -#include +#include +#include #include #include #include #include #include #include +#include +#include +#include #include #include +#include static wlc_pub_t *wlc_pub_malloc(osl_t *osh, uint unit, uint *err, uint devid); diff --git a/trunk/drivers/staging/brcm80211/sys/wlc_ampdu.c b/trunk/drivers/staging/brcm80211/sys/wlc_ampdu.c index a4e49f3c1363..0bd7069dc331 100644 --- a/trunk/drivers/staging/brcm80211/sys/wlc_ampdu.c +++ b/trunk/drivers/staging/brcm80211/sys/wlc_ampdu.c @@ -16,19 +16,19 @@ #include #include #include -#include -#include #include #include #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -36,6 +36,7 @@ #include #include #include +#include #ifdef WLC_HIGH_ONLY #include diff --git a/trunk/drivers/staging/brcm80211/sys/wlc_antsel.c b/trunk/drivers/staging/brcm80211/sys/wlc_antsel.c index 5ff8831d2fa8..ecc35de77004 100644 --- a/trunk/drivers/staging/brcm80211/sys/wlc_antsel.c +++ b/trunk/drivers/staging/brcm80211/sys/wlc_antsel.c @@ -19,18 +19,23 @@ #ifdef WLANTSEL #include -#include +#include +#include #include #include #include #include #include +#include +#include +#include #include #include #include #include #include +#include #include #include #include diff --git a/trunk/drivers/staging/brcm80211/sys/wlc_bmac.c b/trunk/drivers/staging/brcm80211/sys/wlc_bmac.c index b70f9d099233..fc5201d5171a 100644 --- a/trunk/drivers/staging/brcm80211/sys/wlc_bmac.c +++ b/trunk/drivers/staging/brcm80211/sys/wlc_bmac.c @@ -20,7 +20,9 @@ #include #include -#include +#include +#include +#include #include #include #include @@ -42,12 +44,14 @@ #include #include #include +#include /* BMAC_NOTE: a WLC_HIGH compile include of wlc.h adds in more structures and type * dependencies. Need to include these to files to allow a clean include of wlc.h * with WLC_HIGH defined. * At some point we may be able to skip the include of wlc.h and instead just * define a stub wlc_info and band struct to allow rpc calls to get the rpc handle. */ +#include #include #include #include @@ -69,6 +73,7 @@ #include #include +#include #define TIMER_INTERVAL_WATCHDOG_BMAC 1000 /* watchdog timer, in unit of ms */ diff --git a/trunk/drivers/staging/brcm80211/sys/wlc_channel.c b/trunk/drivers/staging/brcm80211/sys/wlc_channel.c index 509280337e34..2fcdbc72c837 100644 --- a/trunk/drivers/staging/brcm80211/sys/wlc_channel.c +++ b/trunk/drivers/staging/brcm80211/sys/wlc_channel.c @@ -19,16 +19,21 @@ #include #include #include -#include +#include +#include #include #include +#include +#include #include #include #include +#include #include #include #include #include +#include typedef struct wlc_cm_band { u8 locale_flags; /* locale_info_t flags */ diff --git a/trunk/drivers/staging/brcm80211/sys/wlc_event.c b/trunk/drivers/staging/brcm80211/sys/wlc_event.c index 7e1bf0e2ecdd..e4ab077bf87f 100644 --- a/trunk/drivers/staging/brcm80211/sys/wlc_event.c +++ b/trunk/drivers/staging/brcm80211/sys/wlc_event.c @@ -16,9 +16,13 @@ #include #include -#include +#include +#include +#include #include #include +#include +#include #include #include #include @@ -32,6 +36,7 @@ #ifdef MSGTRACE #include #endif +#include /* Local prototypes */ static void wlc_timer_cb(void *arg); diff --git a/trunk/drivers/staging/brcm80211/sys/wlc_mac80211.c b/trunk/drivers/staging/brcm80211/sys/wlc_mac80211.c index feaffcc64ec6..a9fa48a14c5d 100644 --- a/trunk/drivers/staging/brcm80211/sys/wlc_mac80211.c +++ b/trunk/drivers/staging/brcm80211/sys/wlc_mac80211.c @@ -16,8 +16,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -61,6 +62,7 @@ #endif /* WLC_HIGH_ONLY */ #include #include +#include #ifdef WLC_HIGH_ONLY #undef R_REG @@ -135,6 +137,8 @@ uint wl_msg_level = #define SCAN_IN_PROGRESS(x) 0 +#define EPI_VERSION_NUM 0x054b0b00 + #ifdef BCMDBG /* pointer to most recently allocated wl/wlc */ static wlc_info_t *wlc_info_dbg = (wlc_info_t *) (NULL); @@ -667,7 +671,7 @@ bool wlc_ps_check(wlc_info_t *wlc) * may be either true or false due to the low level override. */ wake = STAY_AWAKE(wlc); - wake_ok = (wake && ((tmp & MCTL_WAKE) != 0)) || !wake; + wake_ok = ((tmp & MCTL_WAKE) != 0) || !wake; #endif if (hps && !wake_ok) { WL_ERROR(("wl%d: wake not sync, sw %d maccontrol 0x%x\n", wlc->pub->unit, wake, tmp)); @@ -1780,8 +1784,10 @@ void *wlc_attach(void *wl, u16 vendor, u16 device, uint unit, bool piomode, ASSERT(sizeof(struct dot11_bcn_prb) == DOT11_BCN_PRB_LEN); ASSERT(sizeof(tx_status_t) == TXSTATUS_LEN); ASSERT(sizeof(ht_cap_ie_t) == HT_CAP_IE_LEN); +#ifdef BRCM_FULLMAC ASSERT(offsetof(wl_scan_params_t, channel_list) == WL_SCAN_PARAMS_FIXED_SIZE); +#endif ASSERT(IS_ALIGNED(offsetof(wsec_key_t, data), sizeof(u32))); ASSERT(ISPOWEROF2(MA_WINDOW_SZ)); diff --git a/trunk/drivers/staging/brcm80211/sys/wlc_mac80211.h b/trunk/drivers/staging/brcm80211/sys/wlc_mac80211.h index 6a77591234b7..a3c6fb884990 100644 --- a/trunk/drivers/staging/brcm80211/sys/wlc_mac80211.h +++ b/trunk/drivers/staging/brcm80211/sys/wlc_mac80211.h @@ -17,19 +17,13 @@ #ifndef _wlc_h_ #define _wlc_h_ -#include - -#include #include -#include #include #include #ifdef WLC_SPLIT #include #endif - #include - #include #define MA_WINDOW_SZ 8 /* moving average window size */ diff --git a/trunk/drivers/staging/brcm80211/sys/wlc_phy_shim.c b/trunk/drivers/staging/brcm80211/sys/wlc_phy_shim.c index bf8e2e1a15f6..201ecdb319cd 100644 --- a/trunk/drivers/staging/brcm80211/sys/wlc_phy_shim.c +++ b/trunk/drivers/staging/brcm80211/sys/wlc_phy_shim.c @@ -24,9 +24,10 @@ #include #include #include -#include -#include +#include +#include #include +#include #include #include @@ -46,6 +47,7 @@ #include #include #include +#include #include @@ -53,6 +55,7 @@ #include #include #include +#include /* PHY SHIM module specific state */ struct wlc_phy_shim_info { diff --git a/trunk/drivers/staging/brcm80211/sys/wlc_pub.h b/trunk/drivers/staging/brcm80211/sys/wlc_pub.h index a6a8c33483c9..f6ac5e99cf31 100644 --- a/trunk/drivers/staging/brcm80211/sys/wlc_pub.h +++ b/trunk/drivers/staging/brcm80211/sys/wlc_pub.h @@ -437,13 +437,9 @@ struct wlc_if; #define EDCF_ENAB(pub) (WME_ENAB(pub)) #define QOS_ENAB(pub) (WME_ENAB(pub) || N_ENAB(pub)) -#define MONITOR_ENAB(wlc) (bcmspace && (wlc)->monitor) +#define MONITOR_ENAB(wlc) ((wlc)->monitor) -#define PROMISC_ENAB(wlc) (bcmspace && (wlc)->promisc) - -extern void wlc_pkttag_info_move(wlc_pub_t *pub, void *pkt_from, void *pkt_to); - -#define WLPKTTAGSCB(p) (WLPKTTAG(p)->_scb) +#define PROMISC_ENAB(wlc) ((wlc)->promisc) #define WLC_PREC_COUNT 16 /* Max precedence level implemented */ diff --git a/trunk/drivers/staging/brcm80211/sys/wlc_rate.c b/trunk/drivers/staging/brcm80211/sys/wlc_rate.c index d2d72568756d..e1199b236f5f 100644 --- a/trunk/drivers/staging/brcm80211/sys/wlc_rate.c +++ b/trunk/drivers/staging/brcm80211/sys/wlc_rate.c @@ -17,12 +17,14 @@ #include #include #include -#include +#include #include #include #include #include +#include +#include #include #include #include diff --git a/trunk/drivers/staging/brcm80211/sys/wlc_stf.c b/trunk/drivers/staging/brcm80211/sys/wlc_stf.c index 4728ad90e295..2bca0526b44c 100644 --- a/trunk/drivers/staging/brcm80211/sys/wlc_stf.c +++ b/trunk/drivers/staging/brcm80211/sys/wlc_stf.c @@ -15,8 +15,8 @@ */ #include +#include #include -#include #include #include #include @@ -25,17 +25,21 @@ #include #include #include +#include +#include #include #include #include #include #include #include +#include #include #include #include #include #include +#include #define WLC_STF_SS_STBC_RX(wlc) (WLCISNPHY(wlc->band) && \ NREV_GT(wlc->band->phyrev, 3) && NREV_LE(wlc->band->phyrev, 6)) diff --git a/trunk/drivers/staging/brcm80211/util/aiutils.c b/trunk/drivers/staging/brcm80211/util/aiutils.c index 75a7e3a5c009..1d4e3729ad61 100644 --- a/trunk/drivers/staging/brcm80211/util/aiutils.c +++ b/trunk/drivers/staging/brcm80211/util/aiutils.c @@ -17,8 +17,12 @@ #include #include #include +#ifdef BRCM_FULLMAC +#include +#endif #include -#include +#include +#include #include #include #include diff --git a/trunk/drivers/staging/brcm80211/util/bcmotp.c b/trunk/drivers/staging/brcm80211/util/bcmotp.c index c909832c7ee1..9b1e6d961a72 100644 --- a/trunk/drivers/staging/brcm80211/util/bcmotp.c +++ b/trunk/drivers/staging/brcm80211/util/bcmotp.c @@ -18,7 +18,8 @@ #include #include #include -#include +#include +#include #include #include #include diff --git a/trunk/drivers/staging/brcm80211/util/bcmsrom.c b/trunk/drivers/staging/brcm80211/util/bcmsrom.c index 1282ef7eb922..4f3d3ca1af79 100644 --- a/trunk/drivers/staging/brcm80211/util/bcmsrom.c +++ b/trunk/drivers/staging/brcm80211/util/bcmsrom.c @@ -17,7 +17,8 @@ #include #include #include -#include +#include +#include #include #include #include diff --git a/trunk/drivers/staging/brcm80211/util/bcmutils.c b/trunk/drivers/staging/brcm80211/util/bcmutils.c index 9789ea45ecd6..869d34c420d2 100644 --- a/trunk/drivers/staging/brcm80211/util/bcmutils.c +++ b/trunk/drivers/staging/brcm80211/util/bcmutils.c @@ -19,8 +19,10 @@ #include #include #include +#include +#include +#include #include -#include #include #include #include @@ -30,7 +32,6 @@ #include #include - /* copy a buffer into a pkt buffer chain */ uint pktfrombuf(osl_t *osh, void *p, uint offset, int len, unsigned char *buf) { diff --git a/trunk/drivers/staging/brcm80211/util/bcmwifi.c b/trunk/drivers/staging/brcm80211/util/bcmwifi.c index 1bb6c78eece7..81e54bd7a554 100644 --- a/trunk/drivers/staging/brcm80211/util/bcmwifi.c +++ b/trunk/drivers/staging/brcm80211/util/bcmwifi.c @@ -15,6 +15,10 @@ */ #include #include +#ifdef BRCM_FULLMAC +#include +#endif +#include #include #include #include diff --git a/trunk/drivers/staging/brcm80211/util/hnddma.c b/trunk/drivers/staging/brcm80211/util/hnddma.c index fe503e7de563..b4dcb05705b3 100644 --- a/trunk/drivers/staging/brcm80211/util/hnddma.c +++ b/trunk/drivers/staging/brcm80211/util/hnddma.c @@ -16,7 +16,8 @@ #include #include -#include +#include +#include #include #include #include diff --git a/trunk/drivers/staging/brcm80211/util/hndpmu.c b/trunk/drivers/staging/brcm80211/util/hndpmu.c index a8f3306c1d2b..6fb256bc5549 100644 --- a/trunk/drivers/staging/brcm80211/util/hndpmu.c +++ b/trunk/drivers/staging/brcm80211/util/hndpmu.c @@ -15,7 +15,11 @@ */ #include #include -#include +#include +#include +#ifdef BRCM_FULLMAC +#include +#endif #include #include #include diff --git a/trunk/drivers/staging/brcm80211/util/linux_osl.c b/trunk/drivers/staging/brcm80211/util/linux_osl.c index 2bb5b8722df6..7211f8a383ff 100644 --- a/trunk/drivers/staging/brcm80211/util/linux_osl.c +++ b/trunk/drivers/staging/brcm80211/util/linux_osl.c @@ -20,7 +20,10 @@ #include #endif /* mips */ #include -#include +#include +#include +#include +#include #include #include #include @@ -36,82 +39,13 @@ struct osl_info { osl_pubinfo_t pub; uint magic; void *pdev; - uint failed; uint bustype; }; /* Global ASSERT type flag */ u32 g_assert_type; -#ifdef BRCM_FULLMAC -static s16 linuxbcmerrormap[] = { 0, /* 0 */ - -EINVAL, /* BCME_ERROR */ - -EINVAL, /* BCME_BADARG */ - -EINVAL, /* BCME_BADOPTION */ - -EINVAL, /* BCME_NOTUP */ - -EINVAL, /* BCME_NOTDOWN */ - -EINVAL, /* BCME_NOTAP */ - -EINVAL, /* BCME_NOTSTA */ - -EINVAL, /* BCME_BADKEYIDX */ - -EINVAL, /* BCME_RADIOOFF */ - -EINVAL, /* BCME_NOTBANDLOCKED */ - -EINVAL, /* BCME_NOCLK */ - -EINVAL, /* BCME_BADRATESET */ - -EINVAL, /* BCME_BADBAND */ - -E2BIG, /* BCME_BUFTOOSHORT */ - -E2BIG, /* BCME_BUFTOOLONG */ - -EBUSY, /* BCME_BUSY */ - -EINVAL, /* BCME_NOTASSOCIATED */ - -EINVAL, /* BCME_BADSSIDLEN */ - -EINVAL, /* BCME_OUTOFRANGECHAN */ - -EINVAL, /* BCME_BADCHAN */ - -EFAULT, /* BCME_BADADDR */ - -ENOMEM, /* BCME_NORESOURCE */ - -EOPNOTSUPP, /* BCME_UNSUPPORTED */ - -EMSGSIZE, /* BCME_BADLENGTH */ - -EINVAL, /* BCME_NOTREADY */ - -EPERM, /* BCME_NOTPERMITTED */ - -ENOMEM, /* BCME_NOMEM */ - -EINVAL, /* BCME_ASSOCIATED */ - -ERANGE, /* BCME_RANGE */ - -EINVAL, /* BCME_NOTFOUND */ - -EINVAL, /* BCME_WME_NOT_ENABLED */ - -EINVAL, /* BCME_TSPEC_NOTFOUND */ - -EINVAL, /* BCME_ACM_NOTSUPPORTED */ - -EINVAL, /* BCME_NOT_WME_ASSOCIATION */ - -EIO, /* BCME_SDIO_ERROR */ - -ENODEV, /* BCME_DONGLE_DOWN */ - -EINVAL, /* BCME_VERSION */ - -EIO, /* BCME_TXFAIL */ - -EIO, /* BCME_RXFAIL */ - -EINVAL, /* BCME_NODEVICE */ - -EINVAL, /* BCME_NMODE_DISABLED */ - -ENODATA, /* BCME_NONRESIDENT */ - -/* When an new error code is added to bcmutils.h, add os - * spcecific error translation here as well - */ -/* check if BCME_LAST changed since the last time this function was updated */ -#if BCME_LAST != -42 -#error "You need to add a OS error translation in the linuxbcmerrormap \ - for new error code defined in bcmutils.h" -#endif -}; - -/* translate bcmerrors into linux errors */ -int osl_error(int bcmerror) -{ - if (bcmerror > 0) - bcmerror = 0; - else if (bcmerror < BCME_LAST) - bcmerror = BCME_ERROR; - - /* Array bounds covered by ASSERT in osl_attach */ - return linuxbcmerrormap[-bcmerror]; -} -#endif /* BRCM_FULLMAC */ - -osl_t *osl_attach(void *pdev, uint bustype, bool pkttag) +osl_t *osl_attach(void *pdev, uint bustype) { osl_t *osh; @@ -120,15 +54,8 @@ osl_t *osl_attach(void *pdev, uint bustype, bool pkttag) bzero(osh, sizeof(osl_t)); -#ifdef BRCM_FULLMAC - /* Check that error map has the right number of entries in it */ - ASSERT(ABS(BCME_LAST) == (ARRAY_SIZE(linuxbcmerrormap) - 1)); -#endif /* BRCM_FULLMAC */ - osh->magic = OS_HANDLE_MAGIC; - osh->failed = 0; osh->pdev = pdev; - osh->pub.pkttag = pkttag; osh->bustype = bustype; switch (bustype) { @@ -149,12 +76,6 @@ osl_t *osl_attach(void *pdev, uint bustype, bool pkttag) break; } -#if defined(BCMDBG) && !defined(BRCM_FULLMAC) - if (pkttag) { - struct sk_buff *skb; - ASSERT(OSL_PKTTAG_SZ <= sizeof(skb->cb)); - } -#endif return osh; } @@ -167,7 +88,6 @@ void osl_detach(osl_t *osh) kfree(osh); } -/* Return a new packet. zero out pkttag */ void *BCMFASTPATH osl_pktget(osl_t *osh, uint len) { struct sk_buff *skb; @@ -282,11 +202,6 @@ uint osl_pci_slot(osl_t *osh) return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); } -uint osl_dma_consistent_align(void) -{ - return PAGE_SIZE; -} - void *osl_dma_alloc_consistent(osl_t *osh, uint size, u16 align_bits, uint *alloced, unsigned long *pap) { @@ -294,7 +209,7 @@ void *osl_dma_alloc_consistent(osl_t *osh, uint size, u16 align_bits, if (align_bits) { u16 align = (1 << align_bits); - if (!IS_ALIGNED(DMA_CONSISTENT_ALIGN, align)) + if (!IS_ALIGNED(PAGE_SIZE, align)) size += align; *alloced = size; } diff --git a/trunk/drivers/staging/brcm80211/util/nicpci.c b/trunk/drivers/staging/brcm80211/util/nicpci.c index 23f86dd7b159..169a4287ee63 100644 --- a/trunk/drivers/staging/brcm80211/util/nicpci.c +++ b/trunk/drivers/staging/brcm80211/util/nicpci.c @@ -15,7 +15,7 @@ */ #include -#include +#include #include #include #include diff --git a/trunk/drivers/staging/brcm80211/util/sbutils.c b/trunk/drivers/staging/brcm80211/util/sbutils.c index e4c0baba553d..82767e266e97 100644 --- a/trunk/drivers/staging/brcm80211/util/sbutils.c +++ b/trunk/drivers/staging/brcm80211/util/sbutils.c @@ -16,6 +16,9 @@ #include #include +#ifdef BRCM_FULLMAC +#include +#endif #include #include #include diff --git a/trunk/drivers/staging/brcm80211/util/siutils.c b/trunk/drivers/staging/brcm80211/util/siutils.c index f3ea7e1a7aef..3b99293307ea 100644 --- a/trunk/drivers/staging/brcm80211/util/siutils.c +++ b/trunk/drivers/staging/brcm80211/util/siutils.c @@ -17,8 +17,12 @@ #include #include #include +#ifdef BRCM_FULLMAC +#include +#endif #include -#include +#include +#include #include #include #include diff --git a/trunk/drivers/staging/comedi/drivers/addi-data/addi_common.c b/trunk/drivers/staging/comedi/drivers/addi-data/addi_common.c index 93d7c056741d..76f2483871a7 100644 --- a/trunk/drivers/staging/comedi/drivers/addi-data/addi_common.c +++ b/trunk/drivers/staging/comedi/drivers/addi-data/addi_common.c @@ -2710,10 +2710,10 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it) } else { outl(0x83838383, devpriv->i_IobaseAmcc + 0x60); } - /* Enable the interrupt for the controler */ + /* Enable the interrupt for the controller */ dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38); outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38); - printk("\nEnable the interrupt for the controler"); + printk("\nEnable the interrupt for the controller"); } printk("\nRead Eeprom"); i_EepromReadMainHeader(io_addr[0], this_board->pc_EepromChip, diff --git a/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c index 912bc0fc54bf..a76ed2553fb4 100644 --- a/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c +++ b/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c @@ -225,7 +225,7 @@ int i_APCI1710_Reset(struct comedi_device *dev) devpriv->s_BoardInfos.b_BoardVersion = 1; - /* Enable the interrupt for the controler */ + /* Enable the interrupt for the controller */ dw_Dummy = inl(devpriv->s_BoardInfos.ui_Address + 0x38); outl(dw_Dummy | 0x2000, devpriv->s_BoardInfos.ui_Address + 0x38); diff --git a/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c index b943a06e70dc..a93e2349ad3a 100644 --- a/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c +++ b/trunk/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c @@ -3011,7 +3011,7 @@ int i_APCI3200_Reset(struct comedi_device *dev) outl(0x83838383, devpriv->i_IobaseAmcc + 0x60); - /* Enable the interrupt for the controler */ + /* Enable the interrupt for the controller */ dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38); outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38); outl(0, devpriv->i_IobaseAddon); /* Resets the output */ diff --git a/trunk/drivers/staging/comedi/drivers/rtd520.c b/trunk/drivers/staging/comedi/drivers/rtd520.c index 60ebfc3c75fd..aa8aeeee043f 100644 --- a/trunk/drivers/staging/comedi/drivers/rtd520.c +++ b/trunk/drivers/staging/comedi/drivers/rtd520.c @@ -753,7 +753,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; struct pci_dev *pcidev; int ret; - resource_size_t physLas0; /* configuation */ + resource_size_t physLas0; /* configuration */ resource_size_t physLas1; /* data area */ resource_size_t physLcfg; /* PLX9080 */ #ifdef USE_DMA diff --git a/trunk/drivers/staging/cptm1217/Kconfig b/trunk/drivers/staging/cptm1217/Kconfig new file mode 100644 index 000000000000..f90545d78f93 --- /dev/null +++ b/trunk/drivers/staging/cptm1217/Kconfig @@ -0,0 +1,11 @@ +config TOUCHSCREEN_CLEARPAD_TM1217 + tristate "Synaptics Clearpad TM1217" + depends on I2C + depends on GPIOLIB + help + Say Y here if you have a Synaptics Clearpad TM1217 Controller + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called clearpad_tm1217. diff --git a/trunk/drivers/staging/cptm1217/Makefile b/trunk/drivers/staging/cptm1217/Makefile new file mode 100644 index 000000000000..8961fafa80e7 --- /dev/null +++ b/trunk/drivers/staging/cptm1217/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += clearpad_tm1217.o + diff --git a/trunk/drivers/staging/cptm1217/TODO b/trunk/drivers/staging/cptm1217/TODO new file mode 100644 index 000000000000..303922465e4d --- /dev/null +++ b/trunk/drivers/staging/cptm1217/TODO @@ -0,0 +1,5 @@ +- Wait for the official upstream general clearpad drivers as promised over + the past few months +- Merge any device support needed from this driver into it +- Delete this driver + diff --git a/trunk/drivers/staging/cptm1217/clearpad_tm1217.c b/trunk/drivers/staging/cptm1217/clearpad_tm1217.c new file mode 100644 index 000000000000..269503f9516f --- /dev/null +++ b/trunk/drivers/staging/cptm1217/clearpad_tm1217.c @@ -0,0 +1,675 @@ +/* + * clearpad_tm1217.c - Touch Screen driver for Synaptics Clearpad + * TM1217 controller + * + * Copyright (C) 2008 Intel Corp + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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; ifnot, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * Questions/Comments/Bug fixes to Ramesh Agarwal (ramesh.agarwal@intel.com) + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cp_tm1217.h" + +#define CPTM1217_DEVICE_NAME "cptm1217" +#define CPTM1217_DRIVER_NAME CPTM1217_DEVICE_NAME + +#define MAX_TOUCH_SUPPORTED 2 +#define TOUCH_SUPPORTED 1 +#define SAMPLING_FREQ 80 /* Frequency in HZ */ +#define DELAY_BTWIN_SAMPLE (1000 / SAMPLING_FREQ) +#define WAIT_FOR_RESPONSE 5 /* 5msec just works */ +#define MAX_RETRIES 5 /* As above */ +#define INCREMENTAL_DELAY 5 /* As above */ + +/* Regster Definitions */ +#define TMA1217_DEV_STATUS 0x13 /* Device Status */ +#define TMA1217_INT_STATUS 0x14 /* Interrupt Status */ + +/* Controller can detect upto 2 possible finger touches. + * Each finger touch provides 12 bit X Y co-ordinates, the values are split + * across 2 registers, and an 8 bit Z value */ +#define TMA1217_FINGER_STATE 0x18 /* Finger State */ +#define TMA1217_FINGER1_X_HIGHER8 0x19 /* Higher 8 bit of X coordinate */ +#define TMA1217_FINGER1_Y_HIGHER8 0x1A /* Higher 8 bit of Y coordinate */ +#define TMA1217_FINGER1_XY_LOWER4 0x1B /* Lower 4 bits of X and Y */ +#define TMA1217_FINGER1_Z_VALUE 0x1D /* 8 bit Z value for finger 1 */ +#define TMA1217_FINGER2_X_HIGHER8 0x1E /* Higher 8 bit of X coordinate */ +#define TMA1217_FINGER2_Y_HIGHER8 0x1F /* Higher 8 bit of Y coordinate */ +#define TMA1217_FINGER2_XY_LOWER4 0x20 /* Lower 4 bits of X and Y */ +#define TMA1217_FINGER2_Z_VALUE 0x22 /* 8 bit Z value for finger 2 */ +#define TMA1217_DEVICE_CTRL 0x23 /* Device Control */ +#define TMA1217_INTERRUPT_ENABLE 0x24 /* Interrupt Enable */ +#define TMA1217_REPORT_MODE 0x2B /* Reporting Mode */ +#define TMA1217_MAX_X_LOWER8 0x31 /* Bit 0-7 for Max X */ +#define TMA1217_MAX_X_HIGHER4 0x32 /* Bit 8-11 for Max X */ +#define TMA1217_MAX_Y_LOWER8 0x33 /* Bit 0-7 for Max Y */ +#define TMA1217_MAX_Y_HIGHER4 0x34 /* Bit 8-11 for Max Y */ +#define TMA1217_DEVICE_CMD_RESET 0x67 /* Device CMD reg for reset */ +#define TMA1217_DEVICE_CMD_REZERO 0x69 /* Device CMD reg for rezero */ + +#define TMA1217_MANUFACTURER_ID 0x73 /* Manufacturer Id */ +#define TMA1217_PRODUCT_FAMILY 0x75 /* Product Family */ +#define TMA1217_FIRMWARE_REVISION 0x76 /* Firmware Revision */ +#define TMA1217_SERIAL_NO_HIGH 0x7C /* Bit 8-15 of device serial no. */ +#define TMA1217_SERIAL_NO_LOW 0x7D /* Bit 0-7 of device serial no. */ +#define TMA1217_PRODUCT_ID_START 0x7E /* Start address for 10 byte ID */ +#define TMA1217_DEVICE_CAPABILITY 0x8B /* Reporting capability */ + + +/* + * The touch position structure. + */ +struct touch_state { + int x; + int y; + bool button; +}; + +/* Device Specific info given by the controller */ +struct cp_dev_info { + u16 maxX; + u16 maxY; +}; + +/* Vendor related info given by the controller */ +struct cp_vendor_info { + u8 vendor_id; + u8 product_family; + u8 firmware_rev; + u16 serial_no; +}; + +/* + * Private structure to store the device details + */ +struct cp_tm1217_device { + struct i2c_client *client; + struct device *dev; + struct cp_vendor_info vinfo; + struct cp_dev_info dinfo; + struct input_dev_info { + char phys[32]; + char name[128]; + struct input_dev *input; + struct touch_state touch; + } cp_input_info[MAX_TOUCH_SUPPORTED]; + + int thread_running; + struct mutex thread_mutex; + + int gpio; +}; + + +/* The following functions are used to read/write registers on the device + * as per the RMI prorocol. Technically, a page select should be written + * before doing read/write but since the register offsets are below 0xFF + * we can use the default value of page which is 0x00 + */ +static int cp_tm1217_read(struct cp_tm1217_device *ts, + u8 *req, int size) +{ + int i, retval; + + /* Send the address */ + retval = i2c_master_send(ts->client, &req[0], 1); + if (retval != 1) { + dev_err(ts->dev, "cp_tm1217: I2C send failed\n"); + return retval; + } + msleep(WAIT_FOR_RESPONSE); + for (i = 0; i < MAX_RETRIES; i++) { + retval = i2c_master_recv(ts->client, &req[1], size); + if (retval == size) { + break; + } else { + msleep(INCREMENTAL_DELAY); + dev_dbg(ts->dev, "cp_tm1217: Retry count is %d\n", i); + } + } + if (retval != size) + dev_err(ts->dev, "cp_tm1217: Read from device failed\n"); + + return retval; +} + +static int cp_tm1217_write(struct cp_tm1217_device *ts, + u8 *req, int size) +{ + int retval; + + /* Send the address and the data to be written */ + retval = i2c_master_send(ts->client, &req[0], size + 1); + if (retval != size + 1) { + dev_err(ts->dev, "cp_tm1217: I2C write failed: %d\n", retval); + return retval; + } + /* Wait for the write to complete. TBD why this is required */ + msleep(WAIT_FOR_RESPONSE); + + return size; +} + +static int cp_tm1217_mask_interrupt(struct cp_tm1217_device *ts) +{ + u8 req[2]; + int retval; + + req[0] = TMA1217_INTERRUPT_ENABLE; + req[1] = 0x0; + retval = cp_tm1217_write(ts, req, 1); + if (retval != 1) + return -EIO; + + return 0; +} + +static int cp_tm1217_unmask_interrupt(struct cp_tm1217_device *ts) +{ + u8 req[2]; + int retval; + + req[0] = TMA1217_INTERRUPT_ENABLE; + req[1] = 0xa; + retval = cp_tm1217_write(ts, req, 1); + if (retval != 1) + return -EIO; + + return 0; +} + +static void process_touch(struct cp_tm1217_device *ts, int index) +{ + int retval; + struct input_dev_info *input_info = + (struct input_dev_info *)&ts->cp_input_info[index]; + u8 xy_data[6]; + + if (index == 0) + xy_data[0] = TMA1217_FINGER1_X_HIGHER8; + else + xy_data[0] = TMA1217_FINGER2_X_HIGHER8; + + retval = cp_tm1217_read(ts, xy_data, 5); + if (retval < 5) { + dev_err(ts->dev, "cp_tm1217: XY read from device failed\n"); + return; + } + + /* Note: Currently not using the Z values but may be requried in + the future. */ + input_info->touch.x = (xy_data[1] << 4) + | (xy_data[3] & 0x0F); + input_info->touch.y = (xy_data[2] << 4) + | ((xy_data[3] & 0xF0) >> 4); + input_report_abs(input_info->input, ABS_X, input_info->touch.x); + input_report_abs(input_info->input, ABS_Y, input_info->touch.y); + input_sync(input_info->input); +} + +static void cp_tm1217_get_data(struct cp_tm1217_device *ts) +{ + u8 req[2]; + int retval, i, finger_touched = 0; + + do { + req[0] = TMA1217_FINGER_STATE; + retval = cp_tm1217_read(ts, req, 1); + if (retval != 1) { + dev_err(ts->dev, + "cp_tm1217: Read from device failed\n"); + continue; + } + finger_touched = 0; + /* Start sampling until the pressure is below + threshold */ + for (i = 0; i < TOUCH_SUPPORTED; i++) { + if (req[1] & 0x3) { + finger_touched++; + if (ts->cp_input_info[i].touch.button == 0) { + /* send the button touch event */ + input_report_key( + ts->cp_input_info[i].input, + BTN_TOUCH, 1); + ts->cp_input_info[i].touch.button = 1; + } + process_touch(ts, i); + } else { + if (ts->cp_input_info[i].touch.button == 1) { + /* send the button release event */ + input_report_key( + ts->cp_input_info[i].input, + BTN_TOUCH, 0); + input_sync(ts->cp_input_info[i].input); + ts->cp_input_info[i].touch.button = 0; + } + } + req[1] = req[1] >> 2; + } + msleep(DELAY_BTWIN_SAMPLE); + } while (finger_touched > 0); +} + +static irqreturn_t cp_tm1217_sample_thread(int irq, void *handle) +{ + struct cp_tm1217_device *ts = (struct cp_tm1217_device *) handle; + u8 req[2]; + int retval; + + /* Chedk if another thread is already running */ + mutex_lock(&ts->thread_mutex); + if (ts->thread_running == 1) { + mutex_unlock(&ts->thread_mutex); + return IRQ_HANDLED; + } else { + ts->thread_running = 1; + mutex_unlock(&ts->thread_mutex); + } + + /* Mask the interrupts */ + retval = cp_tm1217_mask_interrupt(ts); + + /* Read the Interrupt Status register to find the cause of the + Interrupt */ + req[0] = TMA1217_INT_STATUS; + retval = cp_tm1217_read(ts, req, 1); + if (retval != 1) + goto exit_thread; + + if (!(req[1] & 0x8)) + goto exit_thread; + + cp_tm1217_get_data(ts); + +exit_thread: + /* Unmask the interrupts before going to sleep */ + retval = cp_tm1217_unmask_interrupt(ts); + + mutex_lock(&ts->thread_mutex); + ts->thread_running = 0; + mutex_unlock(&ts->thread_mutex); + + return IRQ_HANDLED; +} + +static int cp_tm1217_init_data(struct cp_tm1217_device *ts) +{ + int retval; + u8 req[2]; + + /* Read the vendor id/ fw revision etc. Ignoring return check as this + is non critical info */ + req[0] = TMA1217_MANUFACTURER_ID; + retval = cp_tm1217_read(ts, req, 1); + ts->vinfo.vendor_id = req[1]; + + req[0] = TMA1217_PRODUCT_FAMILY; + retval = cp_tm1217_read(ts, req, 1); + ts->vinfo.product_family = req[1]; + + req[0] = TMA1217_FIRMWARE_REVISION; + retval = cp_tm1217_read(ts, req, 1); + ts->vinfo.firmware_rev = req[1]; + + req[0] = TMA1217_SERIAL_NO_HIGH; + retval = cp_tm1217_read(ts, req, 1); + ts->vinfo.serial_no = (req[1] << 8); + + req[0] = TMA1217_SERIAL_NO_LOW; + retval = cp_tm1217_read(ts, req, 1); + ts->vinfo.serial_no = ts->vinfo.serial_no | req[1]; + + req[0] = TMA1217_MAX_X_HIGHER4; + retval = cp_tm1217_read(ts, req, 1); + ts->dinfo.maxX = (req[1] & 0xF) << 8; + + req[0] = TMA1217_MAX_X_LOWER8; + retval = cp_tm1217_read(ts, req, 1); + ts->dinfo.maxX = ts->dinfo.maxX | req[1]; + + req[0] = TMA1217_MAX_Y_HIGHER4; + retval = cp_tm1217_read(ts, req, 1); + ts->dinfo.maxY = (req[1] & 0xF) << 8; + + req[0] = TMA1217_MAX_Y_LOWER8; + retval = cp_tm1217_read(ts, req, 1); + ts->dinfo.maxY = ts->dinfo.maxY | req[1]; + + return 0; + +} + +/* + * Set up a GPIO for use as the interrupt. We can't simply do this at + * boot time because the GPIO drivers themselves may not be around at + * boot/firmware set up time to do the work. Instead defer it to driver + * detection. + */ + +static int cp_tm1217_setup_gpio_irq(struct cp_tm1217_device *ts) +{ + int retval; + + /* Hook up the irq handler */ + retval = gpio_request(ts->gpio, "cp_tm1217_touch"); + if (retval < 0) { + dev_err(ts->dev, "cp_tm1217: GPIO request failed error %d\n", + retval); + return retval; + } + + retval = gpio_direction_input(ts->gpio); + if (retval < 0) { + dev_err(ts->dev, + "cp_tm1217: GPIO direction configuration failed, error %d\n", + retval); + gpio_free(ts->gpio); + return retval; + } + + retval = gpio_to_irq(ts->gpio); + if (retval < 0) { + dev_err(ts->dev, "cp_tm1217: GPIO to IRQ failedi," + " error %d\n", retval); + gpio_free(ts->gpio); + } + dev_dbg(ts->dev, + "cp_tm1217: Got IRQ number is %d for GPIO %d\n", + retval, ts->gpio); + return retval; +} + +static int cp_tm1217_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct cp_tm1217_device *ts; + struct input_dev *input_dev; + struct input_dev_info *input_info; + struct cp_tm1217_platform_data *pdata; + u8 req[2]; + int i, retval; + + /* No pdata is fine - we then use "normal" IRQ mode */ + + pdata = client->dev.platform_data; + + ts = kzalloc(sizeof(struct cp_tm1217_device), GFP_KERNEL); + if (!ts) { + dev_err(&client->dev, + "cp_tm1217: Private Device Struct alloc failed\n"); + return -ENOMEM; + } + + ts->client = client; + ts->dev = &client->dev; + i2c_set_clientdata(client, ts); + + ts->thread_running = 0; + mutex_init(&ts->thread_mutex); + + /* Reset the Controller */ + req[0] = TMA1217_DEVICE_CMD_RESET; + req[1] = 0x1; + retval = cp_tm1217_write(ts, req, 1); + if (retval != 1) { + dev_err(ts->dev, "cp_tm1217: Controller reset failed\n"); + kfree(ts); + return -EIO; + } + + /* Clear up the interrupt status from reset. */ + req[0] = TMA1217_INT_STATUS; + retval = cp_tm1217_read(ts, req, 1); + + /* Mask all the interrupts */ + retval = cp_tm1217_mask_interrupt(ts); + + /* Read the controller information */ + cp_tm1217_init_data(ts); + + /* The following code will register multiple event devices when + multi-pointer is enabled, the code has not been tested + with MPX */ + for (i = 0; i < TOUCH_SUPPORTED; i++) { + input_dev = input_allocate_device(); + if (input_dev == NULL) { + kfree(ts); + dev_err(ts->dev, + "cp_tm1217:Input Device Struct alloc failed\n"); + return -ENOMEM; + } + input_info = &ts->cp_input_info[i]; + snprintf(input_info->name, sizeof(input_info->name), + "cp_tm1217_touchscreen_%d", i); + input_dev->name = input_info->name; + snprintf(input_info->phys, sizeof(input_info->phys), + "%s/input%d", dev_name(&client->dev), i); + + input_dev->phys = input_info->phys; + input_dev->id.bustype = BUS_I2C; + + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + + input_set_abs_params(input_dev, ABS_X, 0, ts->dinfo.maxX, 0, 0); + input_set_abs_params(input_dev, ABS_Y, 0, ts->dinfo.maxY, 0, 0); + + retval = input_register_device(input_dev); + if (retval) { + dev_err(ts->dev, + "Input dev registration failed for %s\n", + input_dev->name); + goto fail; + } + input_info->input = input_dev; + } + + /* Setup the reporting mode to send an interrupt only when + finger arrives or departs. */ + req[0] = TMA1217_REPORT_MODE; + req[1] = 0x02; + retval = cp_tm1217_write(ts, req, 1); + + /* Setup the device to no sleep mode for now and make it configured */ + req[0] = TMA1217_DEVICE_CTRL; + req[1] = 0x84; + retval = cp_tm1217_write(ts, req, 1); + + /* Check for the status of the device */ + req[0] = TMA1217_DEV_STATUS; + retval = cp_tm1217_read(ts, req, 1); + if (req[1] != 0) { + dev_err(ts->dev, + "cp_tm1217: Device Status 0x%x != 0: config failed\n", + req[1]); + + retval = -EIO; + goto fail; + } + + if (pdata && pdata->gpio) { + ts->gpio = pdata->gpio; + retval = cp_tm1217_setup_gpio_irq(ts); + } else + retval = client->irq; + + if (retval < 0) { + dev_err(ts->dev, "cp_tm1217: GPIO request failed error %d\n", + retval); + goto fail; + } + + client->irq = retval; + + + retval = request_threaded_irq(client->irq, + NULL, cp_tm1217_sample_thread, + IRQF_TRIGGER_FALLING, "cp_tm1217_touch", ts); + if (retval < 0) { + dev_err(ts->dev, "cp_tm1217: Request IRQ error %d\n", retval); + goto fail_gpio; + } + + /* Unmask the interrupts */ + retval = cp_tm1217_unmask_interrupt(ts); + if (retval == 0) + return 0; + + free_irq(client->irq, ts); +fail_gpio: + if (ts->gpio) + gpio_free(ts->gpio); +fail: + /* Clean up before returning failure */ + for (i = 0; i < TOUCH_SUPPORTED; i++) { + if (ts->cp_input_info[i].input) { + input_unregister_device(ts->cp_input_info[i].input); + input_free_device(ts->cp_input_info[i].input); + } + } + kfree(ts); + return retval; + +} + +/* + * cp_tm1217 suspend + * + */ +static int cp_tm1217_suspend(struct i2c_client *client, pm_message_t mesg) +{ + struct cp_tm1217_device *ts = i2c_get_clientdata(client); + u8 req[2]; + int retval; + + /* Put the controller to sleep */ + req[0] = TMA1217_DEVICE_CTRL; + retval = cp_tm1217_read(ts, req, 1); + req[1] = (req[1] & 0xF8) | 0x1; + retval = cp_tm1217_write(ts, req, 1); + + if (device_may_wakeup(&client->dev)) + enable_irq_wake(client->irq); + + return 0; +} + +/* + * cp_tm1217_resume + * + */ +static int cp_tm1217_resume(struct i2c_client *client) +{ + struct cp_tm1217_device *ts = i2c_get_clientdata(client); + u8 req[2]; + int retval; + + /* Take the controller out of sleep */ + req[0] = TMA1217_DEVICE_CTRL; + retval = cp_tm1217_read(ts, req, 1); + req[1] = (req[1] & 0xF8) | 0x4; + retval = cp_tm1217_write(ts, req, 1); + + /* Restore the register settings sinc the power to the + could have been cut off */ + + /* Setup the reporting mode to send an interrupt only when + finger arrives or departs. */ + req[0] = TMA1217_REPORT_MODE; + req[1] = 0x02; + retval = cp_tm1217_write(ts, req, 1); + + /* Setup the device to no sleep mode for now and make it configured */ + req[0] = TMA1217_DEVICE_CTRL; + req[1] = 0x84; + retval = cp_tm1217_write(ts, req, 1); + + /* Setup the interrupt mask */ + retval = cp_tm1217_unmask_interrupt(ts); + + if (device_may_wakeup(&client->dev)) + disable_irq_wake(client->irq); + + return 0; +} + +/* + * cp_tm1217_remove + * + */ +static int cp_tm1217_remove(struct i2c_client *client) +{ + struct cp_tm1217_device *ts = i2c_get_clientdata(client); + int i; + + free_irq(client->irq, ts); + if (ts->gpio) + gpio_free(ts->gpio); + for (i = 0; i < TOUCH_SUPPORTED; i++) + input_unregister_device(ts->cp_input_info[i].input); + kfree(ts); + return 0; +} + +static struct i2c_device_id cp_tm1217_idtable[] = { + { CPTM1217_DEVICE_NAME, 0 }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, cp_tm1217_idtable); + +static struct i2c_driver cp_tm1217_driver = { + .driver = { + .owner = THIS_MODULE, + .name = CPTM1217_DRIVER_NAME, + }, + .id_table = cp_tm1217_idtable, + .probe = cp_tm1217_probe, + .remove = cp_tm1217_remove, + .suspend = cp_tm1217_suspend, + .resume = cp_tm1217_resume, +}; + +static int __init clearpad_tm1217_init(void) +{ + return i2c_add_driver(&cp_tm1217_driver); +} + +static void __exit clearpad_tm1217_exit(void) +{ + i2c_del_driver(&cp_tm1217_driver); +} + +module_init(clearpad_tm1217_init); +module_exit(clearpad_tm1217_exit); + +MODULE_AUTHOR("Ramesh Agarwal "); +MODULE_DESCRIPTION("Synaptics TM1217 TouchScreen Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/cptm1217/cp_tm1217.h b/trunk/drivers/staging/cptm1217/cp_tm1217.h new file mode 100644 index 000000000000..a0ce31db53f8 --- /dev/null +++ b/trunk/drivers/staging/cptm1217/cp_tm1217.h @@ -0,0 +1,9 @@ +#ifndef __LINUX_I2C_CP_TM1217_H +#define __LINUX_I2C_CP_TM1217_H + +struct cp_tm1217_platform_data +{ + int gpio; /* If not set uses the IRQ resource 0 */ +}; + +#endif diff --git a/trunk/drivers/staging/frontier/alphatrack.c b/trunk/drivers/staging/frontier/alphatrack.c index ef7fbf8b069a..2babb034a254 100644 --- a/trunk/drivers/staging/frontier/alphatrack.c +++ b/trunk/drivers/staging/frontier/alphatrack.c @@ -89,7 +89,7 @@ static int debug = ALPHATRACK_DEBUG; /* Use our own dbg macro */ #define dbg_info(dev, format, arg...) do \ - { if (debug) dev_info(dev , format , ## arg); } while (0) + { if (debug) dev_info(dev , format , ## arg); } while (0) #define alphatrack_ocmd_info(dev, cmd, format, arg...) @@ -769,7 +769,7 @@ static int usb_alphatrack_probe(struct usb_interface *intf, } dev->write_buffer = - kmalloc(sizeof(struct alphatrack_ocmd) * true_size, GFP_KERNEL); + kmalloc(true_size * sizeof(struct alphatrack_ocmd), GFP_KERNEL); if (!dev->write_buffer) { dev_err(&intf->dev, "Couldn't allocate write_buffer\n"); diff --git a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_chdev.c b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_chdev.c index 87a6487531c2..920ca52d6e4b 100644 --- a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_chdev.c +++ b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_chdev.c @@ -64,7 +64,7 @@ spinlock_t free_buff_lock; int numofmsgbuf = 0; // Global variable to indicate that all provisioning data is sent to DSP -//BOOLEAN fProvComplete; +//bool fProvComplete; // // Table of entry-point routines for char device @@ -623,10 +623,10 @@ static long ft1000_ChIoctl (struct file *File, unsigned int Command, memcpy(get_stat_data.eui64, info->eui64, EUISZ); if (info->ProgConStat != 0xFF) { - ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_LED, (PUCHAR)&ledStat, FT1000_MAG_DSP_LED_INDX); + ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_LED, (u8 *)&ledStat, FT1000_MAG_DSP_LED_INDX); get_stat_data.LedStat = ntohs(ledStat); DEBUG("FT1000:ft1000_ChIoctl: LedStat = 0x%x\n", get_stat_data.LedStat); - ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_CON_STATE, (PUCHAR)&conStat, FT1000_MAG_DSP_CON_STATE_INDX); + ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_CON_STATE, (u8 *)&conStat, FT1000_MAG_DSP_CON_STATE_INDX); get_stat_data.ConStat = ntohs(conStat); DEBUG("FT1000:ft1000_ChIoctl: ConStat = 0x%x\n", get_stat_data.ConStat); } @@ -653,12 +653,12 @@ static long ft1000_ChIoctl (struct file *File, unsigned int Command, { IOCTL_DPRAM_BLK *dpram_data; //IOCTL_DPRAM_COMMAND dpram_command; - USHORT qtype; - USHORT msgsz; + u16 qtype; + u16 msgsz; struct pseudo_hdr *ppseudo_hdr; - PUSHORT pmsg; - USHORT total_len; - USHORT app_index; + u16 *pmsg; + u16 total_len; + u16 app_index; u16 status; //DEBUG("FT1000:ft1000_ChIoctl: IOCTL_FT1000_SET_DPRAM called\n"); @@ -766,8 +766,8 @@ static long ft1000_ChIoctl (struct file *File, unsigned int Command, // Make sure we are within the limits of the slow queue memory limitation if ( (msgsz < MAX_CMD_SQSIZE) && (msgsz > PSEUDOSZ) ) { // Need to put sequence number plus new checksum for message - //pmsg = (PUSHORT)&dpram_command.dpram_blk.pseudohdr; - pmsg = (PUSHORT)&dpram_data->pseudohdr; + //pmsg = (u16 *)&dpram_command.dpram_blk.pseudohdr; + pmsg = (u16 *)&dpram_data->pseudohdr; ppseudo_hdr = (struct pseudo_hdr *)pmsg; total_len = msgsz+2; if (total_len & 0x1) { diff --git a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_download.c b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_download.c index 4dd456fbab9b..e4905ad2badc 100644 --- a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_download.c +++ b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_download.c @@ -123,11 +123,11 @@ struct dsp_image_info { // Notes: // //--------------------------------------------------------------------------- -static ULONG check_usb_db (struct ft1000_device *ft1000dev) +static u32 check_usb_db (struct ft1000_device *ft1000dev) { int loopcnt; - USHORT temp; - ULONG status; + u16 temp; + u32 status; loopcnt = 0; while (loopcnt < 10) @@ -190,7 +190,7 @@ static ULONG check_usb_db (struct ft1000_device *ft1000dev) // Function: get_handshake // // Parameters: struct ft1000_device - device structure -// USHORT expected_value - the handshake value expected +// u16 expected_value - the handshake value expected // // Returns: handshakevalue - success // HANDSHAKE_TIMEOUT_VALUE - failure @@ -200,11 +200,11 @@ static ULONG check_usb_db (struct ft1000_device *ft1000dev) // Notes: // //--------------------------------------------------------------------------- -static USHORT get_handshake(struct ft1000_device *ft1000dev, USHORT expected_value) +static u16 get_handshake(struct ft1000_device *ft1000dev, u16 expected_value) { - USHORT handshake; + u16 handshake; int loopcnt; - ULONG status=0; + u32 status=0; struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net); loopcnt = 0; @@ -228,7 +228,7 @@ static USHORT get_handshake(struct ft1000_device *ft1000dev, USHORT expected_val status = ft1000_write_register (ft1000dev, FT1000_DB_DNLD_RX, FT1000_REG_DOORBELL); } - status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, (PUCHAR)&handshake, 1); + status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, (u8 *)&handshake, 1); //DEBUG("get_handshake: handshake is %x\n", tempx); handshake = ntohs(handshake); //DEBUG("get_handshake: after swap, handshake is %x\n", handshake); @@ -259,7 +259,7 @@ static USHORT get_handshake(struct ft1000_device *ft1000dev, USHORT expected_val // Function: put_handshake // // Parameters: struct ft1000_device - device structure -// USHORT handshake_value - handshake to be written +// u16 handshake_value - handshake to be written // // Returns: none // @@ -269,30 +269,30 @@ static USHORT get_handshake(struct ft1000_device *ft1000dev, USHORT expected_val // Notes: // //--------------------------------------------------------------------------- -static void put_handshake(struct ft1000_device *ft1000dev,USHORT handshake_value) +static void put_handshake(struct ft1000_device *ft1000dev,u16 handshake_value) { - ULONG tempx; - USHORT tempword; - ULONG status; + u32 tempx; + u16 tempword; + u32 status; - tempx = (ULONG)handshake_value; + tempx = (u32)handshake_value; tempx = ntohl(tempx); - tempword = (USHORT)(tempx & 0xffff); + tempword = (u16)(tempx & 0xffff); status = ft1000_write_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, tempword, 0); - tempword = (USHORT)(tempx >> 16); + tempword = (u16)(tempx >> 16); status = ft1000_write_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, tempword, 1); status = ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX, FT1000_REG_DOORBELL); } -static USHORT get_handshake_usb(struct ft1000_device *ft1000dev, USHORT expected_value) +static u16 get_handshake_usb(struct ft1000_device *ft1000dev, u16 expected_value) { - USHORT handshake; + u16 handshake; int loopcnt; - USHORT temp; - ULONG status=0; + u16 temp; + u32 status=0; struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net); loopcnt = 0; @@ -300,10 +300,10 @@ static USHORT get_handshake_usb(struct ft1000_device *ft1000dev, USHORT expected while (loopcnt < 100) { if (pft1000info->usbboot == 2) { - status = ft1000_read_dpram32 (ft1000dev, 0, (PUCHAR)&(pft1000info->tempbuf[0]), 64); + status = ft1000_read_dpram32 (ft1000dev, 0, (u8 *)&(pft1000info->tempbuf[0]), 64); for (temp=0; temp<16; temp++) DEBUG("tempbuf %d = 0x%x\n", temp, pft1000info->tempbuf[temp]); - status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, (PUCHAR)&handshake, 1); + status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, (u8 *)&handshake, 1); DEBUG("handshake from read_dpram16 = 0x%x\n", handshake); if (pft1000info->dspalive == pft1000info->tempbuf[6]) handshake = 0; @@ -313,7 +313,7 @@ static USHORT get_handshake_usb(struct ft1000_device *ft1000dev, USHORT expected } } else { - status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, (PUCHAR)&handshake, 1); + status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, (u8 *)&handshake, 1); } loopcnt++; msleep(10); @@ -327,7 +327,7 @@ static USHORT get_handshake_usb(struct ft1000_device *ft1000dev, USHORT expected return HANDSHAKE_TIMEOUT_VALUE; } -static void put_handshake_usb(struct ft1000_device *ft1000dev,USHORT handshake_value) +static void put_handshake_usb(struct ft1000_device *ft1000dev,u16 handshake_value) { int i; @@ -346,44 +346,44 @@ static void put_handshake_usb(struct ft1000_device *ft1000dev,USHORT handshake_v // Notes: // //--------------------------------------------------------------------------- -static USHORT get_request_type(struct ft1000_device *ft1000dev) +static u16 get_request_type(struct ft1000_device *ft1000dev) { - USHORT request_type; - ULONG status; - USHORT tempword; - ULONG tempx; + u16 request_type; + u32 status; + u16 tempword; + u32 tempx; struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net); if ( pft1000info->bootmode == 1) { - status = fix_ft1000_read_dpram32 (ft1000dev, DWNLD_MAG1_TYPE_LOC, (PUCHAR)&tempx); + status = fix_ft1000_read_dpram32 (ft1000dev, DWNLD_MAG1_TYPE_LOC, (u8 *)&tempx); tempx = ntohl(tempx); } else { tempx = 0; - status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_TYPE_LOC, (PUCHAR)&tempword, 1); + status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_TYPE_LOC, (u8 *)&tempword, 1); tempx |= (tempword << 16); tempx = ntohl(tempx); } - request_type = (USHORT)tempx; + request_type = (u16)tempx; //DEBUG("get_request_type: request_type is %x\n", request_type); return request_type; } -static USHORT get_request_type_usb(struct ft1000_device *ft1000dev) +static u16 get_request_type_usb(struct ft1000_device *ft1000dev) { - USHORT request_type; - ULONG status; - USHORT tempword; - ULONG tempx; + u16 request_type; + u32 status; + u16 tempword; + u32 tempx; struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net); if ( pft1000info->bootmode == 1) { - status = fix_ft1000_read_dpram32 (ft1000dev, DWNLD_MAG1_TYPE_LOC, (PUCHAR)&tempx); + status = fix_ft1000_read_dpram32 (ft1000dev, DWNLD_MAG1_TYPE_LOC, (u8 *)&tempx); tempx = ntohl(tempx); } else @@ -394,12 +394,12 @@ static USHORT get_request_type_usb(struct ft1000_device *ft1000dev) } else { tempx = 0; - status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_TYPE_LOC, (PUCHAR)&tempword, 1); + status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_TYPE_LOC, (u8 *)&tempword, 1); } tempx |= (tempword << 16); tempx = ntohl(tempx); } - request_type = (USHORT)tempx; + request_type = (u16)tempx; //DEBUG("get_request_type: request_type is %x\n", request_type); return request_type; @@ -420,22 +420,22 @@ static USHORT get_request_type_usb(struct ft1000_device *ft1000dev) //--------------------------------------------------------------------------- static long get_request_value(struct ft1000_device *ft1000dev) { - ULONG value; - USHORT tempword; - ULONG status; + u32 value; + u16 tempword; + u32 status; struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net); if ( pft1000info->bootmode == 1) { - status = fix_ft1000_read_dpram32(ft1000dev, DWNLD_MAG1_SIZE_LOC, (PUCHAR)&value); + status = fix_ft1000_read_dpram32(ft1000dev, DWNLD_MAG1_SIZE_LOC, (u8 *)&value); value = ntohl(value); } else { - status = ft1000_read_dpram16(ft1000dev, DWNLD_MAG1_SIZE_LOC, (PUCHAR)&tempword, 0); + status = ft1000_read_dpram16(ft1000dev, DWNLD_MAG1_SIZE_LOC, (u8 *)&tempword, 0); value = tempword; - status = ft1000_read_dpram16(ft1000dev, DWNLD_MAG1_SIZE_LOC, (PUCHAR)&tempword, 1); + status = ft1000_read_dpram16(ft1000dev, DWNLD_MAG1_SIZE_LOC, (u8 *)&tempword, 1); value |= (tempword << 16); value = ntohl(value); } @@ -449,9 +449,9 @@ static long get_request_value(struct ft1000_device *ft1000dev) #if 0 static long get_request_value_usb(struct ft1000_device *ft1000dev) { - ULONG value; - USHORT tempword; - ULONG status; + u32 value; + u16 tempword; + u32 status; struct ft1000_info * pft1000info = netdev_priv(ft1000dev->net); if (pft1000info->usbboot == 2) { @@ -460,7 +460,7 @@ static long get_request_value_usb(struct ft1000_device *ft1000dev) } else { value = 0; - status = ft1000_read_dpram16(ft1000dev, DWNLD_MAG1_SIZE_LOC, (PUCHAR)&tempword, 1); + status = ft1000_read_dpram16(ft1000dev, DWNLD_MAG1_SIZE_LOC, (u8 *)&tempword, 1); } value |= (tempword << 16); @@ -490,11 +490,11 @@ static long get_request_value_usb(struct ft1000_device *ft1000dev) //--------------------------------------------------------------------------- static void put_request_value(struct ft1000_device *ft1000dev, long lvalue) { - ULONG tempx; - ULONG status; + u32 tempx; + u32 status; tempx = ntohl(lvalue); - status = fix_ft1000_write_dpram32(ft1000dev, DWNLD_MAG1_SIZE_LOC, (PUCHAR)&tempx); + status = fix_ft1000_write_dpram32(ft1000dev, DWNLD_MAG1_SIZE_LOC, (u8 *)&tempx); @@ -516,10 +516,10 @@ static void put_request_value(struct ft1000_device *ft1000dev, long lvalue) // Notes: // //--------------------------------------------------------------------------- -static USHORT hdr_checksum(struct pseudo_hdr *pHdr) +static u16 hdr_checksum(struct pseudo_hdr *pHdr) { - USHORT *usPtr = (USHORT *)pHdr; - USHORT chksum; + u16 *usPtr = (u16 *)pHdr; + u16 chksum; chksum = ((((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^ @@ -533,8 +533,8 @@ static USHORT hdr_checksum(struct pseudo_hdr *pHdr) // Function: write_blk // // Parameters: struct ft1000_device - device structure -// USHORT **pUsFile - DSP image file pointer in USHORT -// UCHAR **pUcFile - DSP image file pointer in UCHAR +// u16 **pUsFile - DSP image file pointer in u16 +// u8 **pUcFile - DSP image file pointer in u8 // long word_length - lenght of the buffer to be written // to DPRAM // @@ -546,20 +546,20 @@ static USHORT hdr_checksum(struct pseudo_hdr *pHdr) // Notes: // //--------------------------------------------------------------------------- -static ULONG write_blk (struct ft1000_device *ft1000dev, USHORT **pUsFile, UCHAR **pUcFile, long word_length) +static u32 write_blk (struct ft1000_device *ft1000dev, u16 **pUsFile, u8 **pUcFile, long word_length) { - ULONG Status = STATUS_SUCCESS; - USHORT dpram; + u32 Status = STATUS_SUCCESS; + u16 dpram; long temp_word_length; int loopcnt, i, j; - USHORT *pTempFile; - USHORT tempword; - USHORT tempbuffer[64]; - USHORT resultbuffer[64]; + u16 *pTempFile; + u16 tempword; + u16 tempbuffer[64]; + u16 resultbuffer[64]; struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net); //DEBUG("FT1000:download:start word_length = %d\n",(int)word_length); - dpram = (USHORT)DWNLD_MAG1_PS_HDR_LOC; + dpram = (u16)DWNLD_MAG1_PS_HDR_LOC; tempword = *(*pUsFile); (*pUsFile)++; Status = ft1000_write_dpram16(ft1000dev, dpram, tempword, 0); @@ -569,7 +569,7 @@ static ULONG write_blk (struct ft1000_device *ft1000dev, USHORT **pUsFile, UCHAR *pUcFile = *pUcFile + 4; word_length--; - tempword = (USHORT)word_length; + tempword = (u16)word_length; word_length = (word_length / 16) + 1; pTempFile = *pUsFile; temp_word_length = word_length; @@ -602,24 +602,24 @@ static ULONG write_blk (struct ft1000_device *ft1000dev, USHORT **pUsFile, UCHAR if (pft1000info->bootmode == 0) { if (dpram >= 0x3F4) - Status = ft1000_write_dpram32 (ft1000dev, dpram, (PUCHAR)&tempbuffer[0], 8); + Status = ft1000_write_dpram32 (ft1000dev, dpram, (u8 *)&tempbuffer[0], 8); else - Status = ft1000_write_dpram32 (ft1000dev, dpram, (PUCHAR)&tempbuffer[0], 64); + Status = ft1000_write_dpram32 (ft1000dev, dpram, (u8 *)&tempbuffer[0], 64); } else { for (j=0; j<10; j++) { - Status = ft1000_write_dpram32 (ft1000dev, dpram, (PUCHAR)&tempbuffer[0], 64); + Status = ft1000_write_dpram32 (ft1000dev, dpram, (u8 *)&tempbuffer[0], 64); if (Status == STATUS_SUCCESS) { // Work around for ASIC bit stuffing problem. if ( (tempbuffer[31] & 0xfe00) == 0xfe00) { - Status = ft1000_write_dpram32(ft1000dev, dpram+12, (PUCHAR)&tempbuffer[24], 64); + Status = ft1000_write_dpram32(ft1000dev, dpram+12, (u8 *)&tempbuffer[24], 64); } // Let's check the data written - Status = ft1000_read_dpram32 (ft1000dev, dpram, (PUCHAR)&resultbuffer[0], 64); + Status = ft1000_read_dpram32 (ft1000dev, dpram, (u8 *)&resultbuffer[0], 64); if ( (tempbuffer[31] & 0xfe00) == 0xfe00) { for (i=0; i<28; i++) @@ -633,7 +633,7 @@ static ULONG write_blk (struct ft1000_device *ft1000dev, USHORT **pUsFile, UCHAR break; } } - Status = ft1000_read_dpram32 (ft1000dev, dpram+12, (PUCHAR)&resultbuffer[0], 64); + Status = ft1000_read_dpram32 (ft1000dev, dpram+12, (u8 *)&resultbuffer[0], 64); for (i=0; i<16; i++) { if (resultbuffer[i] != tempbuffer[i+24]) @@ -689,8 +689,8 @@ static void usb_dnld_complete (struct urb *urb) // Function: write_blk_fifo // // Parameters: struct ft1000_device - device structure -// USHORT **pUsFile - DSP image file pointer in USHORT -// UCHAR **pUcFile - DSP image file pointer in UCHAR +// u16 **pUsFile - DSP image file pointer in u16 +// u8 **pUcFile - DSP image file pointer in u8 // long word_length - lenght of the buffer to be written // to DPRAM // @@ -702,9 +702,9 @@ static void usb_dnld_complete (struct urb *urb) // Notes: // //--------------------------------------------------------------------------- -static ULONG write_blk_fifo (struct ft1000_device *ft1000dev, USHORT **pUsFile, UCHAR **pUcFile, long word_length) +static u32 write_blk_fifo (struct ft1000_device *ft1000dev, u16 **pUsFile, u8 **pUcFile, long word_length) { - ULONG Status = STATUS_SUCCESS; + u32 Status = STATUS_SUCCESS; int byte_length; long aligncnt; @@ -770,36 +770,36 @@ static ULONG write_blk_fifo (struct ft1000_device *ft1000dev, USHORT **pUsFile, // Returns: status - return code //--------------------------------------------------------------------------- -u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, ULONG FileLength) +u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, u32 FileLength) { u16 Status = STATUS_SUCCESS; - UINT uiState; - USHORT handshake; + u32 uiState; + u16 handshake; struct pseudo_hdr *pHdr; - USHORT usHdrLength; + u16 usHdrLength; long word_length; - USHORT request; - USHORT temp; - USHORT tempword; + u16 request; + u16 temp; + u16 tempword; struct dsp_file_hdr *pFileHdr5; struct dsp_image_info *pDspImageInfoV6 = NULL; long requested_version; - BOOLEAN bGoodVersion; + bool bGoodVersion; struct drv_msg *pMailBoxData; - USHORT *pUsData = NULL; - USHORT *pUsFile = NULL; - UCHAR *pUcFile = NULL; - UCHAR *pBootEnd = NULL, *pCodeEnd= NULL; + u16 *pUsData = NULL; + u16 *pUsFile = NULL; + u8 *pUcFile = NULL; + u8 *pBootEnd = NULL, *pCodeEnd= NULL; int imageN; long loader_code_address, loader_code_size = 0; long run_address = 0, run_size = 0; - ULONG templong; - ULONG image_chksum = 0; + u32 templong; + u32 image_chksum = 0; - USHORT dpram = 0; - PUCHAR pbuffer; + u16 dpram = 0; + u8 *pbuffer; struct prov_record *pprov_record; struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net); @@ -820,10 +820,10 @@ u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, ULONG FileLe ft1000_write_register (ft1000dev, 0x800, FT1000_REG_MAG_WATERMARK); - pUsFile = (USHORT *)(pFileStart + pFileHdr5->loader_offset); - pUcFile = (UCHAR *)(pFileStart + pFileHdr5->loader_offset); + pUsFile = (u16 *)(pFileStart + pFileHdr5->loader_offset); + pUcFile = (u8 *)(pFileStart + pFileHdr5->loader_offset); - pBootEnd = (UCHAR *)(pFileStart + pFileHdr5->loader_code_end); + pBootEnd = (u8 *)(pFileStart + pFileHdr5->loader_code_end); loader_code_address = pFileHdr5->loader_code_address; loader_code_size = pFileHdr5->loader_code_size; @@ -878,8 +878,8 @@ u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, ULONG FileLe case REQUEST_DONE_BL: DEBUG("FT1000:REQUEST_DONE_BL\n"); /* Reposition ptrs to beginning of code section */ - pUsFile = (USHORT *)(pBootEnd); - pUcFile = (UCHAR *)(pBootEnd); + pUsFile = (u16 *)(pBootEnd); + pUcFile = (u8 *)(pBootEnd); //DEBUG("FT1000:download:pUsFile = 0x%8x\n", (int)pUsFile); //DEBUG("FT1000:download:pUcFile = 0x%8x\n", (int)pUcFile); uiState = STATE_CODE_DWNLD; @@ -909,7 +909,7 @@ u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, ULONG FileLe /* * Position ASIC DPRAM auto-increment pointer. */ - dpram = (USHORT)DWNLD_MAG1_PS_HDR_LOC; + dpram = (u16)DWNLD_MAG1_PS_HDR_LOC; if (word_length & 0x1) word_length++; word_length = word_length / 2; @@ -988,8 +988,8 @@ u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, ULONG FileLe case REQUEST_DONE_CL: pft1000info->usbboot = 3; /* Reposition ptrs to beginning of provisioning section */ - pUsFile = (USHORT *)(pFileStart + pFileHdr5->commands_offset); - pUcFile = (UCHAR *)(pFileStart + pFileHdr5->commands_offset); + pUsFile = (u16 *)(pFileStart + pFileHdr5->commands_offset); + pUcFile = (u8 *)(pFileStart + pFileHdr5->commands_offset); uiState = STATE_DONE_DWNLD; break; case REQUEST_CODE_SEGMENT: @@ -1027,7 +1027,7 @@ u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, ULONG FileLe /* * Position ASIC DPRAM auto-increment pointer. */ - dpram = (USHORT)DWNLD_MAG1_PS_HDR_LOC; + dpram = (u16)DWNLD_MAG1_PS_HDR_LOC; if (word_length & 0x1) word_length++; word_length = word_length / 2; @@ -1053,8 +1053,8 @@ u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, ULONG FileLe */ - pUsData = (USHORT *)&pMailBoxData->data[0]; - dpram = (USHORT)DWNLD_MAG1_PS_HDR_LOC; + pUsData = (u16 *)&pMailBoxData->data[0]; + dpram = (u16)DWNLD_MAG1_PS_HDR_LOC; if (word_length & 0x1) word_length++; @@ -1066,7 +1066,7 @@ u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, ULONG FileLe templong = *pUsData++; templong |= (*pUsData++ << 16); - Status = fix_ft1000_write_dpram32 (ft1000dev, dpram++, (PUCHAR)&templong); + Status = fix_ft1000_write_dpram32 (ft1000dev, dpram++, (u8 *)&templong); } break; @@ -1079,10 +1079,10 @@ u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, ULONG FileLe * Position ASIC DPRAM auto-increment pointer. */ - pUsFile = (USHORT *)(pFileStart + pFileHdr5->version_data_offset); + pUsFile = (u16 *)(pFileStart + pFileHdr5->version_data_offset); - dpram = (USHORT)DWNLD_MAG1_PS_HDR_LOC; + dpram = (u16)DWNLD_MAG1_PS_HDR_LOC; if (word_length & 0x1) word_length++; @@ -1095,7 +1095,7 @@ u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, ULONG FileLe templong = ntohs(*pUsFile++); temp = ntohs(*pUsFile++); templong |= (temp << 16); - Status = fix_ft1000_write_dpram32 (ft1000dev, dpram++, (PUCHAR)&templong); + Status = fix_ft1000_write_dpram32 (ft1000dev, dpram++, (u8 *)&templong); } break; @@ -1110,20 +1110,20 @@ u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, ULONG FileLe for (imageN = 0; imageN < pFileHdr5->nDspImages; imageN++) { - temp = (USHORT)(pDspImageInfoV6->version); + temp = (u16)(pDspImageInfoV6->version); templong = temp; - temp = (USHORT)(pDspImageInfoV6->version >> 16); + temp = (u16)(pDspImageInfoV6->version >> 16); templong |= (temp << 16); - if (templong == (ULONG)requested_version) + if (templong == (u32)requested_version) { bGoodVersion = TRUE; DEBUG("FT1000:download: bGoodVersion is TRUE\n"); - pUsFile = (USHORT *)(pFileStart + pDspImageInfoV6->begin_offset); - pUcFile = (UCHAR *)(pFileStart + pDspImageInfoV6->begin_offset); - pCodeEnd = (UCHAR *)(pFileStart + pDspImageInfoV6->end_offset); + pUsFile = (u16 *)(pFileStart + pDspImageInfoV6->begin_offset); + pUcFile = (u8 *)(pFileStart + pDspImageInfoV6->begin_offset); + pCodeEnd = (u8 *)(pFileStart + pDspImageInfoV6->end_offset); run_address = pDspImageInfoV6->run_address; run_size = pDspImageInfoV6->image_size; - image_chksum = (ULONG)pDspImageInfoV6->checksum; + image_chksum = (u32)pDspImageInfoV6->checksum; break; } pDspImageInfoV6++; @@ -1181,14 +1181,14 @@ u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, ULONG FileLe // Get buffer for provisioning data pbuffer = kmalloc((usHdrLength + sizeof(struct pseudo_hdr)), GFP_ATOMIC); if (pbuffer) { - memcpy(pbuffer, (void *)pUcFile, (UINT)(usHdrLength + sizeof(struct pseudo_hdr))); + memcpy(pbuffer, (void *)pUcFile, (u32)(usHdrLength + sizeof(struct pseudo_hdr))); // link provisioning data pprov_record = kmalloc(sizeof(struct prov_record), GFP_ATOMIC); if (pprov_record) { pprov_record->pprov_data = pbuffer; list_add_tail (&pprov_record->list, &pft1000info->prov_list); // Move to next entry if available - pUcFile = (UCHAR *)((unsigned long)pUcFile + (UINT)((usHdrLength + 1) & 0xFFFFFFFE) + sizeof(struct pseudo_hdr)); + pUcFile = (u8 *)((unsigned long)pUcFile + (u32)((usHdrLength + 1) & 0xFFFFFFFE) + sizeof(struct pseudo_hdr)); if ( (unsigned long)(pUcFile) - (unsigned long)(pFileStart) >= (unsigned long)FileLength) { uiState = STATE_DONE_FILE; } diff --git a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c index 5b89ee2a2971..b41884e60d07 100644 --- a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c +++ b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c @@ -45,33 +45,6 @@ static unsigned long gCardIndex; #define MAX_RCV_LOOP 100 -/**************************************************************** - * ft1000_control_complete - ****************************************************************/ -static void ft1000_control_complete(struct urb *urb) -{ - struct ft1000_device *ft1000dev = (struct ft1000_device *)urb->context; - - //DEBUG("FT1000_CONTROL_COMPLETE ENTERED\n"); - if (ft1000dev == NULL ) - { - DEBUG("NULL ft1000dev, failure\n"); - return ; - } - else if ( ft1000dev->dev == NULL ) - { - DEBUG("NULL ft1000dev->dev, failure\n"); - return ; - } - - if(waitqueue_active(&ft1000dev->control_wait)) - { - wake_up(&ft1000dev->control_wait); - } - - //DEBUG("FT1000_CONTROL_COMPLETE RETURNED\n"); -} - //--------------------------------------------------------------------------- // Function: ft1000_control // @@ -187,7 +160,7 @@ u16 ft1000_read_register(struct ft1000_device *ft1000dev, u16* Data, u16 nRegInd // Notes: // //--------------------------------------------------------------------------- -u16 ft1000_write_register(struct ft1000_device *ft1000dev, USHORT value, u16 nRegIndx) +u16 ft1000_write_register(struct ft1000_device *ft1000dev, u16 value, u16 nRegIndx) { u16 ret = STATUS_SUCCESS; @@ -223,7 +196,7 @@ u16 ft1000_write_register(struct ft1000_device *ft1000dev, USHORT value, u16 nRe // //--------------------------------------------------------------------------- -u16 ft1000_read_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer, USHORT cnt) +u16 ft1000_read_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u16 cnt) { u16 ret = STATUS_SUCCESS; @@ -262,7 +235,7 @@ u16 ft1000_read_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buf // Notes: // //--------------------------------------------------------------------------- -u16 ft1000_write_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer, USHORT cnt) +u16 ft1000_write_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u16 cnt) { u16 ret = STATUS_SUCCESS; @@ -299,7 +272,7 @@ u16 ft1000_write_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR bu // Notes: // //--------------------------------------------------------------------------- -u16 ft1000_read_dpram16(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer, u8 highlow) +u16 ft1000_read_dpram16(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u8 highlow) { u16 ret = STATUS_SUCCESS; @@ -347,7 +320,7 @@ u16 ft1000_read_dpram16(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buf // Notes: // //--------------------------------------------------------------------------- -u16 ft1000_write_dpram16(struct ft1000_device *ft1000dev, USHORT indx, USHORT value, u8 highlow) +u16 ft1000_write_dpram16(struct ft1000_device *ft1000dev, u16 indx, u16 value, u8 highlow) { u16 ret = STATUS_SUCCESS; @@ -392,10 +365,10 @@ u16 ft1000_write_dpram16(struct ft1000_device *ft1000dev, USHORT indx, USHORT va // Notes: // //--------------------------------------------------------------------------- -u16 fix_ft1000_read_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer) +u16 fix_ft1000_read_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer) { - UCHAR buf[16]; - USHORT pos; + u8 buf[16]; + u16 pos; u16 ret = STATUS_SUCCESS; //DEBUG("fix_ft1000_read_dpram32: indx: %d \n", indx); @@ -441,14 +414,14 @@ u16 fix_ft1000_read_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR // Notes: // //--------------------------------------------------------------------------- -u16 fix_ft1000_write_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer) +u16 fix_ft1000_write_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer) { - USHORT pos1; - USHORT pos2; - USHORT i; - UCHAR buf[32]; - UCHAR resultbuffer[32]; - PUCHAR pdata; + u16 pos1; + u16 pos2; + u16 i; + u8 buf[32]; + u8 resultbuffer[32]; + u8 *pdata; u16 ret = STATUS_SUCCESS; //DEBUG("fix_ft1000_write_dpram32: Entered:\n"); @@ -472,7 +445,7 @@ u16 fix_ft1000_write_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHA return ret; } - ret = ft1000_read_dpram32(ft1000dev, pos1, (PUCHAR)&resultbuffer[0], 16); + ret = ft1000_read_dpram32(ft1000dev, pos1, (u8 *)&resultbuffer[0], 16); if (ret == STATUS_SUCCESS) { buffer = pdata; @@ -487,8 +460,8 @@ u16 fix_ft1000_write_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHA if (ret == STATUS_FAILURE) { - ret = ft1000_write_dpram32(ft1000dev, pos1, (PUCHAR)&tempbuffer[0], 16); - ret = ft1000_read_dpram32(ft1000dev, pos1, (PUCHAR)&resultbuffer[0], 16); + ret = ft1000_write_dpram32(ft1000dev, pos1, (u8 *)&tempbuffer[0], 16); + ret = ft1000_read_dpram32(ft1000dev, pos1, (u8 *)&resultbuffer[0], 16); if (ret == STATUS_SUCCESS) { buffer = pdata; @@ -518,10 +491,10 @@ u16 fix_ft1000_write_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHA // // Returns: None //----------------------------------------------------------------------- -static void card_reset_dsp (struct ft1000_device *ft1000dev, BOOLEAN value) +static void card_reset_dsp (struct ft1000_device *ft1000dev, bool value) { u16 status = STATUS_SUCCESS; - USHORT tempword; + u16 tempword; status = ft1000_write_register (ft1000dev, HOST_INTF_BE, FT1000_REG_SUP_CTRL); status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_SUP_CTRL); @@ -620,8 +593,8 @@ void CardSendCommand(struct ft1000_device *ft1000dev, void *ptempbuffer, int siz int dsp_reload(struct ft1000_device *ft1000dev) { u16 status; - USHORT tempword; - ULONG templong; + u16 tempword; + u32 templong; struct ft1000_info *pft1000info; @@ -648,7 +621,7 @@ int dsp_reload(struct ft1000_device *ft1000dev) status = ft1000_write_register (ft1000dev, HOST_INTF_BE, FT1000_REG_SUP_CTRL); // Let's check for FEFE - status = ft1000_read_dpram32 (ft1000dev, FT1000_MAG_DPRAM_FEFE_INDX, (PUCHAR)&templong, 4); + status = ft1000_read_dpram32 (ft1000dev, FT1000_MAG_DPRAM_FEFE_INDX, (u8 *)&templong, 4); DEBUG("templong (fefe) = 0x%8x\n", templong); // call codeloader @@ -753,7 +726,7 @@ static int ft1000_reset_card (struct net_device *dev) // Initialize DSP heartbeat area to ho ft1000_write_dpram16(ft1000dev, FT1000_MAG_HI_HO, ho_mag, FT1000_MAG_HI_HO_INDX); - ft1000_read_dpram16(ft1000dev, FT1000_MAG_HI_HO, (PCHAR)&tempword, FT1000_MAG_HI_HO_INDX); + ft1000_read_dpram16(ft1000dev, FT1000_MAG_HI_HO, (u8 *)&tempword, FT1000_MAG_HI_HO_INDX); DEBUG("ft1000_hw:ft1000_reset_card:hi_ho value = 0x%x\n", tempword); @@ -874,10 +847,7 @@ u16 init_ft1000_netdev(struct ft1000_device *ft1000dev) pInfo->fCondResetPend = 0; pInfo->usbboot = 0; pInfo->dspalive = 0; - for (i=0;i<32 ;i++ ) - { - pInfo->tempbuf[i] = 0; - } + memset(&pInfo->tempbuf[0], 0, sizeof(pInfo->tempbuf)); INIT_LIST_HEAD(&pInfo->prov_list); @@ -1026,178 +996,6 @@ static void ft1000_usb_transmit_complete(struct urb *urb) //DEBUG("Return from ft1000_usb_transmit_complete\n"); } - -/**************************************************************** - * ft1000_control - ****************************************************************/ -static int ft1000_read_fifo_reg(struct ft1000_device *ft1000dev,unsigned int pipe, - u8 request, - u8 requesttype, - u16 value, - u16 index, - void *data, - u16 size, - int timeout) -{ - u16 ret; - - DECLARE_WAITQUEUE(wait, current); - struct urb *urb; - struct usb_ctrlrequest *dr; - int status; - - if (ft1000dev == NULL ) - { - DEBUG("NULL ft1000dev, failure\n"); - return STATUS_FAILURE; - } - else if ( ft1000dev->dev == NULL ) - { - DEBUG("NULL ft1000dev->dev, failure\n"); - return STATUS_FAILURE; - } - - spin_lock(&ft1000dev->device_lock); - - if(in_interrupt()) - { - spin_unlock(&ft1000dev->device_lock); - return -EBUSY; - } - - urb = usb_alloc_urb(0, GFP_KERNEL); - dr = kmalloc(sizeof(struct usb_ctrlrequest), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); - - if(!urb || !dr) - { - kfree(dr); - usb_free_urb(urb); - spin_unlock(&ft1000dev->device_lock); - return -ENOMEM; - } - - - - dr->bRequestType = requesttype; - dr->bRequest = request; - dr->wValue = value; - dr->wIndex = index; - dr->wLength = size; - - usb_fill_control_urb(urb, ft1000dev->dev, pipe, (char*)dr, (void*)data, size, (void *)ft1000_control_complete, (void*)ft1000dev); - - - init_waitqueue_head(&ft1000dev->control_wait); - - set_current_state(TASK_INTERRUPTIBLE); - - add_wait_queue(&ft1000dev->control_wait, &wait); - - - - - status = usb_submit_urb(urb, GFP_KERNEL); - - if(status) - { - usb_free_urb(urb); - kfree(dr); - remove_wait_queue(&ft1000dev->control_wait, &wait); - spin_unlock(&ft1000dev->device_lock); - return status; - } - - if(urb->status == -EINPROGRESS) - { - while(timeout && urb->status == -EINPROGRESS) - { - status = timeout = schedule_timeout(timeout); - } - } - else - { - status = 1; - } - - remove_wait_queue(&ft1000dev->control_wait, &wait); - - if(!status) - { - usb_unlink_urb(urb); - printk("ft1000 timeout\n"); - status = -ETIMEDOUT; - } - else - { - status = urb->status; - - if(urb->status) - { - printk("ft1000 control message failed (urb addr: %p) with error number: %i\n", urb, (int)status); - - usb_clear_halt(ft1000dev->dev, usb_rcvctrlpipe(ft1000dev->dev, 0)); - usb_clear_halt(ft1000dev->dev, usb_sndctrlpipe(ft1000dev->dev, 0)); - usb_unlink_urb(urb); - } - } - - - - usb_free_urb(urb); - kfree(dr); - spin_unlock(&ft1000dev->device_lock); - return ret; - - -} - -//--------------------------------------------------------------------------- -// Function: ft1000_read_fifo_len -// -// Parameters: ft1000dev - device structure -// -// -// Returns: none -// -// Description: read the fifo length register content -// -// Notes: -// -//--------------------------------------------------------------------------- -static inline u16 ft1000_read_fifo_len (struct net_device *dev) -{ - u16 temp; - u16 ret; - - struct ft1000_info *info = (struct ft1000_info *) netdev_priv(dev); - struct ft1000_device *ft1000dev = info->pFt1000Dev; -// DEBUG("ft1000_read_fifo_len: enter ft1000dev %x\n", ft1000dev); //aelias [-] reason: warning: format ???%x??? expects type ???unsigned int???, but argument 2 has type ???struct ft1000_device *??? - DEBUG("ft1000_read_fifo_len: enter ft1000dev %p\n", ft1000dev); //aelias [+] reason: up - - ret = STATUS_SUCCESS; - - ret = ft1000_read_fifo_reg(ft1000dev, - usb_rcvctrlpipe(ft1000dev->dev,0), - HARLEY_READ_REGISTER, - HARLEY_READ_OPERATION, - 0, - FT1000_REG_MAG_UFSR, - &temp, - 2, - LARGE_TIMEOUT); - - if (ret>0) - ret = STATUS_SUCCESS; - else - ret = STATUS_FAILURE; - - DEBUG("ft1000_read_fifo_len: returned %d\n", temp); - - return (temp- 16); - -} - - //--------------------------------------------------------------------------- // // Function: ft1000_copy_down_pkt @@ -1219,16 +1017,15 @@ static int ft1000_copy_down_pkt (struct net_device *netdev, u8 *packet, u16 len) struct ft1000_device *pFt1000Dev = pInfo->pFt1000Dev; - int i, count, ret; - USHORT *pTemp; - USHORT checksum; + int count, ret; u8 *t; + struct pseudo_hdr hdr; if (!pInfo->CardReady) { DEBUG("ft1000_copy_down_pkt::Card Not Ready\n"); - return STATUS_FAILURE; + return -ENODEV; } @@ -1240,27 +1037,27 @@ static int ft1000_copy_down_pkt (struct net_device *netdev, u8 *packet, u16 len) { DEBUG("Error:ft1000_copy_down_pkt:Message Size Overflow!\n"); DEBUG("size = %d\n", count); - return STATUS_FAILURE; + return -EINVAL; } if ( count % 4) count = count + (4- (count %4) ); - pTemp = (PUSHORT)&(pFt1000Dev->tx_buf[0]); - *pTemp ++ = ntohs(count); - *pTemp ++ = 0x1020; - *pTemp ++ = 0x2010; - *pTemp ++ = 0x9100; - *pTemp ++ = 0; - *pTemp ++ = 0; - *pTemp ++ = 0; - pTemp = (PUSHORT)&(pFt1000Dev->tx_buf[0]); - checksum = *pTemp ++; - for (i=1; i<7; i++) - { - checksum ^= *pTemp ++; - } - *pTemp++ = checksum; + memset(&hdr, 0, sizeof(struct pseudo_hdr)); + + hdr.length = ntohs(count); + hdr.source = 0x10; + hdr.destination = 0x20; + hdr.portdest = 0x20; + hdr.portsrc = 0x10; + hdr.sh_str_id = 0x91; + hdr.control = 0x00; + + hdr.checksum = hdr.length ^ hdr.source ^ hdr.destination ^ + hdr.portdest ^ hdr.portsrc ^ hdr.sh_str_id ^ + hdr.control; + + memcpy(&pFt1000Dev->tx_buf[0], &hdr, sizeof(hdr)); memcpy(&(pFt1000Dev->tx_buf[sizeof(struct pseudo_hdr)]), packet, len); netif_stop_queue(netdev); @@ -1283,25 +1080,18 @@ static int ft1000_copy_down_pkt (struct net_device *netdev, u8 *packet, u16 len) }*/ - ret = usb_submit_urb(pFt1000Dev->tx_urb, GFP_ATOMIC); - if(ret) - { + ret = usb_submit_urb(pFt1000Dev->tx_urb, GFP_ATOMIC); + if (ret) { DEBUG("ft1000 failed tx_urb %d\n", ret); - - return STATUS_FAILURE; - - } - else - { - //DEBUG("ft1000 sucess tx_urb %d\n", ret); - - pInfo->stats.tx_packets++; - pInfo->stats.tx_bytes += (len+14); - } + return ret; + } else { + pInfo->stats.tx_packets++; + pInfo->stats.tx_bytes += (len+14); + } //DEBUG("ft1000_copy_down_pkt() exit\n"); - return STATUS_SUCCESS; + return 0; } //--------------------------------------------------------------------------- @@ -1331,14 +1121,13 @@ static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev) if ( skb == NULL ) { DEBUG ("ft1000_hw: ft1000_start_xmit:skb == NULL!!!\n" ); - return STATUS_FAILURE; + return NETDEV_TX_OK; } if ( pFt1000Dev->status & FT1000_STATUS_CLOSING) { DEBUG("network driver is closed, return\n"); - dev_kfree_skb(skb); - return STATUS_SUCCESS; + goto err; } //DEBUG("ft1000_start_xmit 1:length of packet = %d\n", skb->len); @@ -1357,28 +1146,24 @@ static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev) { /* Drop packet is mediastate is down */ DEBUG("ft1000_hw:ft1000_start_xmit:mediastate is down\n"); - dev_kfree_skb(skb); - return STATUS_SUCCESS; + goto err; } if ( (skb->len < ENET_HEADER_SIZE) || (skb->len > ENET_MAX_SIZE) ) { /* Drop packet which has invalid size */ DEBUG("ft1000_hw:ft1000_start_xmit:invalid ethernet length\n"); - dev_kfree_skb(skb); - return STATUS_SUCCESS; + goto err; } //mbelian - if(ft1000_copy_down_pkt (dev, (pdata+ENET_HEADER_SIZE-2), skb->len - ENET_HEADER_SIZE + 2) == STATUS_FAILURE) - { - dev_kfree_skb(skb); - return STATUS_SUCCESS; - } + ft1000_copy_down_pkt(dev, (pdata+ENET_HEADER_SIZE-2), + skb->len - ENET_HEADER_SIZE + 2); - dev_kfree_skb(skb); +err: + dev_kfree_skb(skb); //DEBUG(" ft1000_start_xmit() exit\n"); - return 0; + return NETDEV_TX_OK; } //--------------------------------------------------------------------------- @@ -1424,7 +1209,7 @@ static int ft1000_copy_up_pkt (struct urb *urb) //DEBUG("ft1000_copy_up_pkt: transfer_buffer_length=%d, actual_buffer_len=%d\n", // urb->transfer_buffer_length, urb->actual_length); - chksum = (PUSHORT)ft1000dev->rx_buf; + chksum = (u16 *)ft1000dev->rx_buf; tempword = *chksum++; for (i=1; i<7; i++) @@ -1521,7 +1306,7 @@ static int ft1000_submit_rx_urb(struct ft1000_info *info) { DEBUG("network driver is closed, return\n"); //usb_kill_urb(pFt1000Dev->rx_urb); //mbelian - return STATUS_SUCCESS; + return -ENODEV; } usb_fill_bulk_urb(pFt1000Dev->rx_urb, @@ -1536,12 +1321,12 @@ static int ft1000_submit_rx_urb(struct ft1000_info *info) if((result = usb_submit_urb(pFt1000Dev->rx_urb, GFP_ATOMIC))) { printk("ft1000_submit_rx_urb: submitting rx_urb %d failed\n", result); - return STATUS_FAILURE; + return result; } //DEBUG("ft1000_submit_rx_urb exit: result=%d\n", result); - return STATUS_SUCCESS; + return 0; } //--------------------------------------------------------------------------- @@ -1562,6 +1347,7 @@ static int ft1000_open (struct net_device *dev) { struct ft1000_info *pInfo = (struct ft1000_info *)netdev_priv(dev); struct timeval tv; //mbelian + int ret; DEBUG("ft1000_open is called for card %d\n", pInfo->CardNumber); //DEBUG("ft1000_open: dev->addr=%x, dev->addr_len=%d\n", dev->addr, dev->addr_len); @@ -1579,8 +1365,9 @@ static int ft1000_open (struct net_device *dev) netif_carrier_on(dev); //mbelian - ft1000_submit_rx_urb(pInfo); - return 0; + ret = ft1000_submit_rx_urb(pInfo); + + return ret; } //--------------------------------------------------------------------------- @@ -1692,13 +1479,13 @@ static int ft1000_chkcard (struct ft1000_device *dev) { // = 1 (successful) // //--------------------------------------------------------------------------- -static BOOLEAN ft1000_receive_cmd (struct ft1000_device *dev, u16 *pbuffer, int maxsz, u16 *pnxtph) { +static bool ft1000_receive_cmd (struct ft1000_device *dev, u16 *pbuffer, int maxsz, u16 *pnxtph) { u16 size, ret; u16 *ppseudohdr; int i; u16 tempword; - ret = ft1000_read_dpram16(dev, FT1000_MAG_PH_LEN, (PUCHAR)&size, FT1000_MAG_PH_LEN_INDX); + ret = ft1000_read_dpram16(dev, FT1000_MAG_PH_LEN, (u8 *)&size, FT1000_MAG_PH_LEN_INDX); size = ntohs(size) + PSEUDOSZ; if (size > maxsz) { DEBUG("FT1000:ft1000_receive_cmd:Invalid command length = %d\n", size); @@ -1754,9 +1541,9 @@ static int ft1000_dsp_prov(void *arg) u16 i=0; struct prov_record *ptr; struct pseudo_hdr *ppseudo_hdr; - PUSHORT pmsg; + u16 *pmsg; u16 status; - USHORT TempShortBuf [256]; + u16 TempShortBuf [256]; DEBUG("*** DspProv Entered\n"); @@ -1792,7 +1579,7 @@ static int ft1000_dsp_prov(void *arg) len = htons(len); len += PSEUDOSZ; - pmsg = (PUSHORT)ptr->pprov_data; + pmsg = (u16 *)ptr->pprov_data; ppseudo_hdr = (struct pseudo_hdr *)pmsg; // Insert slow queue sequence number ppseudo_hdr->seq_num = info->squeseqnum++; @@ -1809,7 +1596,7 @@ static int ft1000_dsp_prov(void *arg) TempShortBuf[1] = htons (len); memcpy(&TempShortBuf[2], ppseudo_hdr, len); - status = ft1000_write_dpram32 (dev, 0, (PUCHAR)&TempShortBuf[0], (unsigned short)(len+2)); + status = ft1000_write_dpram32 (dev, 0, (u8 *)&TempShortBuf[0], (unsigned short)(len+2)); status = ft1000_write_register (dev, FT1000_DB_DPRAM_TX, FT1000_REG_DOORBELL); list_del(&ptr->list); @@ -1839,7 +1626,7 @@ static int ft1000_proc_drvmsg (struct ft1000_device *dev, u16 size) { struct drv_msg *pdrvmsg; u16 i; struct pseudo_hdr *ppseudo_hdr; - PUSHORT pmsg; + u16 *pmsg; u16 status; union { u8 byte[2]; @@ -1971,7 +1758,7 @@ static int ft1000_proc_drvmsg (struct ft1000_device *dev, u16 size) { tempword = ntohs(pdrvmsg->length); info->DSPInfoBlklen = tempword; if (tempword < (MAX_DSP_SESS_REC-4) ) { - pmsg = (PUSHORT)&pdrvmsg->data[0]; + pmsg = (u16 *)&pdrvmsg->data[0]; for (i=0; i<((tempword+1)/2); i++) { DEBUG("FT1000:drivermsg:dsp info data = 0x%x\n", *pmsg); info->DSPInfoBlk[i+10] = *pmsg++; @@ -2003,10 +1790,10 @@ static int ft1000_proc_drvmsg (struct ft1000_device *dev, u16 size) { // Put message into Slow Queue // Form Pseudo header - pmsg = (PUSHORT)info->DSPInfoBlk; + pmsg = (u16 *)info->DSPInfoBlk; *pmsg++ = 0; *pmsg++ = htons(info->DSPInfoBlklen+20+info->DSPInfoBlklen); - ppseudo_hdr = (struct pseudo_hdr *)(PUSHORT)&info->DSPInfoBlk[2]; + ppseudo_hdr = (struct pseudo_hdr *)(u16 *)&info->DSPInfoBlk[2]; ppseudo_hdr->length = htons(info->DSPInfoBlklen+4+info->DSPInfoBlklen); ppseudo_hdr->source = 0x10; ppseudo_hdr->destination = 0x20; @@ -2028,7 +1815,7 @@ static int ft1000_proc_drvmsg (struct ft1000_device *dev, u16 size) { } info->DSPInfoBlk[10] = 0x7200; info->DSPInfoBlk[11] = htons(info->DSPInfoBlklen); - status = ft1000_write_dpram32 (dev, 0, (PUCHAR)&info->DSPInfoBlk[0], (unsigned short)(info->DSPInfoBlklen+22)); + status = ft1000_write_dpram32 (dev, 0, (u8 *)&info->DSPInfoBlk[0], (unsigned short)(info->DSPInfoBlklen+22)); status = ft1000_write_register (dev, FT1000_DB_DPRAM_TX, FT1000_REG_DOORBELL); info->DrvMsgPend = 0; @@ -2053,7 +1840,7 @@ static int ft1000_proc_drvmsg (struct ft1000_device *dev, u16 size) { if ( (tempword & FT1000_DB_DPRAM_TX) == 0) { // Put message into Slow Queue // Form Pseudo header - pmsg = (PUSHORT)&tempbuffer[0]; + pmsg = (u16 *)&tempbuffer[0]; ppseudo_hdr = (struct pseudo_hdr *)pmsg; ppseudo_hdr->length = htons(0x0012); ppseudo_hdr->source = 0x10; @@ -2074,7 +1861,7 @@ static int ft1000_proc_drvmsg (struct ft1000_device *dev, u16 size) { for (i=1; i<7; i++) { ppseudo_hdr->checksum ^= *pmsg++; } - pmsg = (PUSHORT)&tempbuffer[16]; + pmsg = (u16 *)&tempbuffer[16]; *pmsg++ = htons(RSP_DRV_ERR_RPT_MSG); *pmsg++ = htons(0x000e); *pmsg++ = htons(info->DSP_TIME[0]); @@ -2089,7 +1876,7 @@ static int ft1000_proc_drvmsg (struct ft1000_device *dev, u16 size) { *pmsg++ = convert.wrd; *pmsg++ = htons(info->DrvErrNum); - CardSendCommand (dev, (unsigned char*)&tempbuffer[0], (USHORT)(0x0012 + PSEUDOSZ)); + CardSendCommand (dev, (unsigned char*)&tempbuffer[0], (u16)(0x0012 + PSEUDOSZ)); info->DrvErrNum = 0; } info->DrvMsgPend = 0; @@ -2120,9 +1907,9 @@ int ft1000_poll(void* dev_id) { u16 status; u16 size; int i; - USHORT data; - USHORT modulo; - USHORT portid; + u16 data; + u16 modulo; + u16 portid; u16 nxtph; struct dpram_blk *pdpram_blk; struct pseudo_hdr *ppseudo_hdr; @@ -2143,14 +1930,14 @@ int ft1000_poll(void* dev_id) { if (tempword & FT1000_DB_DPRAM_RX) { //DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_DB_DPRAM_RX\n"); - status = ft1000_read_dpram16(dev, 0x200, (PUCHAR)&data, 0); + status = ft1000_read_dpram16(dev, 0x200, (u8 *)&data, 0); //DEBUG("ft1000_poll:FT1000_DB_DPRAM_RX:ft1000_read_dpram16:size = 0x%x\n", data); size = ntohs(data) + 16 + 2; //wai if (size % 4) { modulo = 4 - (size % 4); size = size + modulo; } - status = ft1000_read_dpram16(dev, 0x201, (PUCHAR)&portid, 1); + status = ft1000_read_dpram16(dev, 0x201, (u8 *)&portid, 1); portid &= 0xff; //DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type: FT1000_DB_DPRAM_RX : portid 0x%x\n", portid); @@ -2285,7 +2072,7 @@ int ft1000_poll(void* dev_id) { status = ft1000_write_register (dev, FT1000_ASIC_RESET_REQ, FT1000_REG_DOORBELL); status = ft1000_write_register (dev, HOST_INTF_BE, FT1000_REG_SUP_CTRL); // copy dsp session record from Adapter block - status = ft1000_write_dpram32 (dev, 0, (PUCHAR)&info->DSPSess.Rec[0], 1024); + status = ft1000_write_dpram32 (dev, 0, (u8 *)&info->DSPSess.Rec[0], 1024); // Program WMARK register status = ft1000_write_register (dev, 0x600, FT1000_REG_MAG_WATERMARK); // ring doorbell to tell DSP that ASIC is out of reset @@ -2299,10 +2086,10 @@ int ft1000_poll(void* dev_id) { if (info->fAppMsgPend == 0) { // Reset ASIC and DSP - status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER0, (PUCHAR)&(info->DSP_TIME[0]), FT1000_MAG_DSP_TIMER0_INDX); - status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER1, (PUCHAR)&(info->DSP_TIME[1]), FT1000_MAG_DSP_TIMER1_INDX); - status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER2, (PUCHAR)&(info->DSP_TIME[2]), FT1000_MAG_DSP_TIMER2_INDX); - status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER3, (PUCHAR)&(info->DSP_TIME[3]), FT1000_MAG_DSP_TIMER3_INDX); + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER0, (u8 *)&(info->DSP_TIME[0]), FT1000_MAG_DSP_TIMER0_INDX); + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER1, (u8 *)&(info->DSP_TIME[1]), FT1000_MAG_DSP_TIMER1_INDX); + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER2, (u8 *)&(info->DSP_TIME[2]), FT1000_MAG_DSP_TIMER2_INDX); + status = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER3, (u8 *)&(info->DSP_TIME[3]), FT1000_MAG_DSP_TIMER3_INDX); info->CardReady = 0; info->DrvErrNum = DSP_CONDRESET_INFO; DEBUG("ft1000_hw:DSP conditional reset requested\n"); diff --git a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_hw.h b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_hw.h index c58074131014..ab9312f9f326 100644 --- a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_hw.h +++ b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_hw.h @@ -4,7 +4,7 @@ #include "ft1000_usb.h" -extern u16 ft1000_read_register(struct usb_device *dev, PUSHORT Data, u8 nRegIndx); -extern u16 ft1000_write_register(struct usb_device *dev, USHORT value, u8 nRegIndx); +extern u16 ft1000_read_register(struct usb_device *dev, u16 *Data, u8 nRegIndx); +extern u16 ft1000_write_register(struct usb_device *dev, u16 value, u8 nRegIndx); #endif diff --git a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c index 36cdd588fa98..f665640058ae 100644 --- a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c +++ b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c @@ -38,8 +38,8 @@ //#endif -u16 ft1000_read_dpram16 (struct ft1000_device *ft1000dev, USHORT indx, - PUCHAR buffer, u8 highlow); +u16 ft1000_read_dpram16 (struct ft1000_device *ft1000dev, u16 indx, + u8 *buffer, u8 highlow); static int @@ -77,11 +77,11 @@ ft1000ReadProc (char *page, char **start, off_t off, int count, int *eof, if (info->ProgConStat != 0xFF) { ft1000_read_dpram16 (info->pFt1000Dev, FT1000_MAG_DSP_LED, - (PUCHAR) & ledStat, FT1000_MAG_DSP_LED_INDX); + (u8 *)&ledStat, FT1000_MAG_DSP_LED_INDX); info->LedStat = ntohs (ledStat); ft1000_read_dpram16 (info->pFt1000Dev, FT1000_MAG_DSP_CON_STATE, - (PUCHAR) & conStat, FT1000_MAG_DSP_CON_STATE_INDX); + (u8 *)&conStat, FT1000_MAG_DSP_CON_STATE_INDX); info->ConStat = ntohs (conStat); do_gettimeofday (&tv); delta = (tv.tv_sec - info->ConTm); diff --git a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c index 28f55b2030e9..41bbe991f0de 100644 --- a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c +++ b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c @@ -36,7 +36,7 @@ static struct usb_device_id id_table[] = { MODULE_DEVICE_TABLE(usb, id_table); -static BOOLEAN gPollingfailed = FALSE; +static bool gPollingfailed = FALSE; int ft1000_poll_thread(void *arg) { int ret = STATUS_SUCCESS; @@ -84,7 +84,6 @@ static int ft1000_probe(struct usb_interface *interface, ft1000dev->dev = dev; ft1000dev->status = 0; ft1000dev->net = NULL; - spin_lock_init(&ft1000dev->device_lock); ft1000dev->tx_urb = usb_alloc_urb(0, GFP_ATOMIC); ft1000dev->rx_urb = usb_alloc_urb(0, GFP_ATOMIC); diff --git a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h index a9d419a98a06..a07db26441f1 100644 --- a/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h +++ b/trunk/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h @@ -98,16 +98,6 @@ struct prov_record { /*end of Jim*/ #define DEBUG(args...) printk(KERN_INFO args) -#define UCHAR u8 -#define USHORT u16 -#define ULONG u32 /* WTF ??? */ -#define BOOLEAN u8 -#define PULONG u32 * -#define PUSHORT u16 * -#define PUCHAR u8 * -#define PCHAR u8 * -#define UINT u32 - #define FALSE 0 #define TRUE 1 @@ -372,15 +362,15 @@ struct prov_record { -#define ISR_EMPTY (UCHAR)0x00 // no bits set in ISR +#define ISR_EMPTY (u8)0x00 // no bits set in ISR -#define ISR_DOORBELL_ACK (UCHAR)0x01 // the doorbell i sent has been recieved. +#define ISR_DOORBELL_ACK (u8)0x01 // the doorbell i sent has been recieved. -#define ISR_DOORBELL_PEND (UCHAR)0x02 // doorbell for me +#define ISR_DOORBELL_PEND (u8)0x02 // doorbell for me -#define ISR_RCV (UCHAR)0x04 // packet received with no errors +#define ISR_RCV (u8)0x04 // packet received with no errors -#define ISR_WATERMARK (UCHAR)0x08 // +#define ISR_WATERMARK (u8)0x08 // @@ -466,12 +456,9 @@ struct ft1000_device { struct usb_device *dev; struct net_device *net; - spinlock_t device_lock; u32 status; - wait_queue_head_t control_wait; - struct urb *rx_urb; struct urb *tx_urb; @@ -497,9 +484,9 @@ struct ft1000_info { unsigned char usbboot; unsigned short dspalive; u16 ASIC_ID; - BOOLEAN fProvComplete; - BOOLEAN fCondResetPend; - BOOLEAN fAppMsgPend; + bool fProvComplete; + bool fCondResetPend; + bool fAppMsgPend; char *pfwimg; int fwimgsz; u16 DrvErrNum; @@ -567,20 +554,20 @@ struct dpram_blk { } __attribute__ ((packed)); u16 ft1000_read_register(struct ft1000_device *ft1000dev, u16* Data, u16 nRegIndx); -u16 ft1000_write_register(struct ft1000_device *ft1000dev, USHORT value, u16 nRegIndx); -u16 ft1000_read_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer, USHORT cnt); -u16 ft1000_write_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer, USHORT cnt); -u16 ft1000_read_dpram16(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer, u8 highlow); -u16 ft1000_write_dpram16(struct ft1000_device *ft1000dev, USHORT indx, USHORT value, u8 highlow); -u16 fix_ft1000_read_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer); -u16 fix_ft1000_write_dpram32(struct ft1000_device *ft1000dev, USHORT indx, PUCHAR buffer); +u16 ft1000_write_register(struct ft1000_device *ft1000dev, u16 value, u16 nRegIndx); +u16 ft1000_read_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u16 cnt); +u16 ft1000_write_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u16 cnt); +u16 ft1000_read_dpram16(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u8 highlow); +u16 ft1000_write_dpram16(struct ft1000_device *ft1000dev, u16 indx, u16 value, u8 highlow); +u16 fix_ft1000_read_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer); +u16 fix_ft1000_write_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer); extern void *pFileStart; extern size_t FileLength; extern int numofmsgbuf; int ft1000_close (struct net_device *dev); -u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, ULONG FileLength); +u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, u32 FileLength); extern struct list_head freercvpool; extern spinlock_t free_buff_lock; // lock to arbitrate free buffer list for receive command data diff --git a/trunk/drivers/staging/iio/Kconfig b/trunk/drivers/staging/iio/Kconfig index ed48815a916b..e2ac07d86110 100644 --- a/trunk/drivers/staging/iio/Kconfig +++ b/trunk/drivers/staging/iio/Kconfig @@ -42,11 +42,15 @@ config IIO_TRIGGER source "drivers/staging/iio/accel/Kconfig" source "drivers/staging/iio/adc/Kconfig" +source "drivers/staging/iio/addac/Kconfig" +source "drivers/staging/iio/dac/Kconfig" +source "drivers/staging/iio/dds/Kconfig" source "drivers/staging/iio/gyro/Kconfig" source "drivers/staging/iio/imu/Kconfig" source "drivers/staging/iio/light/Kconfig" source "drivers/staging/iio/magnetometer/Kconfig" - +source "drivers/staging/iio/meter/Kconfig" +source "drivers/staging/iio/resolver/Kconfig" source "drivers/staging/iio/trigger/Kconfig" endif # IIO diff --git a/trunk/drivers/staging/iio/Makefile b/trunk/drivers/staging/iio/Makefile index e909674920fc..f9b5fb2fe8f1 100644 --- a/trunk/drivers/staging/iio/Makefile +++ b/trunk/drivers/staging/iio/Makefile @@ -11,8 +11,13 @@ obj-$(CONFIG_IIO_SW_RING) += ring_sw.o obj-y += accel/ obj-y += adc/ +obj-y += addac/ +obj-y += dac/ +obj-y += dds/ obj-y += gyro/ obj-y += imu/ obj-y += light/ -obj-y += trigger/ obj-y += magnetometer/ +obj-y += meter/ +obj-y += resolver/ +obj-y += trigger/ diff --git a/trunk/drivers/staging/iio/TODO b/trunk/drivers/staging/iio/TODO index 898cba1c939f..d1ad35e24abb 100644 --- a/trunk/drivers/staging/iio/TODO +++ b/trunk/drivers/staging/iio/TODO @@ -61,6 +61,10 @@ necessitate a header that is also visible from arch board files. (avoided at the moment to keep the driver set contained in staging). +ADI Drivers: +CC the device-drivers-devel@blackfin.uclinux.org mailing list when +e-mailing the normal IIO list (see below). + Documentation 1) Lots of cleanup and expansion. 2) Some device require indvidual docs. diff --git a/trunk/drivers/staging/iio/accel/Kconfig b/trunk/drivers/staging/iio/accel/Kconfig index 5926c03be1a5..a34f1d3e673c 100644 --- a/trunk/drivers/staging/iio/accel/Kconfig +++ b/trunk/drivers/staging/iio/accel/Kconfig @@ -3,6 +3,33 @@ # comment "Accelerometers" +config ADIS16201 + tristate "Analog Devices ADIS16201 Dual-Axis Digital Inclinometer and Accelerometer" + depends on SPI + select IIO_TRIGGER if IIO_RING_BUFFER + select IIO_SW_RING if IIO_RING_BUFFER + help + Say yes here to build support for Analog Devices adis16201 dual-axis + digital inclinometer and accelerometer. + +config ADIS16203 + tristate "Analog Devices ADIS16203 Programmable 360 Degrees Inclinometer" + depends on SPI + select IIO_TRIGGER if IIO_RING_BUFFER + select IIO_SW_RING if IIO_RING_BUFFER + help + Say yes here to build support for Analog Devices adis16203 Programmable + 360 Degrees Inclinometer. + +config ADIS16204 + tristate "Analog Devices ADIS16204 Programmable High-g Digital Impact Sensor and Recorder" + depends on SPI + select IIO_TRIGGER if IIO_RING_BUFFER + select IIO_SW_RING if IIO_RING_BUFFER + help + Say yes here to build support for Analog Devices adis16204 Programmable + High-g Digital Impact Sensor and Recorder. + config ADIS16209 tristate "Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer" depends on SPI diff --git a/trunk/drivers/staging/iio/accel/Makefile b/trunk/drivers/staging/iio/accel/Makefile index ff84703a16f6..1b2a6d3ddafa 100644 --- a/trunk/drivers/staging/iio/accel/Makefile +++ b/trunk/drivers/staging/iio/accel/Makefile @@ -2,6 +2,18 @@ # Makefile for industrial I/O accelerometer drivers # +adis16201-y := adis16201_core.o +adis16201-$(CONFIG_IIO_RING_BUFFER) += adis16201_ring.o adis16201_trigger.o +obj-$(CONFIG_ADIS16201) += adis16201.o + +adis16203-y := adis16203_core.o +adis16203-$(CONFIG_IIO_RING_BUFFER) += adis16203_ring.o adis16203_trigger.o +obj-$(CONFIG_ADIS16203) += adis16203.o + +adis16204-y := adis16204_core.o +adis16204-$(CONFIG_IIO_RING_BUFFER) += adis16204_ring.o adis16204_trigger.o +obj-$(CONFIG_ADIS16204) += adis16204.o + adis16209-y := adis16209_core.o adis16209-$(CONFIG_IIO_RING_BUFFER) += adis16209_ring.o adis16209_trigger.o obj-$(CONFIG_ADIS16209) += adis16209.o diff --git a/trunk/drivers/staging/iio/accel/accel.h b/trunk/drivers/staging/iio/accel/accel.h index f5f61b2497aa..50651f835cea 100644 --- a/trunk/drivers/staging/iio/accel/accel.h +++ b/trunk/drivers/staging/iio/accel/accel.h @@ -65,3 +65,23 @@ #define IIO_DEV_ATTR_ACCEL_Z(_show, _addr) \ IIO_DEVICE_ATTR(accel_z_raw, S_IRUGO, _show, NULL, _addr) +#define IIO_DEV_ATTR_ACCEL_XY(_show, _addr) \ + IIO_DEVICE_ATTR(accel_xy, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ACCEL_PEAK(_show, _addr) \ + IIO_DEVICE_ATTR(accel_peak, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ACCEL_XPEAK(_show, _addr) \ + IIO_DEVICE_ATTR(accel_xpeak, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ACCEL_YPEAK(_show, _addr) \ + IIO_DEVICE_ATTR(accel_ypeak, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ACCEL_ZPEAK(_show, _addr) \ + IIO_DEVICE_ATTR(accel_zpeak, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ACCEL_XYPEAK(_show, _addr) \ + IIO_DEVICE_ATTR(accel_xypeak, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ACCEL_XYZPEAK(_show, _addr) \ + IIO_DEVICE_ATTR(accel_xyzpeak, S_IRUGO, _show, NULL, _addr) diff --git a/trunk/drivers/staging/iio/accel/adis16201.h b/trunk/drivers/staging/iio/accel/adis16201.h new file mode 100644 index 000000000000..c9bf22c13428 --- /dev/null +++ b/trunk/drivers/staging/iio/accel/adis16201.h @@ -0,0 +1,150 @@ +#ifndef SPI_ADIS16201_H_ +#define SPI_ADIS16201_H_ + +#define ADIS16201_STARTUP_DELAY 220 /* ms */ + +#define ADIS16201_READ_REG(a) a +#define ADIS16201_WRITE_REG(a) ((a) | 0x80) + +#define ADIS16201_FLASH_CNT 0x00 /* Flash memory write count */ +#define ADIS16201_SUPPLY_OUT 0x02 /* Output, power supply */ +#define ADIS16201_XACCL_OUT 0x04 /* Output, x-axis accelerometer */ +#define ADIS16201_YACCL_OUT 0x06 /* Output, y-axis accelerometer */ +#define ADIS16201_AUX_ADC 0x08 /* Output, auxiliary ADC input */ +#define ADIS16201_TEMP_OUT 0x0A /* Output, temperature */ +#define ADIS16201_XINCL_OUT 0x0C /* Output, x-axis inclination */ +#define ADIS16201_YINCL_OUT 0x0E /* Output, y-axis inclination */ +#define ADIS16201_XACCL_OFFS 0x10 /* Calibration, x-axis acceleration offset */ +#define ADIS16201_YACCL_OFFS 0x12 /* Calibration, y-axis acceleration offset */ +#define ADIS16201_XACCL_SCALE 0x14 /* x-axis acceleration scale factor */ +#define ADIS16201_YACCL_SCALE 0x16 /* y-axis acceleration scale factor */ +#define ADIS16201_XINCL_OFFS 0x18 /* Calibration, x-axis inclination offset */ +#define ADIS16201_YINCL_OFFS 0x1A /* Calibration, y-axis inclination offset */ +#define ADIS16201_XINCL_SCALE 0x1C /* x-axis inclination scale factor */ +#define ADIS16201_YINCL_SCALE 0x1E /* y-axis inclination scale factor */ +#define ADIS16201_ALM_MAG1 0x20 /* Alarm 1 amplitude threshold */ +#define ADIS16201_ALM_MAG2 0x22 /* Alarm 2 amplitude threshold */ +#define ADIS16201_ALM_SMPL1 0x24 /* Alarm 1, sample period */ +#define ADIS16201_ALM_SMPL2 0x26 /* Alarm 2, sample period */ +#define ADIS16201_ALM_CTRL 0x28 /* Alarm control */ +#define ADIS16201_AUX_DAC 0x30 /* Auxiliary DAC data */ +#define ADIS16201_GPIO_CTRL 0x32 /* General-purpose digital input/output control */ +#define ADIS16201_MSC_CTRL 0x34 /* Miscellaneous control */ +#define ADIS16201_SMPL_PRD 0x36 /* Internal sample period (rate) control */ +#define ADIS16201_AVG_CNT 0x38 /* Operation, filter configuration */ +#define ADIS16201_SLP_CNT 0x3A /* Operation, sleep mode control */ +#define ADIS16201_DIAG_STAT 0x3C /* Diagnostics, system status register */ +#define ADIS16201_GLOB_CMD 0x3E /* Operation, system command register */ + +#define ADIS16201_OUTPUTS 7 + +/* MSC_CTRL */ +#define ADIS16201_MSC_CTRL_SELF_TEST_EN (1 << 8) /* Self-test enable */ +#define ADIS16201_MSC_CTRL_DATA_RDY_EN (1 << 2) /* Data-ready enable: 1 = enabled, 0 = disabled */ +#define ADIS16201_MSC_CTRL_ACTIVE_HIGH (1 << 1) /* Data-ready polarity: 1 = active high, 0 = active low */ +#define ADIS16201_MSC_CTRL_DATA_RDY_DIO1 (1 << 0) /* Data-ready line selection: 1 = DIO1, 0 = DIO0 */ + +/* DIAG_STAT */ +#define ADIS16201_DIAG_STAT_ALARM2 (1<<9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ +#define ADIS16201_DIAG_STAT_ALARM1 (1<<8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ +#define ADIS16201_DIAG_STAT_SPI_FAIL (1<<3) /* SPI communications failure */ +#define ADIS16201_DIAG_STAT_FLASH_UPT (1<<2) /* Flash update failure */ +#define ADIS16201_DIAG_STAT_POWER_HIGH (1<<1) /* Power supply above 3.625 V */ +#define ADIS16201_DIAG_STAT_POWER_LOW (1<<0) /* Power supply below 3.15 V */ + +/* GLOB_CMD */ +#define ADIS16201_GLOB_CMD_SW_RESET (1<<7) +#define ADIS16201_GLOB_CMD_FACTORY_CAL (1<<1) + +#define ADIS16201_MAX_TX 14 +#define ADIS16201_MAX_RX 14 + +#define ADIS16201_ERROR_ACTIVE (1<<14) + +/** + * struct adis16201_state - device instance specific data + * @us: actual spi_device + * @work_trigger_to_ring: bh for triggered event handling + * @inter: used to check if new interrupt has been triggered + * @last_timestamp: passing timestamp from th to bh of interrupt handler + * @indio_dev: industrial I/O device structure + * @trig: data ready trigger registered with iio + * @tx: transmit buffer + * @rx: recieve buffer + * @buf_lock: mutex to protect tx and rx + **/ +struct adis16201_state { + struct spi_device *us; + struct work_struct work_trigger_to_ring; + s64 last_timestamp; + struct iio_dev *indio_dev; + struct iio_trigger *trig; + u8 *tx; + u8 *rx; + struct mutex buf_lock; +}; + +int adis16201_set_irq(struct device *dev, bool enable); + +#ifdef CONFIG_IIO_RING_BUFFER +enum adis16201_scan { + ADIS16201_SCAN_SUPPLY, + ADIS16201_SCAN_ACC_X, + ADIS16201_SCAN_ACC_Y, + ADIS16201_SCAN_AUX_ADC, + ADIS16201_SCAN_TEMP, + ADIS16201_SCAN_INCLI_X, + ADIS16201_SCAN_INCLI_Y, +}; + +void adis16201_remove_trigger(struct iio_dev *indio_dev); +int adis16201_probe_trigger(struct iio_dev *indio_dev); + +ssize_t adis16201_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf); + +int adis16201_configure_ring(struct iio_dev *indio_dev); +void adis16201_unconfigure_ring(struct iio_dev *indio_dev); + +int adis16201_initialize_ring(struct iio_ring_buffer *ring); +void adis16201_uninitialize_ring(struct iio_ring_buffer *ring); +#else /* CONFIG_IIO_RING_BUFFER */ + +static inline void adis16201_remove_trigger(struct iio_dev *indio_dev) +{ +} + +static inline int adis16201_probe_trigger(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline ssize_t +adis16201_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return 0; +} + +static int adis16201_configure_ring(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline void adis16201_unconfigure_ring(struct iio_dev *indio_dev) +{ +} + +static inline int adis16201_initialize_ring(struct iio_ring_buffer *ring) +{ + return 0; +} + +static inline void adis16201_uninitialize_ring(struct iio_ring_buffer *ring) +{ +} + +#endif /* CONFIG_IIO_RING_BUFFER */ +#endif /* SPI_ADIS16201_H_ */ diff --git a/trunk/drivers/staging/iio/accel/adis16201_core.c b/trunk/drivers/staging/iio/accel/adis16201_core.c new file mode 100644 index 000000000000..79b785a0013a --- /dev/null +++ b/trunk/drivers/staging/iio/accel/adis16201_core.c @@ -0,0 +1,659 @@ +/* + * ADIS16201 Programmable Digital Vibration Sensor driver + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "accel.h" +#include "inclinometer.h" +#include "../gyro/gyro.h" +#include "../adc/adc.h" + +#include "adis16201.h" + +#define DRIVER_NAME "adis16201" + +static int adis16201_check_status(struct device *dev); + +/** + * adis16201_spi_write_reg_8() - write single byte to a register + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @reg_address: the address of the register to be written + * @val: the value to write + **/ +static int adis16201_spi_write_reg_8(struct device *dev, + u8 reg_address, + u8 val) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16201_state *st = iio_dev_get_devdata(indio_dev); + + mutex_lock(&st->buf_lock); + st->tx[0] = ADIS16201_WRITE_REG(reg_address); + st->tx[1] = val; + + ret = spi_write(st->us, st->tx, 2); + mutex_unlock(&st->buf_lock); + + return ret; +} + +/** + * adis16201_spi_write_reg_16() - write 2 bytes to a pair of registers + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @reg_address: the address of the lower of the two registers. Second register + * is assumed to have address one greater. + * @val: value to be written + **/ +static int adis16201_spi_write_reg_16(struct device *dev, + u8 lower_reg_address, + u16 value) +{ + int ret; + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16201_state *st = iio_dev_get_devdata(indio_dev); + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + }, { + .tx_buf = st->tx + 2, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADIS16201_WRITE_REG(lower_reg_address); + st->tx[1] = value & 0xFF; + st->tx[2] = ADIS16201_WRITE_REG(lower_reg_address + 1); + st->tx[3] = (value >> 8) & 0xFF; + + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(st->us, &msg); + mutex_unlock(&st->buf_lock); + + return ret; +} + +/** + * adis16201_spi_read_reg_16() - read 2 bytes from a 16-bit register + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @reg_address: the address of the lower of the two registers. Second register + * is assumed to have address one greater. + * @val: somewhere to pass back the value read + **/ +static int adis16201_spi_read_reg_16(struct device *dev, + u8 lower_reg_address, + u16 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16201_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + .delay_usecs = 20, + }, { + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + .delay_usecs = 20, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADIS16201_READ_REG(lower_reg_address); + st->tx[1] = 0; + + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", + lower_reg_address); + goto error_ret; + } + *val = (st->rx[0] << 8) | st->rx[1]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static ssize_t adis16201_read_12bit_unsigned(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u16 val = 0; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = adis16201_spi_read_reg_16(dev, this_attr->address, &val); + if (ret) + return ret; + + if (val & ADIS16201_ERROR_ACTIVE) { + ret = adis16201_check_status(dev); + if (ret) + return ret; + } + + return sprintf(buf, "%u\n", val & 0x0FFF); +} + +static ssize_t adis16201_read_temp(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + ssize_t ret; + u16 val; + + /* Take the iio_dev status lock */ + mutex_lock(&indio_dev->mlock); + + ret = adis16201_spi_read_reg_16(dev, ADIS16201_TEMP_OUT, (u16 *)&val); + if (ret) + goto error_ret; + + if (val & ADIS16201_ERROR_ACTIVE) { + ret = adis16201_check_status(dev); + if (ret) + goto error_ret; + } + + val &= 0xFFF; + ret = sprintf(buf, "%d\n", val); + +error_ret: + mutex_unlock(&indio_dev->mlock); + return ret; +} + +static ssize_t adis16201_read_9bit_signed(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + s16 val = 0; + ssize_t ret; + + mutex_lock(&indio_dev->mlock); + + ret = adis16201_spi_read_reg_16(dev, this_attr->address, (u16 *)&val); + if (!ret) { + if (val & ADIS16201_ERROR_ACTIVE) { + ret = adis16201_check_status(dev); + if (ret) + goto error_ret; + } + val = ((s16)(val << 7) >> 7); + ret = sprintf(buf, "%d\n", val); + } + +error_ret: + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static ssize_t adis16201_read_12bit_signed(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + s16 val = 0; + ssize_t ret; + + mutex_lock(&indio_dev->mlock); + + ret = adis16201_spi_read_reg_16(dev, this_attr->address, (u16 *)&val); + if (!ret) { + if (val & ADIS16201_ERROR_ACTIVE) { + ret = adis16201_check_status(dev); + if (ret) + goto error_ret; + } + + val = ((s16)(val << 4) >> 4); + ret = sprintf(buf, "%d\n", val); + } + +error_ret: + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static ssize_t adis16201_read_14bit_signed(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + s16 val = 0; + ssize_t ret; + + mutex_lock(&indio_dev->mlock); + + ret = adis16201_spi_read_reg_16(dev, this_attr->address, (u16 *)&val); + if (!ret) { + if (val & ADIS16201_ERROR_ACTIVE) { + ret = adis16201_check_status(dev); + if (ret) + goto error_ret; + } + + val = ((s16)(val << 2) >> 2); + ret = sprintf(buf, "%d\n", val); + } + +error_ret: + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static ssize_t adis16201_write_16bit(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + long val; + + ret = strict_strtol(buf, 10, &val); + if (ret) + goto error_ret; + ret = adis16201_spi_write_reg_16(dev, this_attr->address, val); + +error_ret: + return ret ? ret : len; +} + +static int adis16201_reset(struct device *dev) +{ + int ret; + ret = adis16201_spi_write_reg_8(dev, + ADIS16201_GLOB_CMD, + ADIS16201_GLOB_CMD_SW_RESET); + if (ret) + dev_err(dev, "problem resetting device"); + + return ret; +} + +static ssize_t adis16201_write_reset(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + if (len < 1) + return -EINVAL; + switch (buf[0]) { + case '1': + case 'y': + case 'Y': + return adis16201_reset(dev); + } + return -EINVAL; +} + +int adis16201_set_irq(struct device *dev, bool enable) +{ + int ret = 0; + u16 msc; + + ret = adis16201_spi_read_reg_16(dev, ADIS16201_MSC_CTRL, &msc); + if (ret) + goto error_ret; + + msc |= ADIS16201_MSC_CTRL_ACTIVE_HIGH; + msc &= ~ADIS16201_MSC_CTRL_DATA_RDY_DIO1; + if (enable) + msc |= ADIS16201_MSC_CTRL_DATA_RDY_EN; + else + msc &= ~ADIS16201_MSC_CTRL_DATA_RDY_EN; + + ret = adis16201_spi_write_reg_16(dev, ADIS16201_MSC_CTRL, msc); + +error_ret: + return ret; +} + +static int adis16201_check_status(struct device *dev) +{ + u16 status; + int ret; + + ret = adis16201_spi_read_reg_16(dev, ADIS16201_DIAG_STAT, &status); + if (ret < 0) { + dev_err(dev, "Reading status failed\n"); + goto error_ret; + } + ret = status & 0xF; + if (ret) + ret = -EFAULT; + + if (status & ADIS16201_DIAG_STAT_SPI_FAIL) + dev_err(dev, "SPI failure\n"); + if (status & ADIS16201_DIAG_STAT_FLASH_UPT) + dev_err(dev, "Flash update failed\n"); + if (status & ADIS16201_DIAG_STAT_POWER_HIGH) + dev_err(dev, "Power supply above 3.625V\n"); + if (status & ADIS16201_DIAG_STAT_POWER_LOW) + dev_err(dev, "Power supply below 3.15V\n"); + +error_ret: + return ret; +} + +static int adis16201_self_test(struct device *dev) +{ + int ret; + ret = adis16201_spi_write_reg_16(dev, + ADIS16201_MSC_CTRL, + ADIS16201_MSC_CTRL_SELF_TEST_EN); + if (ret) { + dev_err(dev, "problem starting self test"); + goto err_ret; + } + + ret = adis16201_check_status(dev); + +err_ret: + return ret; +} + +static int adis16201_initial_setup(struct adis16201_state *st) +{ + int ret; + struct device *dev = &st->indio_dev->dev; + + /* Disable IRQ */ + ret = adis16201_set_irq(dev, false); + if (ret) { + dev_err(dev, "disable irq failed"); + goto err_ret; + } + + /* Do self test */ + ret = adis16201_self_test(dev); + if (ret) { + dev_err(dev, "self test failure"); + goto err_ret; + } + + /* Read status register to check the result */ + ret = adis16201_check_status(dev); + if (ret) { + adis16201_reset(dev); + dev_err(dev, "device not playing ball -> reset"); + msleep(ADIS16201_STARTUP_DELAY); + ret = adis16201_check_status(dev); + if (ret) { + dev_err(dev, "giving up"); + goto err_ret; + } + } + + printk(KERN_INFO DRIVER_NAME ": at CS%d (irq %d)\n", + st->us->chip_select, st->us->irq); + +err_ret: + return ret; +} + +static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16201_read_12bit_unsigned, + ADIS16201_SUPPLY_OUT); +static IIO_CONST_ATTR(in0_supply_scale, "0.00122"); +static IIO_DEV_ATTR_IN_RAW(1, adis16201_read_12bit_unsigned, + ADIS16201_AUX_ADC); +static IIO_CONST_ATTR(in1_scale, "0.00061"); + +static IIO_DEV_ATTR_ACCEL_X(adis16201_read_14bit_signed, + ADIS16201_XACCL_OUT); +static IIO_DEV_ATTR_ACCEL_Y(adis16201_read_14bit_signed, + ADIS16201_YACCL_OUT); +static IIO_DEV_ATTR_ACCEL_X_OFFSET(S_IWUSR | S_IRUGO, + adis16201_read_12bit_signed, + adis16201_write_16bit, + ADIS16201_XACCL_OFFS); +static IIO_DEV_ATTR_ACCEL_Y_OFFSET(S_IWUSR | S_IRUGO, + adis16201_read_12bit_signed, + adis16201_write_16bit, + ADIS16201_YACCL_OFFS); +static IIO_CONST_ATTR(accel_scale, "0.4625"); + +static IIO_DEV_ATTR_INCLI_X(adis16201_read_14bit_signed, + ADIS16201_XINCL_OUT); +static IIO_DEV_ATTR_INCLI_Y(adis16201_read_14bit_signed, + ADIS16201_YINCL_OUT); +static IIO_DEV_ATTR_INCLI_X_OFFSET(S_IWUSR | S_IRUGO, + adis16201_read_9bit_signed, + adis16201_write_16bit, + ADIS16201_XACCL_OFFS); +static IIO_DEV_ATTR_INCLI_Y_OFFSET(S_IWUSR | S_IRUGO, + adis16201_read_9bit_signed, + adis16201_write_16bit, + ADIS16201_YACCL_OFFS); +static IIO_CONST_ATTR(incli_scale, "0.1"); + +static IIO_DEV_ATTR_TEMP_RAW(adis16201_read_temp); +static IIO_CONST_ATTR(temp_offset, "25"); +static IIO_CONST_ATTR(temp_scale, "-0.47"); + +static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16201_write_reset, 0); + +static IIO_CONST_ATTR(name, "adis16201"); + +static struct attribute *adis16201_event_attributes[] = { + NULL +}; + +static struct attribute_group adis16201_event_attribute_group = { + .attrs = adis16201_event_attributes, +}; + +static struct attribute *adis16201_attributes[] = { + &iio_dev_attr_in0_supply_raw.dev_attr.attr, + &iio_const_attr_in0_supply_scale.dev_attr.attr, + &iio_dev_attr_temp_raw.dev_attr.attr, + &iio_const_attr_temp_offset.dev_attr.attr, + &iio_const_attr_temp_scale.dev_attr.attr, + &iio_dev_attr_reset.dev_attr.attr, + &iio_const_attr_name.dev_attr.attr, + &iio_dev_attr_in1_raw.dev_attr.attr, + &iio_const_attr_in1_scale.dev_attr.attr, + &iio_dev_attr_accel_x_raw.dev_attr.attr, + &iio_dev_attr_accel_y_raw.dev_attr.attr, + &iio_dev_attr_accel_x_offset.dev_attr.attr, + &iio_dev_attr_accel_y_offset.dev_attr.attr, + &iio_const_attr_accel_scale.dev_attr.attr, + &iio_dev_attr_incli_x_raw.dev_attr.attr, + &iio_dev_attr_incli_y_raw.dev_attr.attr, + &iio_dev_attr_incli_x_offset.dev_attr.attr, + &iio_dev_attr_incli_y_offset.dev_attr.attr, + &iio_const_attr_incli_scale.dev_attr.attr, + NULL +}; + +static const struct attribute_group adis16201_attribute_group = { + .attrs = adis16201_attributes, +}; + +static int __devinit adis16201_probe(struct spi_device *spi) +{ + int ret, regdone = 0; + struct adis16201_state *st = kzalloc(sizeof *st, GFP_KERNEL); + if (!st) { + ret = -ENOMEM; + goto error_ret; + } + /* this is only used for removal purposes */ + spi_set_drvdata(spi, st); + + /* Allocate the comms buffers */ + st->rx = kzalloc(sizeof(*st->rx)*ADIS16201_MAX_RX, GFP_KERNEL); + if (st->rx == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->tx = kzalloc(sizeof(*st->tx)*ADIS16201_MAX_TX, GFP_KERNEL); + if (st->tx == NULL) { + ret = -ENOMEM; + goto error_free_rx; + } + st->us = spi; + mutex_init(&st->buf_lock); + /* setup the industrialio driver allocated elements */ + st->indio_dev = iio_allocate_device(); + if (st->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_tx; + } + + st->indio_dev->dev.parent = &spi->dev; + st->indio_dev->num_interrupt_lines = 1; + st->indio_dev->event_attrs = &adis16201_event_attribute_group; + st->indio_dev->attrs = &adis16201_attribute_group; + st->indio_dev->dev_data = (void *)(st); + st->indio_dev->driver_module = THIS_MODULE; + st->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = adis16201_configure_ring(st->indio_dev); + if (ret) + goto error_free_dev; + + ret = iio_device_register(st->indio_dev); + if (ret) + goto error_unreg_ring_funcs; + regdone = 1; + + ret = adis16201_initialize_ring(st->indio_dev->ring); + if (ret) { + printk(KERN_ERR "failed to initialize the ring\n"); + goto error_unreg_ring_funcs; + } + + if (spi->irq) { + ret = iio_register_interrupt_line(spi->irq, + st->indio_dev, + 0, + IRQF_TRIGGER_RISING, + "adis16201"); + if (ret) + goto error_uninitialize_ring; + + ret = adis16201_probe_trigger(st->indio_dev); + if (ret) + goto error_unregister_line; + } + + /* Get the device into a sane initial state */ + ret = adis16201_initial_setup(st); + if (ret) + goto error_remove_trigger; + return 0; + +error_remove_trigger: + adis16201_remove_trigger(st->indio_dev); +error_unregister_line: + if (spi->irq) + iio_unregister_interrupt_line(st->indio_dev, 0); +error_uninitialize_ring: + adis16201_uninitialize_ring(st->indio_dev->ring); +error_unreg_ring_funcs: + adis16201_unconfigure_ring(st->indio_dev); +error_free_dev: + if (regdone) + iio_device_unregister(st->indio_dev); + else + iio_free_device(st->indio_dev); +error_free_tx: + kfree(st->tx); +error_free_rx: + kfree(st->rx); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +static int adis16201_remove(struct spi_device *spi) +{ + struct adis16201_state *st = spi_get_drvdata(spi); + struct iio_dev *indio_dev = st->indio_dev; + + flush_scheduled_work(); + + adis16201_remove_trigger(indio_dev); + if (spi->irq) + iio_unregister_interrupt_line(indio_dev, 0); + + adis16201_uninitialize_ring(indio_dev->ring); + iio_device_unregister(indio_dev); + adis16201_unconfigure_ring(indio_dev); + kfree(st->tx); + kfree(st->rx); + kfree(st); + + return 0; +} + +static struct spi_driver adis16201_driver = { + .driver = { + .name = "adis16201", + .owner = THIS_MODULE, + }, + .probe = adis16201_probe, + .remove = __devexit_p(adis16201_remove), +}; + +static __init int adis16201_init(void) +{ + return spi_register_driver(&adis16201_driver); +} +module_init(adis16201_init); + +static __exit void adis16201_exit(void) +{ + spi_unregister_driver(&adis16201_driver); +} +module_exit(adis16201_exit); + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices ADIS16201 Programmable Digital Vibration Sensor driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/accel/adis16201_ring.c b/trunk/drivers/staging/iio/accel/adis16201_ring.c new file mode 100644 index 000000000000..e6870a2721f1 --- /dev/null +++ b/trunk/drivers/staging/iio/accel/adis16201_ring.c @@ -0,0 +1,218 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "../ring_sw.h" +#include "accel.h" +#include "../trigger.h" +#include "adis16201.h" + +static IIO_SCAN_EL_C(in_supply, ADIS16201_SCAN_SUPPLY, ADIS16201_SUPPLY_OUT, NULL); +static IIO_CONST_ATTR_SCAN_EL_TYPE(in_supply, u, 12, 16); +static IIO_SCAN_EL_C(accel_x, ADIS16201_SCAN_ACC_X, ADIS16201_XACCL_OUT, NULL); +static IIO_SCAN_EL_C(accel_y, ADIS16201_SCAN_ACC_Y, ADIS16201_YACCL_OUT, NULL); +static IIO_CONST_ATTR_SCAN_EL_TYPE(accel, s, 14, 16); +static IIO_SCAN_EL_C(in0, ADIS16201_SCAN_AUX_ADC, ADIS16201_AUX_ADC, NULL); +static IIO_CONST_ATTR_SCAN_EL_TYPE(in0, u, 12, 16); +static IIO_SCAN_EL_C(temp, ADIS16201_SCAN_TEMP, ADIS16201_TEMP_OUT, NULL); +static IIO_CONST_ATTR_SCAN_EL_TYPE(temp, u, 12, 16); +static IIO_SCAN_EL_C(incli_x, ADIS16201_SCAN_INCLI_X, + ADIS16201_XINCL_OUT, NULL); +static IIO_SCAN_EL_C(incli_y, ADIS16201_SCAN_INCLI_Y, + ADIS16201_YINCL_OUT, NULL); +static IIO_CONST_ATTR_SCAN_EL_TYPE(incli, s, 14, 16); +static IIO_SCAN_EL_TIMESTAMP(7); +static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64); + +static struct attribute *adis16201_scan_el_attrs[] = { + &iio_scan_el_in_supply.dev_attr.attr, + &iio_const_attr_in_supply_index.dev_attr.attr, + &iio_const_attr_in_supply_type.dev_attr.attr, + &iio_scan_el_accel_x.dev_attr.attr, + &iio_const_attr_accel_x_index.dev_attr.attr, + &iio_scan_el_accel_y.dev_attr.attr, + &iio_const_attr_accel_y_index.dev_attr.attr, + &iio_const_attr_accel_type.dev_attr.attr, + &iio_scan_el_in0.dev_attr.attr, + &iio_const_attr_in0_index.dev_attr.attr, + &iio_const_attr_in0_type.dev_attr.attr, + &iio_scan_el_temp.dev_attr.attr, + &iio_const_attr_temp_index.dev_attr.attr, + &iio_const_attr_temp_type.dev_attr.attr, + &iio_scan_el_incli_x.dev_attr.attr, + &iio_const_attr_incli_x_index.dev_attr.attr, + &iio_scan_el_incli_y.dev_attr.attr, + &iio_const_attr_incli_y_index.dev_attr.attr, + &iio_const_attr_incli_type.dev_attr.attr, + &iio_scan_el_timestamp.dev_attr.attr, + &iio_const_attr_timestamp_index.dev_attr.attr, + &iio_const_attr_timestamp_type.dev_attr.attr, + NULL, +}; + +static struct attribute_group adis16201_scan_el_group = { + .attrs = adis16201_scan_el_attrs, + .name = "scan_elements", +}; + +/** + * adis16201_poll_func_th() top half interrupt handler called by trigger + * @private_data: iio_dev + **/ +static void adis16201_poll_func_th(struct iio_dev *indio_dev, s64 time) +{ + struct adis16201_state *st = iio_dev_get_devdata(indio_dev); + st->last_timestamp = time; + schedule_work(&st->work_trigger_to_ring); +} + +/** + * adis16201_read_ring_data() read data registers which will be placed into ring + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @rx: somewhere to pass back the value read + **/ +static int adis16201_read_ring_data(struct device *dev, u8 *rx) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16201_state *st = iio_dev_get_devdata(indio_dev); + struct spi_transfer xfers[ADIS16201_OUTPUTS + 1]; + int ret; + int i; + + mutex_lock(&st->buf_lock); + + spi_message_init(&msg); + + memset(xfers, 0, sizeof(xfers)); + for (i = 0; i <= ADIS16201_OUTPUTS; i++) { + xfers[i].bits_per_word = 8; + xfers[i].cs_change = 1; + xfers[i].len = 2; + xfers[i].delay_usecs = 20; + xfers[i].tx_buf = st->tx + 2 * i; + st->tx[2 * i] = ADIS16201_READ_REG(ADIS16201_SUPPLY_OUT + 2 * i); + st->tx[2 * i + 1] = 0; + if (i >= 1) + xfers[i].rx_buf = rx + 2 * (i - 1); + spi_message_add_tail(&xfers[i], &msg); + } + + ret = spi_sync(st->us, &msg); + if (ret) + dev_err(&st->us->dev, "problem when burst reading"); + + mutex_unlock(&st->buf_lock); + + return ret; +} + +/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device + * specific to be rolled into the core. + */ +static void adis16201_trigger_bh_to_ring(struct work_struct *work_s) +{ + struct adis16201_state *st + = container_of(work_s, struct adis16201_state, + work_trigger_to_ring); + struct iio_ring_buffer *ring = st->indio_dev->ring; + + int i = 0; + s16 *data; + size_t datasize = ring->access.get_bytes_per_datum(ring); + + data = kmalloc(datasize, GFP_KERNEL); + if (data == NULL) { + dev_err(&st->us->dev, "memory alloc failed in ring bh"); + return; + } + + if (ring->scan_count) + if (adis16201_read_ring_data(&st->indio_dev->dev, st->rx) >= 0) + for (; i < ring->scan_count; i++) + data[i] = be16_to_cpup( + (__be16 *)&(st->rx[i*2])); + + /* Guaranteed to be aligned with 8 byte boundary */ + if (ring->scan_timestamp) + *((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp; + + ring->access.store_to(ring, + (u8 *)data, + st->last_timestamp); + + iio_trigger_notify_done(st->indio_dev->trig); + kfree(data); + + return; +} + +void adis16201_unconfigure_ring(struct iio_dev *indio_dev) +{ + kfree(indio_dev->pollfunc); + iio_sw_rb_free(indio_dev->ring); +} + +int adis16201_configure_ring(struct iio_dev *indio_dev) +{ + int ret = 0; + struct adis16201_state *st = indio_dev->dev_data; + struct iio_ring_buffer *ring; + INIT_WORK(&st->work_trigger_to_ring, adis16201_trigger_bh_to_ring); + + ring = iio_sw_rb_allocate(indio_dev); + if (!ring) { + ret = -ENOMEM; + return ret; + } + indio_dev->ring = ring; + /* Effectively select the ring buffer implementation */ + iio_ring_sw_register_funcs(&ring->access); + ring->bpe = 2; + ring->scan_el_attrs = &adis16201_scan_el_group; + ring->scan_timestamp = true; + ring->preenable = &iio_sw_ring_preenable; + ring->postenable = &iio_triggered_ring_postenable; + ring->predisable = &iio_triggered_ring_predisable; + ring->owner = THIS_MODULE; + + /* Set default scan mode */ + iio_scan_mask_set(ring, iio_scan_el_in_supply.number); + iio_scan_mask_set(ring, iio_scan_el_accel_x.number); + iio_scan_mask_set(ring, iio_scan_el_accel_y.number); + iio_scan_mask_set(ring, iio_scan_el_temp.number); + iio_scan_mask_set(ring, iio_scan_el_in0.number); + iio_scan_mask_set(ring, iio_scan_el_incli_x.number); + iio_scan_mask_set(ring, iio_scan_el_incli_y.number); + + ret = iio_alloc_pollfunc(indio_dev, NULL, &adis16201_poll_func_th); + if (ret) + goto error_iio_sw_rb_free; + + indio_dev->modes |= INDIO_RING_TRIGGERED; + return 0; + +error_iio_sw_rb_free: + iio_sw_rb_free(indio_dev->ring); + return ret; +} + +int adis16201_initialize_ring(struct iio_ring_buffer *ring) +{ + return iio_ring_buffer_register(ring, 0); +} + +void adis16201_uninitialize_ring(struct iio_ring_buffer *ring) +{ + iio_ring_buffer_unregister(ring); +} diff --git a/trunk/drivers/staging/iio/accel/adis16201_trigger.c b/trunk/drivers/staging/iio/accel/adis16201_trigger.c new file mode 100644 index 000000000000..8a9cea1986e7 --- /dev/null +++ b/trunk/drivers/staging/iio/accel/adis16201_trigger.c @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "../trigger.h" +#include "adis16201.h" + +/** + * adis16201_data_rdy_trig_poll() the event handler for the data rdy trig + **/ +static int adis16201_data_rdy_trig_poll(struct iio_dev *dev_info, + int index, + s64 timestamp, + int no_test) +{ + struct adis16201_state *st = iio_dev_get_devdata(dev_info); + struct iio_trigger *trig = st->trig; + + iio_trigger_poll(trig, timestamp); + + return IRQ_HANDLED; +} + +IIO_EVENT_SH(data_rdy_trig, &adis16201_data_rdy_trig_poll); + +static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL); + +static struct attribute *adis16201_trigger_attrs[] = { + &dev_attr_name.attr, + NULL, +}; + +static const struct attribute_group adis16201_trigger_attr_group = { + .attrs = adis16201_trigger_attrs, +}; + +/** + * adis16201_data_rdy_trigger_set_state() set datardy interrupt state + **/ +static int adis16201_data_rdy_trigger_set_state(struct iio_trigger *trig, + bool state) +{ + struct adis16201_state *st = trig->private_data; + struct iio_dev *indio_dev = st->indio_dev; + int ret = 0; + + dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); + ret = adis16201_set_irq(&st->indio_dev->dev, state); + if (state == false) { + iio_remove_event_from_list(&iio_event_data_rdy_trig, + &indio_dev->interrupts[0] + ->ev_list); + flush_scheduled_work(); + } else { + iio_add_event_to_list(&iio_event_data_rdy_trig, + &indio_dev->interrupts[0]->ev_list); + } + return ret; +} + +/** + * adis16201_trig_try_reen() try renabling irq for data rdy trigger + * @trig: the datardy trigger + **/ +static int adis16201_trig_try_reen(struct iio_trigger *trig) +{ + struct adis16201_state *st = trig->private_data; + enable_irq(st->us->irq); + return 0; +} + +int adis16201_probe_trigger(struct iio_dev *indio_dev) +{ + int ret; + struct adis16201_state *st = indio_dev->dev_data; + + st->trig = iio_allocate_trigger(); + st->trig->name = kasprintf(GFP_KERNEL, + "adis16201-dev%d", + indio_dev->id); + if (!st->trig->name) { + ret = -ENOMEM; + goto error_free_trig; + } + st->trig->dev.parent = &st->us->dev; + st->trig->owner = THIS_MODULE; + st->trig->private_data = st; + st->trig->set_trigger_state = &adis16201_data_rdy_trigger_set_state; + st->trig->try_reenable = &adis16201_trig_try_reen; + st->trig->control_attrs = &adis16201_trigger_attr_group; + ret = iio_trigger_register(st->trig); + + /* select default trigger */ + indio_dev->trig = st->trig; + if (ret) + goto error_free_trig_name; + + return 0; + +error_free_trig_name: + kfree(st->trig->name); +error_free_trig: + iio_free_trigger(st->trig); + + return ret; +} + +void adis16201_remove_trigger(struct iio_dev *indio_dev) +{ + struct adis16201_state *state = indio_dev->dev_data; + + iio_trigger_unregister(state->trig); + kfree(state->trig->name); + iio_free_trigger(state->trig); +} diff --git a/trunk/drivers/staging/iio/accel/adis16203.h b/trunk/drivers/staging/iio/accel/adis16203.h new file mode 100644 index 000000000000..b39323eac9e3 --- /dev/null +++ b/trunk/drivers/staging/iio/accel/adis16203.h @@ -0,0 +1,143 @@ +#ifndef SPI_ADIS16203_H_ +#define SPI_ADIS16203_H_ + +#define ADIS16203_STARTUP_DELAY 220 /* ms */ + +#define ADIS16203_READ_REG(a) a +#define ADIS16203_WRITE_REG(a) ((a) | 0x80) + +#define ADIS16203_FLASH_CNT 0x00 /* Flash memory write count */ +#define ADIS16203_SUPPLY_OUT 0x02 /* Output, power supply */ +#define ADIS16203_AUX_ADC 0x08 /* Output, auxiliary ADC input */ +#define ADIS16203_TEMP_OUT 0x0A /* Output, temperature */ +#define ADIS16203_XINCL_OUT 0x0C /* Output, x-axis inclination */ +#define ADIS16203_YINCL_OUT 0x0E /* Output, y-axis inclination */ +#define ADIS16203_INCL_NULL 0x18 /* Incline null calibration */ +#define ADIS16203_ALM_MAG1 0x20 /* Alarm 1 amplitude threshold */ +#define ADIS16203_ALM_MAG2 0x22 /* Alarm 2 amplitude threshold */ +#define ADIS16203_ALM_SMPL1 0x24 /* Alarm 1, sample period */ +#define ADIS16203_ALM_SMPL2 0x26 /* Alarm 2, sample period */ +#define ADIS16203_ALM_CTRL 0x28 /* Alarm control */ +#define ADIS16203_AUX_DAC 0x30 /* Auxiliary DAC data */ +#define ADIS16203_GPIO_CTRL 0x32 /* General-purpose digital input/output control */ +#define ADIS16203_MSC_CTRL 0x34 /* Miscellaneous control */ +#define ADIS16203_SMPL_PRD 0x36 /* Internal sample period (rate) control */ +#define ADIS16203_AVG_CNT 0x38 /* Operation, filter configuration */ +#define ADIS16203_SLP_CNT 0x3A /* Operation, sleep mode control */ +#define ADIS16203_DIAG_STAT 0x3C /* Diagnostics, system status register */ +#define ADIS16203_GLOB_CMD 0x3E /* Operation, system command register */ + +#define ADIS16203_OUTPUTS 5 + +/* MSC_CTRL */ +#define ADIS16203_MSC_CTRL_PWRUP_SELF_TEST (1 << 10) /* Self-test at power-on: 1 = disabled, 0 = enabled */ +#define ADIS16203_MSC_CTRL_REVERSE_ROT_EN (1 << 9) /* Reverses rotation of both inclination outputs */ +#define ADIS16203_MSC_CTRL_SELF_TEST_EN (1 << 8) /* Self-test enable */ +#define ADIS16203_MSC_CTRL_DATA_RDY_EN (1 << 2) /* Data-ready enable: 1 = enabled, 0 = disabled */ +#define ADIS16203_MSC_CTRL_ACTIVE_HIGH (1 << 1) /* Data-ready polarity: 1 = active high, 0 = active low */ +#define ADIS16203_MSC_CTRL_DATA_RDY_DIO1 (1 << 0) /* Data-ready line selection: 1 = DIO1, 0 = DIO0 */ + +/* DIAG_STAT */ +#define ADIS16203_DIAG_STAT_ALARM2 (1<<9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ +#define ADIS16203_DIAG_STAT_ALARM1 (1<<8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ +#define ADIS16203_DIAG_STAT_SELFTEST_FAIL (1<<5) /* Self-test diagnostic error flag */ +#define ADIS16203_DIAG_STAT_SPI_FAIL (1<<3) /* SPI communications failure */ +#define ADIS16203_DIAG_STAT_FLASH_UPT (1<<2) /* Flash update failure */ +#define ADIS16203_DIAG_STAT_POWER_HIGH (1<<1) /* Power supply above 3.625 V */ +#define ADIS16203_DIAG_STAT_POWER_LOW (1<<0) /* Power supply below 3.15 V */ + +/* GLOB_CMD */ +#define ADIS16203_GLOB_CMD_SW_RESET (1<<7) +#define ADIS16203_GLOB_CMD_CLEAR_STAT (1<<4) +#define ADIS16203_GLOB_CMD_FACTORY_CAL (1<<1) + +#define ADIS16203_MAX_TX 12 +#define ADIS16203_MAX_RX 10 + +#define ADIS16203_ERROR_ACTIVE (1<<14) + +/** + * struct adis16203_state - device instance specific data + * @us: actual spi_device + * @work_trigger_to_ring: bh for triggered event handling + * @inter: used to check if new interrupt has been triggered + * @last_timestamp: passing timestamp from th to bh of interrupt handler + * @indio_dev: industrial I/O device structure + * @trig: data ready trigger registered with iio + * @tx: transmit buffer + * @rx: recieve buffer + * @buf_lock: mutex to protect tx and rx + **/ +struct adis16203_state { + struct spi_device *us; + struct work_struct work_trigger_to_ring; + s64 last_timestamp; + struct iio_dev *indio_dev; + struct iio_trigger *trig; + u8 *tx; + u8 *rx; + struct mutex buf_lock; +}; + +int adis16203_set_irq(struct device *dev, bool enable); + +#ifdef CONFIG_IIO_RING_BUFFER +enum adis16203_scan { + ADIS16203_SCAN_SUPPLY, + ADIS16203_SCAN_AUX_ADC, + ADIS16203_SCAN_TEMP, + ADIS16203_SCAN_INCLI_X, + ADIS16203_SCAN_INCLI_Y, +}; + +void adis16203_remove_trigger(struct iio_dev *indio_dev); +int adis16203_probe_trigger(struct iio_dev *indio_dev); + +ssize_t adis16203_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf); + +int adis16203_configure_ring(struct iio_dev *indio_dev); +void adis16203_unconfigure_ring(struct iio_dev *indio_dev); + +int adis16203_initialize_ring(struct iio_ring_buffer *ring); +void adis16203_uninitialize_ring(struct iio_ring_buffer *ring); +#else /* CONFIG_IIO_RING_BUFFER */ + +static inline void adis16203_remove_trigger(struct iio_dev *indio_dev) +{ +} + +static inline int adis16203_probe_trigger(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline ssize_t +adis16203_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return 0; +} + +static int adis16203_configure_ring(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline void adis16203_unconfigure_ring(struct iio_dev *indio_dev) +{ +} + +static inline int adis16203_initialize_ring(struct iio_ring_buffer *ring) +{ + return 0; +} + +static inline void adis16203_uninitialize_ring(struct iio_ring_buffer *ring) +{ +} + +#endif /* CONFIG_IIO_RING_BUFFER */ +#endif /* SPI_ADIS16203_H_ */ diff --git a/trunk/drivers/staging/iio/accel/adis16203_core.c b/trunk/drivers/staging/iio/accel/adis16203_core.c new file mode 100644 index 000000000000..b57f19087a93 --- /dev/null +++ b/trunk/drivers/staging/iio/accel/adis16203_core.c @@ -0,0 +1,568 @@ +/* + * ADIS16203 Programmable Digital Vibration Sensor driver + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "accel.h" +#include "inclinometer.h" +#include "../gyro/gyro.h" +#include "../adc/adc.h" + +#include "adis16203.h" + +#define DRIVER_NAME "adis16203" + +static int adis16203_check_status(struct device *dev); + +/** + * adis16203_spi_write_reg_8() - write single byte to a register + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @reg_address: the address of the register to be written + * @val: the value to write + **/ +static int adis16203_spi_write_reg_8(struct device *dev, + u8 reg_address, + u8 val) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16203_state *st = iio_dev_get_devdata(indio_dev); + + mutex_lock(&st->buf_lock); + st->tx[0] = ADIS16203_WRITE_REG(reg_address); + st->tx[1] = val; + + ret = spi_write(st->us, st->tx, 2); + mutex_unlock(&st->buf_lock); + + return ret; +} + +/** + * adis16203_spi_write_reg_16() - write 2 bytes to a pair of registers + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @reg_address: the address of the lower of the two registers. Second register + * is assumed to have address one greater. + * @val: value to be written + **/ +static int adis16203_spi_write_reg_16(struct device *dev, + u8 lower_reg_address, + u16 value) +{ + int ret; + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16203_state *st = iio_dev_get_devdata(indio_dev); + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + }, { + .tx_buf = st->tx + 2, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADIS16203_WRITE_REG(lower_reg_address); + st->tx[1] = value & 0xFF; + st->tx[2] = ADIS16203_WRITE_REG(lower_reg_address + 1); + st->tx[3] = (value >> 8) & 0xFF; + + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(st->us, &msg); + mutex_unlock(&st->buf_lock); + + return ret; +} + +/** + * adis16203_spi_read_reg_16() - read 2 bytes from a 16-bit register + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @reg_address: the address of the lower of the two registers. Second register + * is assumed to have address one greater. + * @val: somewhere to pass back the value read + **/ +static int adis16203_spi_read_reg_16(struct device *dev, + u8 lower_reg_address, + u16 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16203_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + .delay_usecs = 20, + }, { + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + .delay_usecs = 20, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADIS16203_READ_REG(lower_reg_address); + st->tx[1] = 0; + + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", + lower_reg_address); + goto error_ret; + } + *val = (st->rx[0] << 8) | st->rx[1]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static ssize_t adis16203_read_12bit_unsigned(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u16 val = 0; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = adis16203_spi_read_reg_16(dev, this_attr->address, &val); + if (ret) + return ret; + + if (val & ADIS16203_ERROR_ACTIVE) + adis16203_check_status(dev); + + return sprintf(buf, "%u\n", val & 0x0FFF); +} + +static ssize_t adis16203_read_temp(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + ssize_t ret; + u16 val; + + /* Take the iio_dev status lock */ + mutex_lock(&indio_dev->mlock); + + ret = adis16203_spi_read_reg_16(dev, ADIS16203_TEMP_OUT, (u16 *)&val); + if (ret) + goto error_ret; + + if (val & ADIS16203_ERROR_ACTIVE) + adis16203_check_status(dev); + + val &= 0xFFF; + ret = sprintf(buf, "%d\n", val); + +error_ret: + mutex_unlock(&indio_dev->mlock); + return ret; +} + +static ssize_t adis16203_read_14bit_signed(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + s16 val = 0; + ssize_t ret; + + mutex_lock(&indio_dev->mlock); + + ret = adis16203_spi_read_reg_16(dev, this_attr->address, (u16 *)&val); + if (!ret) { + if (val & ADIS16203_ERROR_ACTIVE) + adis16203_check_status(dev); + + val = ((s16)(val << 2) >> 2); + ret = sprintf(buf, "%d\n", val); + } + + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static ssize_t adis16203_write_16bit(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + long val; + + ret = strict_strtol(buf, 10, &val); + if (ret) + goto error_ret; + ret = adis16203_spi_write_reg_16(dev, this_attr->address, val); + +error_ret: + return ret ? ret : len; +} + +static int adis16203_reset(struct device *dev) +{ + int ret; + ret = adis16203_spi_write_reg_8(dev, + ADIS16203_GLOB_CMD, + ADIS16203_GLOB_CMD_SW_RESET); + if (ret) + dev_err(dev, "problem resetting device"); + + return ret; +} + +static ssize_t adis16203_write_reset(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + if (len < 1) + return -EINVAL; + switch (buf[0]) { + case '1': + case 'y': + case 'Y': + return adis16203_reset(dev); + } + return -EINVAL; +} + +int adis16203_set_irq(struct device *dev, bool enable) +{ + int ret = 0; + u16 msc; + + ret = adis16203_spi_read_reg_16(dev, ADIS16203_MSC_CTRL, &msc); + if (ret) + goto error_ret; + + msc |= ADIS16203_MSC_CTRL_ACTIVE_HIGH; + msc &= ~ADIS16203_MSC_CTRL_DATA_RDY_DIO1; + if (enable) + msc |= ADIS16203_MSC_CTRL_DATA_RDY_EN; + else + msc &= ~ADIS16203_MSC_CTRL_DATA_RDY_EN; + + ret = adis16203_spi_write_reg_16(dev, ADIS16203_MSC_CTRL, msc); + +error_ret: + return ret; +} + +static int adis16203_check_status(struct device *dev) +{ + u16 status; + int ret; + + ret = adis16203_spi_read_reg_16(dev, ADIS16203_DIAG_STAT, &status); + if (ret < 0) { + dev_err(dev, "Reading status failed\n"); + goto error_ret; + } + ret = status & 0x1F; + + if (status & ADIS16203_DIAG_STAT_SELFTEST_FAIL) + dev_err(dev, "Self test failure\n"); + if (status & ADIS16203_DIAG_STAT_SPI_FAIL) + dev_err(dev, "SPI failure\n"); + if (status & ADIS16203_DIAG_STAT_FLASH_UPT) + dev_err(dev, "Flash update failed\n"); + if (status & ADIS16203_DIAG_STAT_POWER_HIGH) + dev_err(dev, "Power supply above 3.625V\n"); + if (status & ADIS16203_DIAG_STAT_POWER_LOW) + dev_err(dev, "Power supply below 3.15V\n"); + +error_ret: + return ret; +} + +static int adis16203_self_test(struct device *dev) +{ + int ret; + ret = adis16203_spi_write_reg_16(dev, + ADIS16203_MSC_CTRL, + ADIS16203_MSC_CTRL_SELF_TEST_EN); + if (ret) { + dev_err(dev, "problem starting self test"); + goto err_ret; + } + + adis16203_check_status(dev); + +err_ret: + return ret; +} + +static int adis16203_initial_setup(struct adis16203_state *st) +{ + int ret; + struct device *dev = &st->indio_dev->dev; + + /* Disable IRQ */ + ret = adis16203_set_irq(dev, false); + if (ret) { + dev_err(dev, "disable irq failed"); + goto err_ret; + } + + /* Do self test */ + ret = adis16203_self_test(dev); + if (ret) { + dev_err(dev, "self test failure"); + goto err_ret; + } + + /* Read status register to check the result */ + ret = adis16203_check_status(dev); + if (ret) { + adis16203_reset(dev); + dev_err(dev, "device not playing ball -> reset"); + msleep(ADIS16203_STARTUP_DELAY); + ret = adis16203_check_status(dev); + if (ret) { + dev_err(dev, "giving up"); + goto err_ret; + } + } + + printk(KERN_INFO DRIVER_NAME ": at CS%d (irq %d)\n", + st->us->chip_select, st->us->irq); + +err_ret: + return ret; +} + +static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16203_read_12bit_unsigned, + ADIS16203_SUPPLY_OUT); +static IIO_CONST_ATTR(in0_supply_scale, "0.00122"); +static IIO_DEV_ATTR_IN_RAW(1, adis16203_read_12bit_unsigned, + ADIS16203_AUX_ADC); +static IIO_CONST_ATTR(in1_scale, "0.00061"); + +static IIO_DEV_ATTR_INCLI_X(adis16203_read_14bit_signed, + ADIS16203_XINCL_OUT); +static IIO_DEV_ATTR_INCLI_Y(adis16203_read_14bit_signed, + ADIS16203_YINCL_OUT); +static IIO_DEV_ATTR_INCLI_X_OFFSET(S_IWUSR | S_IRUGO, + adis16203_read_14bit_signed, + adis16203_write_16bit, + ADIS16203_INCL_NULL); +static IIO_CONST_ATTR(incli_scale, "0.025"); + +static IIO_DEV_ATTR_TEMP_RAW(adis16203_read_temp); +static IIO_CONST_ATTR(temp_offset, "25"); +static IIO_CONST_ATTR(temp_scale, "-0.47"); + +static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16203_write_reset, 0); + +static IIO_CONST_ATTR(name, "adis16203"); + +static struct attribute *adis16203_event_attributes[] = { + NULL +}; + +static struct attribute_group adis16203_event_attribute_group = { + .attrs = adis16203_event_attributes, +}; + +static struct attribute *adis16203_attributes[] = { + &iio_dev_attr_in0_supply_raw.dev_attr.attr, + &iio_const_attr_in0_supply_scale.dev_attr.attr, + &iio_dev_attr_temp_raw.dev_attr.attr, + &iio_const_attr_temp_offset.dev_attr.attr, + &iio_const_attr_temp_scale.dev_attr.attr, + &iio_dev_attr_reset.dev_attr.attr, + &iio_const_attr_name.dev_attr.attr, + &iio_dev_attr_in1_raw.dev_attr.attr, + &iio_const_attr_in1_scale.dev_attr.attr, + &iio_dev_attr_incli_x_raw.dev_attr.attr, + &iio_dev_attr_incli_y_raw.dev_attr.attr, + &iio_dev_attr_incli_x_offset.dev_attr.attr, + &iio_const_attr_incli_scale.dev_attr.attr, + NULL +}; + +static const struct attribute_group adis16203_attribute_group = { + .attrs = adis16203_attributes, +}; + +static int __devinit adis16203_probe(struct spi_device *spi) +{ + int ret, regdone = 0; + struct adis16203_state *st = kzalloc(sizeof *st, GFP_KERNEL); + if (!st) { + ret = -ENOMEM; + goto error_ret; + } + /* this is only used for removal purposes */ + spi_set_drvdata(spi, st); + + /* Allocate the comms buffers */ + st->rx = kzalloc(sizeof(*st->rx)*ADIS16203_MAX_RX, GFP_KERNEL); + if (st->rx == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->tx = kzalloc(sizeof(*st->tx)*ADIS16203_MAX_TX, GFP_KERNEL); + if (st->tx == NULL) { + ret = -ENOMEM; + goto error_free_rx; + } + st->us = spi; + mutex_init(&st->buf_lock); + /* setup the industrialio driver allocated elements */ + st->indio_dev = iio_allocate_device(); + if (st->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_tx; + } + + st->indio_dev->dev.parent = &spi->dev; + st->indio_dev->num_interrupt_lines = 1; + st->indio_dev->event_attrs = &adis16203_event_attribute_group; + st->indio_dev->attrs = &adis16203_attribute_group; + st->indio_dev->dev_data = (void *)(st); + st->indio_dev->driver_module = THIS_MODULE; + st->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = adis16203_configure_ring(st->indio_dev); + if (ret) + goto error_free_dev; + + ret = iio_device_register(st->indio_dev); + if (ret) + goto error_unreg_ring_funcs; + regdone = 1; + + ret = adis16203_initialize_ring(st->indio_dev->ring); + if (ret) { + printk(KERN_ERR "failed to initialize the ring\n"); + goto error_unreg_ring_funcs; + } + + if (spi->irq) { + ret = iio_register_interrupt_line(spi->irq, + st->indio_dev, + 0, + IRQF_TRIGGER_RISING, + "adis16203"); + if (ret) + goto error_uninitialize_ring; + + ret = adis16203_probe_trigger(st->indio_dev); + if (ret) + goto error_unregister_line; + } + + /* Get the device into a sane initial state */ + ret = adis16203_initial_setup(st); + if (ret) + goto error_remove_trigger; + return 0; + +error_remove_trigger: + adis16203_remove_trigger(st->indio_dev); +error_unregister_line: + if (spi->irq) + iio_unregister_interrupt_line(st->indio_dev, 0); +error_uninitialize_ring: + adis16203_uninitialize_ring(st->indio_dev->ring); +error_unreg_ring_funcs: + adis16203_unconfigure_ring(st->indio_dev); +error_free_dev: + if (regdone) + iio_device_unregister(st->indio_dev); + else + iio_free_device(st->indio_dev); +error_free_tx: + kfree(st->tx); +error_free_rx: + kfree(st->rx); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +static int adis16203_remove(struct spi_device *spi) +{ + struct adis16203_state *st = spi_get_drvdata(spi); + struct iio_dev *indio_dev = st->indio_dev; + + flush_scheduled_work(); + + adis16203_remove_trigger(indio_dev); + if (spi->irq) + iio_unregister_interrupt_line(indio_dev, 0); + + adis16203_uninitialize_ring(indio_dev->ring); + iio_device_unregister(indio_dev); + adis16203_unconfigure_ring(indio_dev); + kfree(st->tx); + kfree(st->rx); + kfree(st); + + return 0; +} + +static struct spi_driver adis16203_driver = { + .driver = { + .name = "adis16203", + .owner = THIS_MODULE, + }, + .probe = adis16203_probe, + .remove = __devexit_p(adis16203_remove), +}; + +static __init int adis16203_init(void) +{ + return spi_register_driver(&adis16203_driver); +} +module_init(adis16203_init); + +static __exit void adis16203_exit(void) +{ + spi_unregister_driver(&adis16203_driver); +} +module_exit(adis16203_exit); + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices ADIS16203 Programmable Digital Vibration Sensor driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/accel/adis16203_ring.c b/trunk/drivers/staging/iio/accel/adis16203_ring.c new file mode 100644 index 000000000000..3d774f7efa25 --- /dev/null +++ b/trunk/drivers/staging/iio/accel/adis16203_ring.c @@ -0,0 +1,211 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "../ring_sw.h" +#include "accel.h" +#include "../trigger.h" +#include "adis16203.h" + +static IIO_SCAN_EL_C(in_supply, ADIS16203_SCAN_SUPPLY, ADIS16203_SUPPLY_OUT, NULL); +static IIO_CONST_ATTR_SCAN_EL_TYPE(in_supply, u, 12, 16); +static IIO_SCAN_EL_C(in0, ADIS16203_SCAN_AUX_ADC, ADIS16203_AUX_ADC, NULL); +static IIO_CONST_ATTR_SCAN_EL_TYPE(in0, u, 12, 16); +static IIO_SCAN_EL_C(temp, ADIS16203_SCAN_TEMP, ADIS16203_TEMP_OUT, NULL); +static IIO_CONST_ATTR_SCAN_EL_TYPE(temp, u, 12, 16); +static IIO_SCAN_EL_C(incli_x, ADIS16203_SCAN_INCLI_X, + ADIS16203_XINCL_OUT, NULL); +static IIO_SCAN_EL_C(incli_y, ADIS16203_SCAN_INCLI_Y, + ADIS16203_YINCL_OUT, NULL); +static IIO_CONST_ATTR_SCAN_EL_TYPE(incli, s, 14, 16); +static IIO_SCAN_EL_TIMESTAMP(5); +static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64); + +static struct attribute *adis16203_scan_el_attrs[] = { + &iio_scan_el_in_supply.dev_attr.attr, + &iio_const_attr_in_supply_index.dev_attr.attr, + &iio_const_attr_in_supply_type.dev_attr.attr, + &iio_scan_el_in0.dev_attr.attr, + &iio_const_attr_in0_index.dev_attr.attr, + &iio_const_attr_in0_type.dev_attr.attr, + &iio_scan_el_temp.dev_attr.attr, + &iio_const_attr_temp_index.dev_attr.attr, + &iio_const_attr_temp_type.dev_attr.attr, + &iio_scan_el_incli_x.dev_attr.attr, + &iio_const_attr_incli_x_index.dev_attr.attr, + &iio_scan_el_incli_y.dev_attr.attr, + &iio_const_attr_incli_y_index.dev_attr.attr, + &iio_const_attr_incli_type.dev_attr.attr, + &iio_scan_el_timestamp.dev_attr.attr, + &iio_const_attr_timestamp_index.dev_attr.attr, + &iio_const_attr_timestamp_type.dev_attr.attr, + NULL, +}; + +static struct attribute_group adis16203_scan_el_group = { + .attrs = adis16203_scan_el_attrs, + .name = "scan_elements", +}; + +/** + * adis16203_poll_func_th() top half interrupt handler called by trigger + * @private_data: iio_dev + **/ +static void adis16203_poll_func_th(struct iio_dev *indio_dev, s64 timestamp) +{ + struct adis16203_state *st = iio_dev_get_devdata(indio_dev); + st->last_timestamp = timestamp; + schedule_work(&st->work_trigger_to_ring); +} + +/** + * adis16203_read_ring_data() read data registers which will be placed into ring + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @rx: somewhere to pass back the value read + **/ +static int adis16203_read_ring_data(struct device *dev, u8 *rx) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16203_state *st = iio_dev_get_devdata(indio_dev); + struct spi_transfer xfers[ADIS16203_OUTPUTS + 1]; + int ret; + int i; + + mutex_lock(&st->buf_lock); + + spi_message_init(&msg); + + memset(xfers, 0, sizeof(xfers)); + for (i = 0; i <= ADIS16203_OUTPUTS; i++) { + xfers[i].bits_per_word = 8; + xfers[i].cs_change = 1; + xfers[i].len = 2; + xfers[i].delay_usecs = 20; + xfers[i].tx_buf = st->tx + 2 * i; + if (i < 1) /* SUPPLY_OUT: 0x02, AUX_ADC: 0x08 */ + st->tx[2 * i] = ADIS16203_READ_REG(ADIS16203_SUPPLY_OUT + 2 * i); + else + st->tx[2 * i] = ADIS16203_READ_REG(ADIS16203_SUPPLY_OUT + 2 * i + 6); + st->tx[2 * i + 1] = 0; + if (i >= 1) + xfers[i].rx_buf = rx + 2 * (i - 1); + spi_message_add_tail(&xfers[i], &msg); + } + + ret = spi_sync(st->us, &msg); + if (ret) + dev_err(&st->us->dev, "problem when burst reading"); + + mutex_unlock(&st->buf_lock); + + return ret; +} + +/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device + * specific to be rolled into the core. + */ +static void adis16203_trigger_bh_to_ring(struct work_struct *work_s) +{ + struct adis16203_state *st + = container_of(work_s, struct adis16203_state, + work_trigger_to_ring); + struct iio_ring_buffer *ring = st->indio_dev->ring; + + int i = 0; + s16 *data; + size_t datasize = ring->access.get_bytes_per_datum(ring); + + data = kmalloc(datasize, GFP_KERNEL); + if (data == NULL) { + dev_err(&st->us->dev, "memory alloc failed in ring bh"); + return; + } + + if (ring->scan_count) + if (adis16203_read_ring_data(&st->indio_dev->dev, st->rx) >= 0) + for (; i < ring->scan_count; i++) + data[i] = be16_to_cpup( + (__be16 *)&(st->rx[i*2])); + + /* Guaranteed to be aligned with 8 byte boundary */ + if (ring->scan_timestamp) + *((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp; + + ring->access.store_to(ring, + (u8 *)data, + st->last_timestamp); + + iio_trigger_notify_done(st->indio_dev->trig); + kfree(data); + + return; +} + +void adis16203_unconfigure_ring(struct iio_dev *indio_dev) +{ + kfree(indio_dev->pollfunc); + iio_sw_rb_free(indio_dev->ring); +} + +int adis16203_configure_ring(struct iio_dev *indio_dev) +{ + int ret = 0; + struct adis16203_state *st = indio_dev->dev_data; + struct iio_ring_buffer *ring; + INIT_WORK(&st->work_trigger_to_ring, adis16203_trigger_bh_to_ring); + + ring = iio_sw_rb_allocate(indio_dev); + if (!ring) { + ret = -ENOMEM; + return ret; + } + indio_dev->ring = ring; + /* Effectively select the ring buffer implementation */ + iio_ring_sw_register_funcs(&ring->access); + ring->bpe = 2; + ring->scan_el_attrs = &adis16203_scan_el_group; + ring->scan_timestamp = true; + ring->preenable = &iio_sw_ring_preenable; + ring->postenable = &iio_triggered_ring_postenable; + ring->predisable = &iio_triggered_ring_predisable; + ring->owner = THIS_MODULE; + + /* Set default scan mode */ + iio_scan_mask_set(ring, iio_scan_el_in_supply.number); + iio_scan_mask_set(ring, iio_scan_el_temp.number); + iio_scan_mask_set(ring, iio_scan_el_in0.number); + iio_scan_mask_set(ring, iio_scan_el_incli_x.number); + iio_scan_mask_set(ring, iio_scan_el_incli_y.number); + + ret = iio_alloc_pollfunc(indio_dev, NULL, &adis16203_poll_func_th); + if (ret) + goto error_iio_sw_rb_free; + + indio_dev->modes |= INDIO_RING_TRIGGERED; + return 0; + +error_iio_sw_rb_free: + iio_sw_rb_free(indio_dev->ring); + return ret; +} + +int adis16203_initialize_ring(struct iio_ring_buffer *ring) +{ + return iio_ring_buffer_register(ring, 0); +} + +void adis16203_uninitialize_ring(struct iio_ring_buffer *ring) +{ + iio_ring_buffer_unregister(ring); +} diff --git a/trunk/drivers/staging/iio/accel/adis16203_trigger.c b/trunk/drivers/staging/iio/accel/adis16203_trigger.c new file mode 100644 index 000000000000..50be51c25dc2 --- /dev/null +++ b/trunk/drivers/staging/iio/accel/adis16203_trigger.c @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "../trigger.h" +#include "adis16203.h" + +/** + * adis16203_data_rdy_trig_poll() the event handler for the data rdy trig + **/ +static int adis16203_data_rdy_trig_poll(struct iio_dev *dev_info, + int index, + s64 timestamp, + int no_test) +{ + struct adis16203_state *st = iio_dev_get_devdata(dev_info); + struct iio_trigger *trig = st->trig; + + iio_trigger_poll(trig, timestamp); + + return IRQ_HANDLED; +} + +IIO_EVENT_SH(data_rdy_trig, &adis16203_data_rdy_trig_poll); + +static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL); + +static struct attribute *adis16203_trigger_attrs[] = { + &dev_attr_name.attr, + NULL, +}; + +static const struct attribute_group adis16203_trigger_attr_group = { + .attrs = adis16203_trigger_attrs, +}; + +/** + * adis16203_data_rdy_trigger_set_state() set datardy interrupt state + **/ +static int adis16203_data_rdy_trigger_set_state(struct iio_trigger *trig, + bool state) +{ + struct adis16203_state *st = trig->private_data; + struct iio_dev *indio_dev = st->indio_dev; + int ret = 0; + + dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); + ret = adis16203_set_irq(&st->indio_dev->dev, state); + if (state == false) { + iio_remove_event_from_list(&iio_event_data_rdy_trig, + &indio_dev->interrupts[0] + ->ev_list); + flush_scheduled_work(); + } else { + iio_add_event_to_list(&iio_event_data_rdy_trig, + &indio_dev->interrupts[0]->ev_list); + } + return ret; +} + +/** + * adis16203_trig_try_reen() try renabling irq for data rdy trigger + * @trig: the datardy trigger + **/ +static int adis16203_trig_try_reen(struct iio_trigger *trig) +{ + struct adis16203_state *st = trig->private_data; + enable_irq(st->us->irq); + return 0; +} + +int adis16203_probe_trigger(struct iio_dev *indio_dev) +{ + int ret; + struct adis16203_state *st = indio_dev->dev_data; + + st->trig = iio_allocate_trigger(); + st->trig->name = kasprintf(GFP_KERNEL, + "adis16203-dev%d", + indio_dev->id); + if (!st->trig->name) { + ret = -ENOMEM; + goto error_free_trig; + } + st->trig->dev.parent = &st->us->dev; + st->trig->owner = THIS_MODULE; + st->trig->private_data = st; + st->trig->set_trigger_state = &adis16203_data_rdy_trigger_set_state; + st->trig->try_reenable = &adis16203_trig_try_reen; + st->trig->control_attrs = &adis16203_trigger_attr_group; + ret = iio_trigger_register(st->trig); + + /* select default trigger */ + indio_dev->trig = st->trig; + if (ret) + goto error_free_trig_name; + + return 0; + +error_free_trig_name: + kfree(st->trig->name); +error_free_trig: + iio_free_trigger(st->trig); + + return ret; +} + +void adis16203_remove_trigger(struct iio_dev *indio_dev) +{ + struct adis16203_state *state = indio_dev->dev_data; + + iio_trigger_unregister(state->trig); + kfree(state->trig->name); + iio_free_trigger(state->trig); +} diff --git a/trunk/drivers/staging/iio/accel/adis16204.h b/trunk/drivers/staging/iio/accel/adis16204.h new file mode 100644 index 000000000000..e9ed7cb048cf --- /dev/null +++ b/trunk/drivers/staging/iio/accel/adis16204.h @@ -0,0 +1,151 @@ +#ifndef SPI_ADIS16204_H_ +#define SPI_ADIS16204_H_ + +#define ADIS16204_STARTUP_DELAY 220 /* ms */ + +#define ADIS16204_READ_REG(a) a +#define ADIS16204_WRITE_REG(a) ((a) | 0x80) + +#define ADIS16204_FLASH_CNT 0x00 /* Flash memory write count */ +#define ADIS16204_SUPPLY_OUT 0x02 /* Output, power supply */ +#define ADIS16204_XACCL_OUT 0x04 /* Output, x-axis accelerometer */ +#define ADIS16204_YACCL_OUT 0x06 /* Output, y-axis accelerometer */ +#define ADIS16204_AUX_ADC 0x08 /* Output, auxiliary ADC input */ +#define ADIS16204_TEMP_OUT 0x0A /* Output, temperature */ +#define ADIS16204_X_PEAK_OUT 0x0C /* Twos complement */ +#define ADIS16204_Y_PEAK_OUT 0x0E /* Twos complement */ +#define ADIS16204_XACCL_NULL 0x10 /* Calibration, x-axis acceleration offset null */ +#define ADIS16204_YACCL_NULL 0x12 /* Calibration, y-axis acceleration offset null */ +#define ADIS16204_XACCL_SCALE 0x14 /* X-axis scale factor calibration register */ +#define ADIS16204_YACCL_SCALE 0x16 /* Y-axis scale factor calibration register */ +#define ADIS16204_XY_RSS_OUT 0x18 /* XY combined acceleration (RSS) */ +#define ADIS16204_XY_PEAK_OUT 0x1A /* Peak, XY combined output (RSS) */ +#define ADIS16204_CAP_BUF_1 0x1C /* Capture buffer output register 1 */ +#define ADIS16204_CAP_BUF_2 0x1E /* Capture buffer output register 2 */ +#define ADIS16204_ALM_MAG1 0x20 /* Alarm 1 amplitude threshold */ +#define ADIS16204_ALM_MAG2 0x22 /* Alarm 2 amplitude threshold */ +#define ADIS16204_ALM_CTRL 0x28 /* Alarm control */ +#define ADIS16204_CAPT_PNTR 0x2A /* Capture register address pointer */ +#define ADIS16204_AUX_DAC 0x30 /* Auxiliary DAC data */ +#define ADIS16204_GPIO_CTRL 0x32 /* General-purpose digital input/output control */ +#define ADIS16204_MSC_CTRL 0x34 /* Miscellaneous control */ +#define ADIS16204_SMPL_PRD 0x36 /* Internal sample period (rate) control */ +#define ADIS16204_AVG_CNT 0x38 /* Operation, filter configuration */ +#define ADIS16204_SLP_CNT 0x3A /* Operation, sleep mode control */ +#define ADIS16204_DIAG_STAT 0x3C /* Diagnostics, system status register */ +#define ADIS16204_GLOB_CMD 0x3E /* Operation, system command register */ + +#define ADIS16204_OUTPUTS 5 + +/* MSC_CTRL */ +#define ADIS16204_MSC_CTRL_PWRUP_SELF_TEST (1 << 10) /* Self-test at power-on: 1 = disabled, 0 = enabled */ +#define ADIS16204_MSC_CTRL_SELF_TEST_EN (1 << 8) /* Self-test enable */ +#define ADIS16204_MSC_CTRL_DATA_RDY_EN (1 << 2) /* Data-ready enable: 1 = enabled, 0 = disabled */ +#define ADIS16204_MSC_CTRL_ACTIVE_HIGH (1 << 1) /* Data-ready polarity: 1 = active high, 0 = active low */ +#define ADIS16204_MSC_CTRL_DATA_RDY_DIO2 (1 << 0) /* Data-ready line selection: 1 = DIO2, 0 = DIO1 */ + +/* DIAG_STAT */ +#define ADIS16204_DIAG_STAT_ALARM2 (1<<9) /* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ +#define ADIS16204_DIAG_STAT_ALARM1 (1<<8) /* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ +#define ADIS16204_DIAG_STAT_SELFTEST_FAIL (1<<5) /* Self-test diagnostic error flag: 1 = error condition, + 0 = normal operation */ +#define ADIS16204_DIAG_STAT_SPI_FAIL (1<<3) /* SPI communications failure */ +#define ADIS16204_DIAG_STAT_FLASH_UPT (1<<2) /* Flash update failure */ +#define ADIS16204_DIAG_STAT_POWER_HIGH (1<<1) /* Power supply above 3.625 V */ +#define ADIS16204_DIAG_STAT_POWER_LOW (1<<0) /* Power supply below 2.975 V */ + +/* GLOB_CMD */ +#define ADIS16204_GLOB_CMD_SW_RESET (1<<7) +#define ADIS16204_GLOB_CMD_CLEAR_STAT (1<<4) +#define ADIS16204_GLOB_CMD_FACTORY_CAL (1<<1) + +#define ADIS16204_MAX_TX 24 +#define ADIS16204_MAX_RX 24 + +#define ADIS16204_ERROR_ACTIVE (1<<14) + +/** + * struct adis16204_state - device instance specific data + * @us: actual spi_device + * @work_trigger_to_ring: bh for triggered event handling + * @inter: used to check if new interrupt has been triggered + * @last_timestamp: passing timestamp from th to bh of interrupt handler + * @indio_dev: industrial I/O device structure + * @trig: data ready trigger registered with iio + * @tx: transmit buffer + * @rx: recieve buffer + * @buf_lock: mutex to protect tx and rx + **/ +struct adis16204_state { + struct spi_device *us; + struct work_struct work_trigger_to_ring; + s64 last_timestamp; + struct iio_dev *indio_dev; + struct iio_trigger *trig; + u8 *tx; + u8 *rx; + struct mutex buf_lock; +}; + +int adis16204_set_irq(struct device *dev, bool enable); + +#ifdef CONFIG_IIO_RING_BUFFER +enum adis16204_scan { + ADIS16204_SCAN_SUPPLY, + ADIS16204_SCAN_ACC_X, + ADIS16204_SCAN_ACC_Y, + ADIS16204_SCAN_AUX_ADC, + ADIS16204_SCAN_TEMP, +}; + +void adis16204_remove_trigger(struct iio_dev *indio_dev); +int adis16204_probe_trigger(struct iio_dev *indio_dev); + +ssize_t adis16204_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf); + +int adis16204_configure_ring(struct iio_dev *indio_dev); +void adis16204_unconfigure_ring(struct iio_dev *indio_dev); + +int adis16204_initialize_ring(struct iio_ring_buffer *ring); +void adis16204_uninitialize_ring(struct iio_ring_buffer *ring); +#else /* CONFIG_IIO_RING_BUFFER */ + +static inline void adis16204_remove_trigger(struct iio_dev *indio_dev) +{ +} + +static inline int adis16204_probe_trigger(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline ssize_t +adis16204_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return 0; +} + +static int adis16204_configure_ring(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline void adis16204_unconfigure_ring(struct iio_dev *indio_dev) +{ +} + +static inline int adis16204_initialize_ring(struct iio_ring_buffer *ring) +{ + return 0; +} + +static inline void adis16204_uninitialize_ring(struct iio_ring_buffer *ring) +{ +} + +#endif /* CONFIG_IIO_RING_BUFFER */ +#endif /* SPI_ADIS16204_H_ */ diff --git a/trunk/drivers/staging/iio/accel/adis16204_core.c b/trunk/drivers/staging/iio/accel/adis16204_core.c new file mode 100644 index 000000000000..cc15e40726fc --- /dev/null +++ b/trunk/drivers/staging/iio/accel/adis16204_core.c @@ -0,0 +1,613 @@ +/* + * ADIS16204 Programmable High-g Digital Impact Sensor and Recorder + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "accel.h" +#include "../gyro/gyro.h" +#include "../adc/adc.h" + +#include "adis16204.h" + +#define DRIVER_NAME "adis16204" + +static int adis16204_check_status(struct device *dev); + +/** + * adis16204_spi_write_reg_8() - write single byte to a register + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @reg_address: the address of the register to be written + * @val: the value to write + **/ +static int adis16204_spi_write_reg_8(struct device *dev, + u8 reg_address, + u8 val) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16204_state *st = iio_dev_get_devdata(indio_dev); + + mutex_lock(&st->buf_lock); + st->tx[0] = ADIS16204_WRITE_REG(reg_address); + st->tx[1] = val; + + ret = spi_write(st->us, st->tx, 2); + mutex_unlock(&st->buf_lock); + + return ret; +} + +/** + * adis16204_spi_write_reg_16() - write 2 bytes to a pair of registers + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @reg_address: the address of the lower of the two registers. Second register + * is assumed to have address one greater. + * @val: value to be written + **/ +static int adis16204_spi_write_reg_16(struct device *dev, + u8 lower_reg_address, + u16 value) +{ + int ret; + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16204_state *st = iio_dev_get_devdata(indio_dev); + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + }, { + .tx_buf = st->tx + 2, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADIS16204_WRITE_REG(lower_reg_address); + st->tx[1] = value & 0xFF; + st->tx[2] = ADIS16204_WRITE_REG(lower_reg_address + 1); + st->tx[3] = (value >> 8) & 0xFF; + + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(st->us, &msg); + mutex_unlock(&st->buf_lock); + + return ret; +} + +/** + * adis16204_spi_read_reg_16() - read 2 bytes from a 16-bit register + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @reg_address: the address of the lower of the two registers. Second register + * is assumed to have address one greater. + * @val: somewhere to pass back the value read + **/ +static int adis16204_spi_read_reg_16(struct device *dev, + u8 lower_reg_address, + u16 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16204_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + .delay_usecs = 20, + }, { + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + .delay_usecs = 20, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADIS16204_READ_REG(lower_reg_address); + st->tx[1] = 0; + + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", + lower_reg_address); + goto error_ret; + } + *val = (st->rx[0] << 8) | st->rx[1]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static ssize_t adis16204_read_12bit_unsigned(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u16 val = 0; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = adis16204_spi_read_reg_16(dev, this_attr->address, &val); + if (ret) + return ret; + + if (val & ADIS16204_ERROR_ACTIVE) + adis16204_check_status(dev); + + return sprintf(buf, "%u\n", val & 0x0FFF); +} + +static ssize_t adis16204_read_temp(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + ssize_t ret; + u16 val; + + /* Take the iio_dev status lock */ + mutex_lock(&indio_dev->mlock); + + ret = adis16204_spi_read_reg_16(dev, ADIS16204_TEMP_OUT, (u16 *)&val); + if (ret) + goto error_ret; + + if (val & ADIS16204_ERROR_ACTIVE) + adis16204_check_status(dev); + + val &= 0xFFF; + ret = sprintf(buf, "%d\n", val); + +error_ret: + mutex_unlock(&indio_dev->mlock); + return ret; +} + +static ssize_t adis16204_read_12bit_signed(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + s16 val = 0; + ssize_t ret; + + mutex_lock(&indio_dev->mlock); + + ret = adis16204_spi_read_reg_16(dev, this_attr->address, (u16 *)&val); + if (!ret) { + if (val & ADIS16204_ERROR_ACTIVE) + adis16204_check_status(dev); + + val = ((s16)(val << 4) >> 4); + ret = sprintf(buf, "%d\n", val); + } + + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static ssize_t adis16204_read_14bit_signed(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + s16 val = 0; + ssize_t ret; + + mutex_lock(&indio_dev->mlock); + + ret = adis16204_spi_read_reg_16(dev, this_attr->address, (u16 *)&val); + if (!ret) { + if (val & ADIS16204_ERROR_ACTIVE) + adis16204_check_status(dev); + + val = ((s16)(val << 2) >> 2); + ret = sprintf(buf, "%d\n", val); + } + + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static ssize_t adis16204_write_16bit(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + long val; + + ret = strict_strtol(buf, 10, &val); + if (ret) + goto error_ret; + ret = adis16204_spi_write_reg_16(dev, this_attr->address, val); + +error_ret: + return ret ? ret : len; +} + +static int adis16204_reset(struct device *dev) +{ + int ret; + ret = adis16204_spi_write_reg_8(dev, + ADIS16204_GLOB_CMD, + ADIS16204_GLOB_CMD_SW_RESET); + if (ret) + dev_err(dev, "problem resetting device"); + + return ret; +} + +static ssize_t adis16204_write_reset(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + if (len < 1) + return -EINVAL; + switch (buf[0]) { + case '1': + case 'y': + case 'Y': + return adis16204_reset(dev); + } + return -EINVAL; +} + +int adis16204_set_irq(struct device *dev, bool enable) +{ + int ret = 0; + u16 msc; + + ret = adis16204_spi_read_reg_16(dev, ADIS16204_MSC_CTRL, &msc); + if (ret) + goto error_ret; + + msc |= ADIS16204_MSC_CTRL_ACTIVE_HIGH; + msc &= ~ADIS16204_MSC_CTRL_DATA_RDY_DIO2; + if (enable) + msc |= ADIS16204_MSC_CTRL_DATA_RDY_EN; + else + msc &= ~ADIS16204_MSC_CTRL_DATA_RDY_EN; + + ret = adis16204_spi_write_reg_16(dev, ADIS16204_MSC_CTRL, msc); + +error_ret: + return ret; +} + +static int adis16204_check_status(struct device *dev) +{ + u16 status; + int ret; + + ret = adis16204_spi_read_reg_16(dev, ADIS16204_DIAG_STAT, &status); + if (ret < 0) { + dev_err(dev, "Reading status failed\n"); + goto error_ret; + } + ret = status & 0x1F; + + if (status & ADIS16204_DIAG_STAT_SELFTEST_FAIL) + dev_err(dev, "Self test failure\n"); + if (status & ADIS16204_DIAG_STAT_SPI_FAIL) + dev_err(dev, "SPI failure\n"); + if (status & ADIS16204_DIAG_STAT_FLASH_UPT) + dev_err(dev, "Flash update failed\n"); + if (status & ADIS16204_DIAG_STAT_POWER_HIGH) + dev_err(dev, "Power supply above 3.625V\n"); + if (status & ADIS16204_DIAG_STAT_POWER_LOW) + dev_err(dev, "Power supply below 2.975V\n"); + +error_ret: + return ret; +} + +static int adis16204_self_test(struct device *dev) +{ + int ret; + ret = adis16204_spi_write_reg_16(dev, + ADIS16204_MSC_CTRL, + ADIS16204_MSC_CTRL_SELF_TEST_EN); + if (ret) { + dev_err(dev, "problem starting self test"); + goto err_ret; + } + + adis16204_check_status(dev); + +err_ret: + return ret; +} + +static int adis16204_initial_setup(struct adis16204_state *st) +{ + int ret; + struct device *dev = &st->indio_dev->dev; + + /* Disable IRQ */ + ret = adis16204_set_irq(dev, false); + if (ret) { + dev_err(dev, "disable irq failed"); + goto err_ret; + } + + /* Do self test */ + ret = adis16204_self_test(dev); + if (ret) { + dev_err(dev, "self test failure"); + goto err_ret; + } + + /* Read status register to check the result */ + ret = adis16204_check_status(dev); + if (ret) { + adis16204_reset(dev); + dev_err(dev, "device not playing ball -> reset"); + msleep(ADIS16204_STARTUP_DELAY); + ret = adis16204_check_status(dev); + if (ret) { + dev_err(dev, "giving up"); + goto err_ret; + } + } + + printk(KERN_INFO DRIVER_NAME ": at CS%d (irq %d)\n", + st->us->chip_select, st->us->irq); + +err_ret: + return ret; +} + +static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16204_read_12bit_unsigned, + ADIS16204_SUPPLY_OUT); +static IIO_CONST_ATTR(in0_supply_scale, "0.00122"); +static IIO_DEV_ATTR_IN_RAW(1, adis16204_read_12bit_unsigned, + ADIS16204_AUX_ADC); +static IIO_CONST_ATTR(in1_scale, "0.00061"); + +static IIO_DEV_ATTR_ACCEL_X(adis16204_read_14bit_signed, + ADIS16204_XACCL_OUT); +static IIO_DEV_ATTR_ACCEL_Y(adis16204_read_14bit_signed, + ADIS16204_YACCL_OUT); +static IIO_DEV_ATTR_ACCEL_XY(adis16204_read_14bit_signed, + ADIS16204_XY_RSS_OUT); +static IIO_DEV_ATTR_ACCEL_XPEAK(adis16204_read_14bit_signed, + ADIS16204_X_PEAK_OUT); +static IIO_DEV_ATTR_ACCEL_YPEAK(adis16204_read_14bit_signed, + ADIS16204_Y_PEAK_OUT); +static IIO_DEV_ATTR_ACCEL_XYPEAK(adis16204_read_14bit_signed, + ADIS16204_XY_PEAK_OUT); +static IIO_DEV_ATTR_ACCEL_X_OFFSET(S_IWUSR | S_IRUGO, + adis16204_read_12bit_signed, + adis16204_write_16bit, + ADIS16204_XACCL_NULL); +static IIO_DEV_ATTR_ACCEL_Y_OFFSET(S_IWUSR | S_IRUGO, + adis16204_read_12bit_signed, + adis16204_write_16bit, + ADIS16204_YACCL_NULL); +static IIO_CONST_ATTR(accel_x_scale, "0.017125"); +static IIO_CONST_ATTR(accel_y_scale, "0.008407"); +static IIO_CONST_ATTR(accel_xy_scale, "0.017125"); + +static IIO_DEV_ATTR_TEMP_RAW(adis16204_read_temp); +static IIO_CONST_ATTR(temp_offset, "25"); +static IIO_CONST_ATTR(temp_scale, "-0.47"); + +static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16204_write_reset, 0); + +static IIO_CONST_ATTR(name, "adis16204"); + +static struct attribute *adis16204_event_attributes[] = { + NULL +}; + +static struct attribute_group adis16204_event_attribute_group = { + .attrs = adis16204_event_attributes, +}; + +static struct attribute *adis16204_attributes[] = { + &iio_dev_attr_in0_supply_raw.dev_attr.attr, + &iio_const_attr_in0_supply_scale.dev_attr.attr, + &iio_dev_attr_temp_raw.dev_attr.attr, + &iio_const_attr_temp_offset.dev_attr.attr, + &iio_const_attr_temp_scale.dev_attr.attr, + &iio_dev_attr_reset.dev_attr.attr, + &iio_const_attr_name.dev_attr.attr, + &iio_dev_attr_in1_raw.dev_attr.attr, + &iio_const_attr_in1_scale.dev_attr.attr, + &iio_dev_attr_accel_x_raw.dev_attr.attr, + &iio_dev_attr_accel_y_raw.dev_attr.attr, + &iio_dev_attr_accel_xy.dev_attr.attr, + &iio_dev_attr_accel_xpeak.dev_attr.attr, + &iio_dev_attr_accel_ypeak.dev_attr.attr, + &iio_dev_attr_accel_xypeak.dev_attr.attr, + &iio_dev_attr_accel_x_offset.dev_attr.attr, + &iio_dev_attr_accel_y_offset.dev_attr.attr, + &iio_const_attr_accel_x_scale.dev_attr.attr, + &iio_const_attr_accel_y_scale.dev_attr.attr, + &iio_const_attr_accel_xy_scale.dev_attr.attr, + NULL +}; + +static const struct attribute_group adis16204_attribute_group = { + .attrs = adis16204_attributes, +}; + +static int __devinit adis16204_probe(struct spi_device *spi) +{ + int ret, regdone = 0; + struct adis16204_state *st = kzalloc(sizeof *st, GFP_KERNEL); + if (!st) { + ret = -ENOMEM; + goto error_ret; + } + /* this is only used for removal purposes */ + spi_set_drvdata(spi, st); + + /* Allocate the comms buffers */ + st->rx = kzalloc(sizeof(*st->rx)*ADIS16204_MAX_RX, GFP_KERNEL); + if (st->rx == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->tx = kzalloc(sizeof(*st->tx)*ADIS16204_MAX_TX, GFP_KERNEL); + if (st->tx == NULL) { + ret = -ENOMEM; + goto error_free_rx; + } + st->us = spi; + mutex_init(&st->buf_lock); + /* setup the industrialio driver allocated elements */ + st->indio_dev = iio_allocate_device(); + if (st->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_tx; + } + + st->indio_dev->dev.parent = &spi->dev; + st->indio_dev->num_interrupt_lines = 1; + st->indio_dev->event_attrs = &adis16204_event_attribute_group; + st->indio_dev->attrs = &adis16204_attribute_group; + st->indio_dev->dev_data = (void *)(st); + st->indio_dev->driver_module = THIS_MODULE; + st->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = adis16204_configure_ring(st->indio_dev); + if (ret) + goto error_free_dev; + + ret = iio_device_register(st->indio_dev); + if (ret) + goto error_unreg_ring_funcs; + regdone = 1; + + ret = adis16204_initialize_ring(st->indio_dev->ring); + if (ret) { + printk(KERN_ERR "failed to initialize the ring\n"); + goto error_unreg_ring_funcs; + } + + if (spi->irq) { + ret = iio_register_interrupt_line(spi->irq, + st->indio_dev, + 0, + IRQF_TRIGGER_RISING, + "adis16204"); + if (ret) + goto error_uninitialize_ring; + + ret = adis16204_probe_trigger(st->indio_dev); + if (ret) + goto error_unregister_line; + } + + /* Get the device into a sane initial state */ + ret = adis16204_initial_setup(st); + if (ret) + goto error_remove_trigger; + return 0; + +error_remove_trigger: + adis16204_remove_trigger(st->indio_dev); +error_unregister_line: + if (spi->irq) + iio_unregister_interrupt_line(st->indio_dev, 0); +error_uninitialize_ring: + adis16204_uninitialize_ring(st->indio_dev->ring); +error_unreg_ring_funcs: + adis16204_unconfigure_ring(st->indio_dev); +error_free_dev: + if (regdone) + iio_device_unregister(st->indio_dev); + else + iio_free_device(st->indio_dev); +error_free_tx: + kfree(st->tx); +error_free_rx: + kfree(st->rx); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +static int adis16204_remove(struct spi_device *spi) +{ + struct adis16204_state *st = spi_get_drvdata(spi); + struct iio_dev *indio_dev = st->indio_dev; + + flush_scheduled_work(); + + adis16204_remove_trigger(indio_dev); + if (spi->irq) + iio_unregister_interrupt_line(indio_dev, 0); + + adis16204_uninitialize_ring(indio_dev->ring); + iio_device_unregister(indio_dev); + adis16204_unconfigure_ring(indio_dev); + kfree(st->tx); + kfree(st->rx); + kfree(st); + + return 0; +} + +static struct spi_driver adis16204_driver = { + .driver = { + .name = "adis16204", + .owner = THIS_MODULE, + }, + .probe = adis16204_probe, + .remove = __devexit_p(adis16204_remove), +}; + +static __init int adis16204_init(void) +{ + return spi_register_driver(&adis16204_driver); +} +module_init(adis16204_init); + +static __exit void adis16204_exit(void) +{ + spi_unregister_driver(&adis16204_driver); +} +module_exit(adis16204_exit); + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices ADIS16204 Programmable High-g Digital Impact Sensor and Recorder"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/accel/adis16204_ring.c b/trunk/drivers/staging/iio/accel/adis16204_ring.c new file mode 100644 index 000000000000..420b160fe3ab --- /dev/null +++ b/trunk/drivers/staging/iio/accel/adis16204_ring.c @@ -0,0 +1,206 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "../ring_sw.h" +#include "accel.h" +#include "../trigger.h" +#include "adis16204.h" + +static IIO_SCAN_EL_C(in_supply, ADIS16204_SCAN_SUPPLY, ADIS16204_SUPPLY_OUT, NULL); +static IIO_CONST_ATTR_SCAN_EL_TYPE(in_supply, u, 12, 16); +static IIO_SCAN_EL_C(accel_x, ADIS16204_SCAN_ACC_X, ADIS16204_XACCL_OUT, NULL); +static IIO_SCAN_EL_C(accel_y, ADIS16204_SCAN_ACC_Y, ADIS16204_YACCL_OUT, NULL); +static IIO_CONST_ATTR_SCAN_EL_TYPE(accel, s, 14, 16); +static IIO_SCAN_EL_C(in0, ADIS16204_SCAN_AUX_ADC, ADIS16204_AUX_ADC, NULL); +static IIO_CONST_ATTR_SCAN_EL_TYPE(in0, u, 12, 16); +static IIO_SCAN_EL_C(temp, ADIS16204_SCAN_TEMP, ADIS16204_TEMP_OUT, NULL); +static IIO_CONST_ATTR_SCAN_EL_TYPE(temp, u, 12, 16); +static IIO_SCAN_EL_TIMESTAMP(5); +static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64); + +static struct attribute *adis16204_scan_el_attrs[] = { + &iio_scan_el_in_supply.dev_attr.attr, + &iio_const_attr_in_supply_index.dev_attr.attr, + &iio_const_attr_in_supply_type.dev_attr.attr, + &iio_scan_el_accel_x.dev_attr.attr, + &iio_const_attr_accel_x_index.dev_attr.attr, + &iio_scan_el_accel_y.dev_attr.attr, + &iio_const_attr_accel_y_index.dev_attr.attr, + &iio_const_attr_accel_type.dev_attr.attr, + &iio_scan_el_in0.dev_attr.attr, + &iio_const_attr_in0_index.dev_attr.attr, + &iio_const_attr_in0_type.dev_attr.attr, + &iio_scan_el_temp.dev_attr.attr, + &iio_const_attr_temp_index.dev_attr.attr, + &iio_const_attr_temp_type.dev_attr.attr, + &iio_scan_el_timestamp.dev_attr.attr, + &iio_const_attr_timestamp_index.dev_attr.attr, + &iio_const_attr_timestamp_type.dev_attr.attr, + NULL, +}; + +static struct attribute_group adis16204_scan_el_group = { + .attrs = adis16204_scan_el_attrs, + .name = "scan_elements", +}; + +/** + * adis16204_poll_func_th() top half interrupt handler called by trigger + * @private_data: iio_dev + **/ +static void adis16204_poll_func_th(struct iio_dev *indio_dev, s64 timestamp) +{ + struct adis16204_state *st = iio_dev_get_devdata(indio_dev); + st->last_timestamp = timestamp; + schedule_work(&st->work_trigger_to_ring); +} + +/** + * adis16204_read_ring_data() read data registers which will be placed into ring + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @rx: somewhere to pass back the value read + **/ +static int adis16204_read_ring_data(struct device *dev, u8 *rx) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16204_state *st = iio_dev_get_devdata(indio_dev); + struct spi_transfer xfers[ADIS16204_OUTPUTS + 1]; + int ret; + int i; + + mutex_lock(&st->buf_lock); + + spi_message_init(&msg); + + memset(xfers, 0, sizeof(xfers)); + for (i = 0; i <= ADIS16204_OUTPUTS; i++) { + xfers[i].bits_per_word = 8; + xfers[i].cs_change = 1; + xfers[i].len = 2; + xfers[i].delay_usecs = 20; + xfers[i].tx_buf = st->tx + 2 * i; + st->tx[2 * i] = ADIS16204_READ_REG(ADIS16204_SUPPLY_OUT + 2 * i); + st->tx[2 * i + 1] = 0; + if (i >= 1) + xfers[i].rx_buf = rx + 2 * (i - 1); + spi_message_add_tail(&xfers[i], &msg); + } + + ret = spi_sync(st->us, &msg); + if (ret) + dev_err(&st->us->dev, "problem when burst reading"); + + mutex_unlock(&st->buf_lock); + + return ret; +} + +/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device + * specific to be rolled into the core. + */ +static void adis16204_trigger_bh_to_ring(struct work_struct *work_s) +{ + struct adis16204_state *st + = container_of(work_s, struct adis16204_state, + work_trigger_to_ring); + struct iio_ring_buffer *ring = st->indio_dev->ring; + + int i = 0; + s16 *data; + size_t datasize = ring->access.get_bytes_per_datum(ring); + + data = kmalloc(datasize, GFP_KERNEL); + if (data == NULL) { + dev_err(&st->us->dev, "memory alloc failed in ring bh"); + return; + } + + if (ring->scan_count) + if (adis16204_read_ring_data(&st->indio_dev->dev, st->rx) >= 0) + for (; i < ring->scan_count; i++) + data[i] = be16_to_cpup( + (__be16 *)&(st->rx[i*2])); + + /* Guaranteed to be aligned with 8 byte boundary */ + if (ring->scan_timestamp) + *((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp; + + ring->access.store_to(ring, + (u8 *)data, + st->last_timestamp); + + iio_trigger_notify_done(st->indio_dev->trig); + kfree(data); + + return; +} + +void adis16204_unconfigure_ring(struct iio_dev *indio_dev) +{ + kfree(indio_dev->pollfunc); + iio_sw_rb_free(indio_dev->ring); +} + +int adis16204_configure_ring(struct iio_dev *indio_dev) +{ + int ret = 0; + struct adis16204_state *st = indio_dev->dev_data; + struct iio_ring_buffer *ring; + INIT_WORK(&st->work_trigger_to_ring, adis16204_trigger_bh_to_ring); + + ring = iio_sw_rb_allocate(indio_dev); + if (!ring) { + ret = -ENOMEM; + return ret; + } + indio_dev->ring = ring; + /* Effectively select the ring buffer implementation */ + iio_ring_sw_register_funcs(&ring->access); + ring->bpe = 2; + ring->scan_el_attrs = &adis16204_scan_el_group; + ring->scan_timestamp = true; + ring->preenable = &iio_sw_ring_preenable; + ring->postenable = &iio_triggered_ring_postenable; + ring->predisable = &iio_triggered_ring_predisable; + ring->owner = THIS_MODULE; + + /* Set default scan mode */ + iio_scan_mask_set(ring, iio_scan_el_in_supply.number); + iio_scan_mask_set(ring, iio_scan_el_accel_x.number); + iio_scan_mask_set(ring, iio_scan_el_accel_y.number); + iio_scan_mask_set(ring, iio_scan_el_temp.number); + iio_scan_mask_set(ring, iio_scan_el_in0.number); + + ret = iio_alloc_pollfunc(indio_dev, NULL, &adis16204_poll_func_th); + if (ret) + goto error_iio_sw_rb_free; + + indio_dev->modes |= INDIO_RING_TRIGGERED; + return 0; + +error_iio_sw_rb_free: + iio_sw_rb_free(indio_dev->ring); + return ret; +} + +int adis16204_initialize_ring(struct iio_ring_buffer *ring) +{ + return iio_ring_buffer_register(ring, 0); +} + +void adis16204_uninitialize_ring(struct iio_ring_buffer *ring) +{ + iio_ring_buffer_unregister(ring); +} diff --git a/trunk/drivers/staging/iio/accel/adis16204_trigger.c b/trunk/drivers/staging/iio/accel/adis16204_trigger.c new file mode 100644 index 000000000000..8e9db90e51eb --- /dev/null +++ b/trunk/drivers/staging/iio/accel/adis16204_trigger.c @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "../trigger.h" +#include "adis16204.h" + +/** + * adis16204_data_rdy_trig_poll() the event handler for the data rdy trig + **/ +static int adis16204_data_rdy_trig_poll(struct iio_dev *dev_info, + int index, + s64 timestamp, + int no_test) +{ + struct adis16204_state *st = iio_dev_get_devdata(dev_info); + struct iio_trigger *trig = st->trig; + + iio_trigger_poll(trig, timestamp); + + return IRQ_HANDLED; +} + +IIO_EVENT_SH(data_rdy_trig, &adis16204_data_rdy_trig_poll); + +static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL); + +static struct attribute *adis16204_trigger_attrs[] = { + &dev_attr_name.attr, + NULL, +}; + +static const struct attribute_group adis16204_trigger_attr_group = { + .attrs = adis16204_trigger_attrs, +}; + +/** + * adis16204_data_rdy_trigger_set_state() set datardy interrupt state + **/ +static int adis16204_data_rdy_trigger_set_state(struct iio_trigger *trig, + bool state) +{ + struct adis16204_state *st = trig->private_data; + struct iio_dev *indio_dev = st->indio_dev; + int ret = 0; + + dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); + ret = adis16204_set_irq(&st->indio_dev->dev, state); + if (state == false) { + iio_remove_event_from_list(&iio_event_data_rdy_trig, + &indio_dev->interrupts[0] + ->ev_list); + flush_scheduled_work(); + } else { + iio_add_event_to_list(&iio_event_data_rdy_trig, + &indio_dev->interrupts[0]->ev_list); + } + return ret; +} + +/** + * adis16204_trig_try_reen() try renabling irq for data rdy trigger + * @trig: the datardy trigger + **/ +static int adis16204_trig_try_reen(struct iio_trigger *trig) +{ + struct adis16204_state *st = trig->private_data; + enable_irq(st->us->irq); + return 0; +} + +int adis16204_probe_trigger(struct iio_dev *indio_dev) +{ + int ret; + struct adis16204_state *st = indio_dev->dev_data; + + st->trig = iio_allocate_trigger(); + st->trig->name = kasprintf(GFP_KERNEL, + "adis16204-dev%d", + indio_dev->id); + if (!st->trig->name) { + ret = -ENOMEM; + goto error_free_trig; + } + st->trig->dev.parent = &st->us->dev; + st->trig->owner = THIS_MODULE; + st->trig->private_data = st; + st->trig->set_trigger_state = &adis16204_data_rdy_trigger_set_state; + st->trig->try_reenable = &adis16204_trig_try_reen; + st->trig->control_attrs = &adis16204_trigger_attr_group; + ret = iio_trigger_register(st->trig); + + /* select default trigger */ + indio_dev->trig = st->trig; + if (ret) + goto error_free_trig_name; + + return 0; + +error_free_trig_name: + kfree(st->trig->name); +error_free_trig: + iio_free_trigger(st->trig); + + return ret; +} + +void adis16204_remove_trigger(struct iio_dev *indio_dev) +{ + struct adis16204_state *state = indio_dev->dev_data; + + iio_trigger_unregister(state->trig); + kfree(state->trig->name); + iio_free_trigger(state->trig); +} diff --git a/trunk/drivers/staging/iio/accel/adis16209_ring.c b/trunk/drivers/staging/iio/accel/adis16209_ring.c index 033135c6f226..8eba0af98ed5 100644 --- a/trunk/drivers/staging/iio/accel/adis16209_ring.c +++ b/trunk/drivers/staging/iio/accel/adis16209_ring.c @@ -105,7 +105,7 @@ static int adis16209_read_ring_data(struct device *dev, u8 *rx) xfers[i].bits_per_word = 8; xfers[i].cs_change = 1; xfers[i].len = 2; - xfers[i].delay_usecs = 20; + xfers[i].delay_usecs = 30; xfers[i].tx_buf = st->tx + 2 * i; st->tx[2 * i] = ADIS16209_READ_REG(ADIS16209_SUPPLY_OUT + 2 * i); diff --git a/trunk/drivers/staging/iio/adc/Kconfig b/trunk/drivers/staging/iio/adc/Kconfig index acb67677e563..9ca6565d2bae 100644 --- a/trunk/drivers/staging/iio/adc/Kconfig +++ b/trunk/drivers/staging/iio/adc/Kconfig @@ -27,6 +27,41 @@ config MAX1363_RING_BUFFER Say yes here to include ring buffer support in the MAX1363 ADC driver. +config AD7150 + tristate "Analog Devices ad7150/1/6 capacitive sensor driver" + depends on I2C + help + Say yes here to build support for Analog Devices capacitive sensors. + (ad7150, ad7151, ad7156) Provides direct access via sysfs. + +config AD7152 + tristate "Analog Devices ad7152/3 capacitive sensor driver" + depends on I2C + help + Say yes here to build support for Analog Devices capacitive sensors. + (ad7152, ad7153) Provides direct access via sysfs. + +config AD7291 + tristate "Analog Devices AD7291 temperature sensor driver" + depends on I2C + help + Say yes here to build support for Analog Devices AD7291 + temperature sensors. + +config AD7298 + tristate "Analog Devices AD7298 temperature sensor and ADC driver" + depends on SPI + help + Say yes here to build support for Analog Devices AD7298 + temperature sensors and ADC. + +config AD7314 + tristate "Analog Devices AD7314 temperature sensor driver" + depends on SPI + help + Say yes here to build support for Analog Devices AD7314 + temperature sensors. + config AD799X tristate "Analog Devices AD799x ADC driver" depends on I2C @@ -50,9 +85,9 @@ config AD799X_RING_BUFFER config AD7476 tristate "Analog Devices AD7475/6/7/8 AD7466/7/8 and AD7495 ADC driver" depends on SPI - select IIO_RING_BUFFER + select IIO_RING_BUFFER select IIO_SW_RING - select IIO_TRIGGER + select IIO_TRIGGER help Say yes here to build support for Analog Devices AD7475, AD7476, AD7477, AD7478, AD7466, AD7467, AD7468, AD7495 @@ -61,3 +96,41 @@ config AD7476 To compile this driver as a module, choose M here: the module will be called ad7476. + +config AD7745 + tristate "Analog Devices AD7745, AD7746 AD7747 capacitive sensor driver" + depends on I2C + help + Say yes here to build support for Analog Devices capacitive sensors. + (AD7745, AD7746, AD7747) Provides direct access via sysfs. + + To compile this driver as a module, choose M here: the + module will be called ad7745. + +config AD7816 + tristate "Analog Devices AD7816/7/8 temperature sensor and ADC driver" + depends on SPI + help + Say yes here to build support for Analog Devices AD7816/7/8 + temperature sensors and ADC. + +config ADT75 + tristate "Analog Devices ADT75 temperature sensor driver" + depends on I2C + help + Say yes here to build support for Analog Devices ADT75 + temperature sensors. + +config ADT7310 + tristate "Analog Devices ADT7310 temperature sensor driver" + depends on SPI + help + Say yes here to build support for Analog Devices ADT7310 + temperature sensors. + +config ADT7410 + tristate "Analog Devices ADT7410 temperature sensor driver" + depends on I2C + help + Say yes here to build support for Analog Devices ADT7410 + temperature sensors. diff --git a/trunk/drivers/staging/iio/adc/Makefile b/trunk/drivers/staging/iio/adc/Makefile index b62c319bcedd..a7dce6bd5f3a 100644 --- a/trunk/drivers/staging/iio/adc/Makefile +++ b/trunk/drivers/staging/iio/adc/Makefile @@ -14,3 +14,14 @@ obj-$(CONFIG_AD799X) += ad799x.o ad7476-y := ad7476_core.o ad7476-$(CONFIG_IIO_RING_BUFFER) += ad7476_ring.o obj-$(CONFIG_AD7476) += ad7476.o + +obj-$(CONFIG_AD7150) += ad7150.o +obj-$(CONFIG_AD7152) += ad7152.o +obj-$(CONFIG_AD7291) += ad7291.o +obj-$(CONFIG_AD7298) += ad7298.o +obj-$(CONFIG_AD7314) += ad7314.o +obj-$(CONFIG_AD7745) += ad7745.o +obj-$(CONFIG_AD7816) += ad7816.o +obj-$(CONFIG_ADT75) += adt75.o +obj-$(CONFIG_ADT7310) += adt7310.o +obj-$(CONFIG_ADT7410) += adt7410.o diff --git a/trunk/drivers/staging/iio/adc/ad7150.c b/trunk/drivers/staging/iio/adc/ad7150.c new file mode 100644 index 000000000000..8555766109d8 --- /dev/null +++ b/trunk/drivers/staging/iio/adc/ad7150.c @@ -0,0 +1,877 @@ +/* + * AD7150 capacitive sensor driver supporting AD7150/1/6 + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +/* + * AD7150 registers definition + */ + +#define AD7150_STATUS 0 +#define AD7150_STATUS_OUT1 (1 << 3) +#define AD7150_STATUS_OUT2 (1 << 5) +#define AD7150_CH1_DATA_HIGH 1 +#define AD7150_CH1_DATA_LOW 2 +#define AD7150_CH2_DATA_HIGH 3 +#define AD7150_CH2_DATA_LOW 4 +#define AD7150_CH1_AVG_HIGH 5 +#define AD7150_CH1_AVG_LOW 6 +#define AD7150_CH2_AVG_HIGH 7 +#define AD7150_CH2_AVG_LOW 8 +#define AD7150_CH1_SENSITIVITY 9 +#define AD7150_CH1_THR_HOLD_H 9 +#define AD7150_CH1_TIMEOUT 10 +#define AD7150_CH1_THR_HOLD_L 10 +#define AD7150_CH1_SETUP 11 +#define AD7150_CH2_SENSITIVITY 12 +#define AD7150_CH2_THR_HOLD_H 12 +#define AD7150_CH2_TIMEOUT 13 +#define AD7150_CH2_THR_HOLD_L 13 +#define AD7150_CH2_SETUP 14 +#define AD7150_CFG 15 +#define AD7150_CFG_FIX (1 << 7) +#define AD7150_PD_TIMER 16 +#define AD7150_CH1_CAPDAC 17 +#define AD7150_CH2_CAPDAC 18 +#define AD7150_SN3 19 +#define AD7150_SN2 20 +#define AD7150_SN1 21 +#define AD7150_SN0 22 +#define AD7150_ID 23 + +#define AD7150_MAX_CONV_MODE 4 + +/* + * struct ad7150_chip_info - chip specifc information + */ + +struct ad7150_chip_info { + const char *name; + struct i2c_client *client; + struct iio_dev *indio_dev; + struct work_struct thresh_work; + bool inter; + s64 last_timestamp; + u16 ch1_threshold; /* Ch1 Threshold (in fixed threshold mode) */ + u8 ch1_sensitivity; /* Ch1 Sensitivity (in adaptive threshold mode) */ + u8 ch1_timeout; /* Ch1 Timeout (in adaptive threshold mode) */ + u8 ch1_setup; + u16 ch2_threshold; /* Ch2 Threshold (in fixed threshold mode) */ + u8 ch2_sensitivity; /* Ch1 Sensitivity (in adaptive threshold mode) */ + u8 ch2_timeout; /* Ch1 Timeout (in adaptive threshold mode) */ + u8 ch2_setup; + u8 powerdown_timer; + char threshold_mode[10]; /* adaptive/fixed threshold mode */ + int old_state; + char *conversion_mode; +}; + +struct ad7150_conversion_mode { + char *name; + u8 reg_cfg; +}; + +struct ad7150_conversion_mode ad7150_conv_mode_table[AD7150_MAX_CONV_MODE] = { + { "idle", 0 }, + { "continuous-conversion", 1 }, + { "single-conversion", 2 }, + { "power-down", 3 }, +}; + +/* + * ad7150 register access by I2C + */ + +static int ad7150_i2c_read(struct ad7150_chip_info *chip, u8 reg, u8 *data, int len) +{ + struct i2c_client *client = chip->client; + int ret = 0; + + ret = i2c_master_send(client, ®, 1); + if (ret < 0) { + dev_err(&client->dev, "I2C write error\n"); + return ret; + } + + ret = i2c_master_recv(client, data, len); + if (ret < 0) { + dev_err(&client->dev, "I2C read error\n"); + return ret; + } + + return ret; +} + +static int ad7150_i2c_write(struct ad7150_chip_info *chip, u8 reg, u8 data) +{ + struct i2c_client *client = chip->client; + int ret = 0; + + u8 tx[2] = { + reg, + data, + }; + + ret = i2c_master_send(client, tx, 2); + if (ret < 0) + dev_err(&client->dev, "I2C write error\n"); + + return ret; +} + +/* + * sysfs nodes + */ + +#define IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(_show) \ + IIO_DEVICE_ATTR(available_conversion_modes, S_IRUGO, _show, NULL, 0) +#define IIO_DEV_ATTR_CONVERSION_MODE(_mode, _show, _store) \ + IIO_DEVICE_ATTR(conversion_mode, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_AVAIL_THRESHOLD_MODES(_show) \ + IIO_DEVICE_ATTR(available_threshold_modes, S_IRUGO, _show, NULL, 0) +#define IIO_DEV_ATTR_THRESHOLD_MODE(_mode, _show, _store) \ + IIO_DEVICE_ATTR(threshold_mode, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_CH1_THRESHOLD(_mode, _show, _store) \ + IIO_DEVICE_ATTR(ch1_threshold, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_CH2_THRESHOLD(_mode, _show, _store) \ + IIO_DEVICE_ATTR(ch2_threshold, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_CH1_SENSITIVITY(_mode, _show, _store) \ + IIO_DEVICE_ATTR(ch1_sensitivity, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_CH2_SENSITIVITY(_mode, _show, _store) \ + IIO_DEVICE_ATTR(ch2_sensitivity, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_CH1_TIMEOUT(_mode, _show, _store) \ + IIO_DEVICE_ATTR(ch1_timeout, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_CH2_TIMEOUT(_mode, _show, _store) \ + IIO_DEVICE_ATTR(ch2_timeout, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_CH1_VALUE(_show) \ + IIO_DEVICE_ATTR(ch1_value, S_IRUGO, _show, NULL, 0) +#define IIO_DEV_ATTR_CH2_VALUE(_show) \ + IIO_DEVICE_ATTR(ch2_value, S_IRUGO, _show, NULL, 0) +#define IIO_DEV_ATTR_CH1_SETUP(_mode, _show, _store) \ + IIO_DEVICE_ATTR(ch1_setup, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_CH2_SETUP(_mode, _show, _store) \ + IIO_DEVICE_ATTR(ch2_setup, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_POWERDOWN_TIMER(_mode, _show, _store) \ + IIO_DEVICE_ATTR(powerdown_timer, _mode, _show, _store, 0) + +static ssize_t ad7150_show_conversion_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int i; + int len = 0; + + for (i = 0; i < AD7150_MAX_CONV_MODE; i++) + len += sprintf(buf + len, "%s\n", ad7150_conv_mode_table[i].name); + + return len; +} + +static IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(ad7150_show_conversion_modes); + +static ssize_t ad7150_show_conversion_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%s\n", chip->conversion_mode); +} + +static ssize_t ad7150_store_conversion_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + u8 cfg; + int i; + + ad7150_i2c_read(chip, AD7150_CFG, &cfg, 1); + + for (i = 0; i < AD7150_MAX_CONV_MODE; i++) { + if (strncmp(buf, ad7150_conv_mode_table[i].name, + strlen(ad7150_conv_mode_table[i].name) - 1) == 0) { + chip->conversion_mode = ad7150_conv_mode_table[i].name; + cfg |= 0x18 | ad7150_conv_mode_table[i].reg_cfg; + ad7150_i2c_write(chip, AD7150_CFG, cfg); + return len; + } + } + + dev_err(dev, "not supported conversion mode\n"); + + return -EINVAL; +} + +static IIO_DEV_ATTR_CONVERSION_MODE(S_IRUGO | S_IWUSR, + ad7150_show_conversion_mode, + ad7150_store_conversion_mode); + +static ssize_t ad7150_show_threshold_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "adaptive\nfixed\n"); +} + +static IIO_DEV_ATTR_AVAIL_THRESHOLD_MODES(ad7150_show_threshold_modes); + +static ssize_t ad7150_show_ch1_value(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + u8 data[2]; + + ad7150_i2c_read(chip, AD7150_CH1_DATA_HIGH, data, 2); + return sprintf(buf, "%d\n", ((int) data[0] << 8) | data[1]); +} + +static IIO_DEV_ATTR_CH1_VALUE(ad7150_show_ch1_value); + +static ssize_t ad7150_show_ch2_value(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + u8 data[2]; + + ad7150_i2c_read(chip, AD7150_CH2_DATA_HIGH, data, 2); + return sprintf(buf, "%d\n", ((int) data[0] << 8) | data[1]); +} + +static IIO_DEV_ATTR_CH2_VALUE(ad7150_show_ch2_value); + +static ssize_t ad7150_show_threshold_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%s\n", chip->threshold_mode); +} + +static ssize_t ad7150_store_threshold_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + u8 cfg; + + ad7150_i2c_read(chip, AD7150_CFG, &cfg, 1); + + if (strncmp(buf, "fixed", 5) == 0) { + strcpy(chip->threshold_mode, "fixed"); + cfg |= AD7150_CFG_FIX; + ad7150_i2c_write(chip, AD7150_CFG, cfg); + + return len; + } else if (strncmp(buf, "adaptive", 8) == 0) { + strcpy(chip->threshold_mode, "adaptive"); + cfg &= ~AD7150_CFG_FIX; + ad7150_i2c_write(chip, AD7150_CFG, cfg); + + return len; + } + + dev_err(dev, "not supported threshold mode\n"); + return -EINVAL; +} + +static IIO_DEV_ATTR_THRESHOLD_MODE(S_IRUGO | S_IWUSR, + ad7150_show_threshold_mode, + ad7150_store_threshold_mode); + +static ssize_t ad7150_show_ch1_threshold(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", chip->ch1_threshold); +} + +static ssize_t ad7150_store_ch1_threshold(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x10000)) { + ad7150_i2c_write(chip, AD7150_CH1_THR_HOLD_H, data >> 8); + ad7150_i2c_write(chip, AD7150_CH1_THR_HOLD_L, data); + chip->ch1_threshold = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_CH1_THRESHOLD(S_IRUGO | S_IWUSR, + ad7150_show_ch1_threshold, + ad7150_store_ch1_threshold); + +static ssize_t ad7150_show_ch2_threshold(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", chip->ch2_threshold); +} + +static ssize_t ad7150_store_ch2_threshold(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x10000)) { + ad7150_i2c_write(chip, AD7150_CH2_THR_HOLD_H, data >> 8); + ad7150_i2c_write(chip, AD7150_CH2_THR_HOLD_L, data); + chip->ch2_threshold = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_CH2_THRESHOLD(S_IRUGO | S_IWUSR, + ad7150_show_ch2_threshold, + ad7150_store_ch2_threshold); + +static ssize_t ad7150_show_ch1_sensitivity(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", chip->ch1_sensitivity); +} + +static ssize_t ad7150_store_ch1_sensitivity(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x100)) { + ad7150_i2c_write(chip, AD7150_CH1_SENSITIVITY, data); + chip->ch1_sensitivity = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_CH1_SENSITIVITY(S_IRUGO | S_IWUSR, + ad7150_show_ch1_sensitivity, + ad7150_store_ch1_sensitivity); + +static ssize_t ad7150_show_ch2_sensitivity(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", chip->ch2_sensitivity); +} + +static ssize_t ad7150_store_ch2_sensitivity(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x100)) { + ad7150_i2c_write(chip, AD7150_CH2_SENSITIVITY, data); + chip->ch2_sensitivity = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_CH2_SENSITIVITY(S_IRUGO | S_IWUSR, + ad7150_show_ch2_sensitivity, + ad7150_store_ch2_sensitivity); + +static ssize_t ad7150_show_ch1_timeout(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", chip->ch1_timeout); +} + +static ssize_t ad7150_store_ch1_timeout(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x100)) { + ad7150_i2c_write(chip, AD7150_CH1_TIMEOUT, data); + chip->ch1_timeout = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_CH1_TIMEOUT(S_IRUGO | S_IWUSR, + ad7150_show_ch1_timeout, + ad7150_store_ch1_timeout); + +static ssize_t ad7150_show_ch2_timeout(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", chip->ch2_timeout); +} + +static ssize_t ad7150_store_ch2_timeout(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x100)) { + ad7150_i2c_write(chip, AD7150_CH2_TIMEOUT, data); + chip->ch2_timeout = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_CH2_TIMEOUT(S_IRUGO | S_IWUSR, + ad7150_show_ch2_timeout, + ad7150_store_ch2_timeout); + +static ssize_t ad7150_show_ch1_setup(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "0x%02x\n", chip->ch1_setup); +} + +static ssize_t ad7150_store_ch1_setup(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x100)) { + ad7150_i2c_write(chip, AD7150_CH1_SETUP, data); + chip->ch1_setup = data; + return len; + } + + + return -EINVAL; +} + +static IIO_DEV_ATTR_CH1_SETUP(S_IRUGO | S_IWUSR, + ad7150_show_ch1_setup, + ad7150_store_ch1_setup); + +static ssize_t ad7150_show_ch2_setup(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "0x%02x\n", chip->ch2_setup); +} + +static ssize_t ad7150_store_ch2_setup(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x100)) { + ad7150_i2c_write(chip, AD7150_CH2_SETUP, data); + chip->ch2_setup = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_CH2_SETUP(S_IRUGO | S_IWUSR, + ad7150_show_ch2_setup, + ad7150_store_ch2_setup); + +static ssize_t ad7150_show_name(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + return sprintf(buf, "%s\n", chip->name); +} + +static IIO_DEVICE_ATTR(name, S_IRUGO, ad7150_show_name, NULL, 0); + +static ssize_t ad7150_show_powerdown_timer(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "0x%02x\n", chip->powerdown_timer); +} + +static ssize_t ad7150_store_powerdown_timer(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7150_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x40)) { + chip->powerdown_timer = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_POWERDOWN_TIMER(S_IRUGO | S_IWUSR, + ad7150_show_powerdown_timer, + ad7150_store_powerdown_timer); + +static struct attribute *ad7150_attributes[] = { + &iio_dev_attr_available_threshold_modes.dev_attr.attr, + &iio_dev_attr_threshold_mode.dev_attr.attr, + &iio_dev_attr_ch1_threshold.dev_attr.attr, + &iio_dev_attr_ch2_threshold.dev_attr.attr, + &iio_dev_attr_ch1_timeout.dev_attr.attr, + &iio_dev_attr_ch2_timeout.dev_attr.attr, + &iio_dev_attr_ch1_setup.dev_attr.attr, + &iio_dev_attr_ch2_setup.dev_attr.attr, + &iio_dev_attr_ch1_sensitivity.dev_attr.attr, + &iio_dev_attr_ch2_sensitivity.dev_attr.attr, + &iio_dev_attr_powerdown_timer.dev_attr.attr, + &iio_dev_attr_ch1_value.dev_attr.attr, + &iio_dev_attr_ch2_value.dev_attr.attr, + &iio_dev_attr_name.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad7150_attribute_group = { + .attrs = ad7150_attributes, +}; + +/* + * threshold events + */ + +#define IIO_EVENT_CODE_CH1_HIGH IIO_BUFFER_EVENT_CODE(0) +#define IIO_EVENT_CODE_CH1_LOW IIO_BUFFER_EVENT_CODE(1) +#define IIO_EVENT_CODE_CH2_HIGH IIO_BUFFER_EVENT_CODE(2) +#define IIO_EVENT_CODE_CH2_LOW IIO_BUFFER_EVENT_CODE(3) + +#define IIO_EVENT_ATTR_CH1_HIGH_SH(_evlist, _show, _store, _mask) \ + IIO_EVENT_ATTR_SH(ch1_high, _evlist, _show, _store, _mask) + +#define IIO_EVENT_ATTR_CH2_HIGH_SH(_evlist, _show, _store, _mask) \ + IIO_EVENT_ATTR_SH(ch2_high, _evlist, _show, _store, _mask) + +#define IIO_EVENT_ATTR_CH1_LOW_SH(_evlist, _show, _store, _mask) \ + IIO_EVENT_ATTR_SH(ch1_low, _evlist, _show, _store, _mask) + +#define IIO_EVENT_ATTR_CH2_LOW_SH(_evlist, _show, _store, _mask) \ + IIO_EVENT_ATTR_SH(ch2_low, _evlist, _show, _store, _mask) + +static void ad7150_interrupt_handler_bh(struct work_struct *work_s) +{ + struct ad7150_chip_info *chip = + container_of(work_s, struct ad7150_chip_info, thresh_work); + u8 int_status; + + enable_irq(chip->client->irq); + + ad7150_i2c_read(chip, AD7150_STATUS, &int_status, 1); + + if ((int_status & AD7150_STATUS_OUT1) && !(chip->old_state & AD7150_STATUS_OUT1)) + iio_push_event(chip->indio_dev, 0, + IIO_EVENT_CODE_CH1_HIGH, + chip->last_timestamp); + else if ((!(int_status & AD7150_STATUS_OUT1)) && (chip->old_state & AD7150_STATUS_OUT1)) + iio_push_event(chip->indio_dev, 0, + IIO_EVENT_CODE_CH1_LOW, + chip->last_timestamp); + + if ((int_status & AD7150_STATUS_OUT2) && !(chip->old_state & AD7150_STATUS_OUT2)) + iio_push_event(chip->indio_dev, 0, + IIO_EVENT_CODE_CH2_HIGH, + chip->last_timestamp); + else if ((!(int_status & AD7150_STATUS_OUT2)) && (chip->old_state & AD7150_STATUS_OUT2)) + iio_push_event(chip->indio_dev, 0, + IIO_EVENT_CODE_CH2_LOW, + chip->last_timestamp); +} + +static int ad7150_interrupt_handler_th(struct iio_dev *dev_info, + int index, + s64 timestamp, + int no_test) +{ + struct ad7150_chip_info *chip = dev_info->dev_data; + + chip->last_timestamp = timestamp; + schedule_work(&chip->thresh_work); + + return 0; +} + +IIO_EVENT_SH(threshold, &ad7150_interrupt_handler_th); + +static ssize_t ad7150_query_out_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + /* + * AD7150 provides two logic output channels, which can be used as interrupt + * but the pins are not configurable + */ + return sprintf(buf, "1\n"); +} + +static ssize_t ad7150_set_out_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return len; +} + +IIO_EVENT_ATTR_CH1_HIGH_SH(iio_event_threshold, ad7150_query_out_mode, ad7150_set_out_mode, 0); +IIO_EVENT_ATTR_CH2_HIGH_SH(iio_event_threshold, ad7150_query_out_mode, ad7150_set_out_mode, 0); +IIO_EVENT_ATTR_CH1_LOW_SH(iio_event_threshold, ad7150_query_out_mode, ad7150_set_out_mode, 0); +IIO_EVENT_ATTR_CH2_LOW_SH(iio_event_threshold, ad7150_query_out_mode, ad7150_set_out_mode, 0); + +static struct attribute *ad7150_event_attributes[] = { + &iio_event_attr_ch1_high.dev_attr.attr, + &iio_event_attr_ch2_high.dev_attr.attr, + &iio_event_attr_ch1_low.dev_attr.attr, + &iio_event_attr_ch2_low.dev_attr.attr, + NULL, +}; + +static struct attribute_group ad7150_event_attribute_group = { + .attrs = ad7150_event_attributes, +}; + +/* + * device probe and remove + */ + +static int __devinit ad7150_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret = 0, regdone = 0; + struct ad7150_chip_info *chip = kzalloc(sizeof(*chip), GFP_KERNEL); + if (chip == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + /* this is only used for device removal purposes */ + i2c_set_clientdata(client, chip); + + chip->client = client; + chip->name = id->name; + + chip->indio_dev = iio_allocate_device(); + if (chip->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_chip; + } + + /* Echipabilish that the iio_dev is a child of the i2c device */ + chip->indio_dev->dev.parent = &client->dev; + chip->indio_dev->attrs = &ad7150_attribute_group; + chip->indio_dev->event_attrs = &ad7150_event_attribute_group; + chip->indio_dev->dev_data = (void *)(chip); + chip->indio_dev->driver_module = THIS_MODULE; + chip->indio_dev->num_interrupt_lines = 1; + chip->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(chip->indio_dev); + if (ret) + goto error_free_dev; + regdone = 1; + + if (client->irq && gpio_is_valid(irq_to_gpio(client->irq)) > 0) { + ret = iio_register_interrupt_line(client->irq, + chip->indio_dev, + 0, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "ad7150"); + if (ret) + goto error_free_dev; + + iio_add_event_to_list(iio_event_attr_ch2_low.listel, + &chip->indio_dev->interrupts[0]->ev_list); + + INIT_WORK(&chip->thresh_work, ad7150_interrupt_handler_bh); + } + + dev_err(&client->dev, "%s capacitive sensor registered, irq: %d\n", id->name, client->irq); + + return 0; + +error_free_dev: + if (regdone) + iio_device_unregister(chip->indio_dev); + else + iio_free_device(chip->indio_dev); +error_free_chip: + kfree(chip); +error_ret: + return ret; +} + +static int __devexit ad7150_remove(struct i2c_client *client) +{ + struct ad7150_chip_info *chip = i2c_get_clientdata(client); + struct iio_dev *indio_dev = chip->indio_dev; + + if (client->irq && gpio_is_valid(irq_to_gpio(client->irq)) > 0) + iio_unregister_interrupt_line(indio_dev, 0); + iio_device_unregister(indio_dev); + kfree(chip); + + return 0; +} + +static const struct i2c_device_id ad7150_id[] = { + { "ad7150", 0 }, + { "ad7151", 0 }, + { "ad7156", 0 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, ad7150_id); + +static struct i2c_driver ad7150_driver = { + .driver = { + .name = "ad7150", + }, + .probe = ad7150_probe, + .remove = __devexit_p(ad7150_remove), + .id_table = ad7150_id, +}; + +static __init int ad7150_init(void) +{ + return i2c_add_driver(&ad7150_driver); +} + +static __exit void ad7150_exit(void) +{ + i2c_del_driver(&ad7150_driver); +} + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices ad7150/1/6 capacitive sensor driver"); +MODULE_LICENSE("GPL v2"); + +module_init(ad7150_init); +module_exit(ad7150_exit); diff --git a/trunk/drivers/staging/iio/adc/ad7152.c b/trunk/drivers/staging/iio/adc/ad7152.c new file mode 100644 index 000000000000..fa7f84062307 --- /dev/null +++ b/trunk/drivers/staging/iio/adc/ad7152.c @@ -0,0 +1,610 @@ +/* + * AD7152 capacitive sensor driver supporting AD7152/3 + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +/* + * AD7152 registers definition + */ + +#define AD7152_STATUS 0 +#define AD7152_STATUS_RDY1 (1 << 0) +#define AD7152_STATUS_RDY2 (1 << 1) +#define AD7152_CH1_DATA_HIGH 1 +#define AD7152_CH1_DATA_LOW 2 +#define AD7152_CH2_DATA_HIGH 3 +#define AD7152_CH2_DATA_LOW 4 +#define AD7152_CH1_OFFS_HIGH 5 +#define AD7152_CH1_OFFS_LOW 6 +#define AD7152_CH2_OFFS_HIGH 7 +#define AD7152_CH2_OFFS_LOW 8 +#define AD7152_CH1_GAIN_HIGH 9 +#define AD7152_CH1_GAIN_LOW 10 +#define AD7152_CH1_SETUP 11 +#define AD7152_CH2_GAIN_HIGH 12 +#define AD7152_CH2_GAIN_LOW 13 +#define AD7152_CH2_SETUP 14 +#define AD7152_CFG 15 +#define AD7152_RESEVERD 16 +#define AD7152_CAPDAC_POS 17 +#define AD7152_CAPDAC_NEG 18 +#define AD7152_CFG2 26 + +#define AD7152_MAX_CONV_MODE 6 + +/* + * struct ad7152_chip_info - chip specifc information + */ + +struct ad7152_chip_info { + const char *name; + struct i2c_client *client; + struct iio_dev *indio_dev; + u16 ch1_offset; /* Channel 1 offset calibration coefficient */ + u16 ch1_gain; /* Channel 1 gain coefficient */ + u8 ch1_setup; + u16 ch2_offset; /* Channel 2 offset calibration coefficient */ + u16 ch2_gain; /* Channel 1 gain coefficient */ + u8 ch2_setup; + u8 filter_rate_setup; /* Capacitive channel digital filter setup; conversion time/update rate setup per channel */ + char *conversion_mode; +}; + +struct ad7152_conversion_mode { + char *name; + u8 reg_cfg; +}; + +struct ad7152_conversion_mode ad7152_conv_mode_table[AD7152_MAX_CONV_MODE] = { + { "idle", 0 }, + { "continuous-conversion", 1 }, + { "single-conversion", 2 }, + { "power-down", 3 }, + { "offset-calibration", 5 }, + { "gain-calibration", 6 }, +}; + +/* + * ad7152 register access by I2C + */ + +static int ad7152_i2c_read(struct ad7152_chip_info *chip, u8 reg, u8 *data, int len) +{ + struct i2c_client *client = chip->client; + int ret; + + ret = i2c_master_send(client, ®, 1); + if (ret < 0) { + dev_err(&client->dev, "I2C write error\n"); + return ret; + } + + ret = i2c_master_recv(client, data, len); + if (ret < 0) { + dev_err(&client->dev, "I2C read error\n"); + } + + return ret; +} + +static int ad7152_i2c_write(struct ad7152_chip_info *chip, u8 reg, u8 data) +{ + struct i2c_client *client = chip->client; + int ret; + + u8 tx[2] = { + reg, + data, + }; + + ret = i2c_master_send(client, tx, 2); + if (ret < 0) + dev_err(&client->dev, "I2C write error\n"); + + return ret; +} + +/* + * sysfs nodes + */ + +#define IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(_show) \ + IIO_DEVICE_ATTR(available_conversion_modes, S_IRUGO, _show, NULL, 0) +#define IIO_DEV_ATTR_CONVERSION_MODE(_mode, _show, _store) \ + IIO_DEVICE_ATTR(conversion_mode, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_CH1_OFFSET(_mode, _show, _store) \ + IIO_DEVICE_ATTR(ch1_offset, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_CH2_OFFSET(_mode, _show, _store) \ + IIO_DEVICE_ATTR(ch2_offset, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_CH1_GAIN(_mode, _show, _store) \ + IIO_DEVICE_ATTR(ch1_gain, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_CH2_GAIN(_mode, _show, _store) \ + IIO_DEVICE_ATTR(ch2_gain, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_CH1_VALUE(_show) \ + IIO_DEVICE_ATTR(ch1_value, S_IRUGO, _show, NULL, 0) +#define IIO_DEV_ATTR_CH2_VALUE(_show) \ + IIO_DEVICE_ATTR(ch2_value, S_IRUGO, _show, NULL, 0) +#define IIO_DEV_ATTR_CH1_SETUP(_mode, _show, _store) \ + IIO_DEVICE_ATTR(ch1_setup, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_CH2_SETUP(_mode, _show, _store) \ + IIO_DEVICE_ATTR(ch2_setup, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_FILTER_RATE_SETUP(_mode, _show, _store) \ + IIO_DEVICE_ATTR(filter_rate_setup, _mode, _show, _store, 0) + +static ssize_t ad7152_show_conversion_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int i; + int len = 0; + + for (i = 0; i < AD7152_MAX_CONV_MODE; i++) + len += sprintf(buf + len, "%s ", ad7152_conv_mode_table[i].name); + + len += sprintf(buf + len, "\n"); + + return len; +} + +static IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(ad7152_show_conversion_modes); + +static ssize_t ad7152_show_ch1_value(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + u8 data[2]; + + ad7152_i2c_read(chip, AD7152_CH1_DATA_HIGH, data, 2); + return sprintf(buf, "%d\n", ((int)data[0] << 8) | data[1]); +} + +static IIO_DEV_ATTR_CH1_VALUE(ad7152_show_ch1_value); + +static ssize_t ad7152_show_ch2_value(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + u8 data[2]; + + ad7152_i2c_read(chip, AD7152_CH2_DATA_HIGH, data, 2); + return sprintf(buf, "%d\n", ((int)data[0] << 8) | data[1]); +} + +static IIO_DEV_ATTR_CH2_VALUE(ad7152_show_ch2_value); + +static ssize_t ad7152_show_conversion_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%s\n", chip->conversion_mode); +} + +static ssize_t ad7152_store_conversion_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + u8 cfg; + int i; + + ad7152_i2c_read(chip, AD7152_CFG, &cfg, 1); + + for (i = 0; i < AD7152_MAX_CONV_MODE; i++) + if (strncmp(buf, ad7152_conv_mode_table[i].name, + strlen(ad7152_conv_mode_table[i].name) - 1) == 0) { + chip->conversion_mode = ad7152_conv_mode_table[i].name; + cfg |= 0x18 | ad7152_conv_mode_table[i].reg_cfg; + ad7152_i2c_write(chip, AD7152_CFG, cfg); + return len; + } + + dev_err(dev, "not supported conversion mode\n"); + + return -EINVAL; +} + +static IIO_DEV_ATTR_CONVERSION_MODE(S_IRUGO | S_IWUSR, + ad7152_show_conversion_mode, + ad7152_store_conversion_mode); + +static ssize_t ad7152_show_ch1_offset(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", chip->ch1_offset); +} + +static ssize_t ad7152_store_ch1_offset(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x10000)) { + ad7152_i2c_write(chip, AD7152_CH1_OFFS_HIGH, data >> 8); + ad7152_i2c_write(chip, AD7152_CH1_OFFS_LOW, data); + chip->ch1_offset = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_CH1_OFFSET(S_IRUGO | S_IWUSR, + ad7152_show_ch1_offset, + ad7152_store_ch1_offset); + +static ssize_t ad7152_show_ch2_offset(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", chip->ch2_offset); +} + +static ssize_t ad7152_store_ch2_offset(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x10000)) { + ad7152_i2c_write(chip, AD7152_CH2_OFFS_HIGH, data >> 8); + ad7152_i2c_write(chip, AD7152_CH2_OFFS_LOW, data); + chip->ch2_offset = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_CH2_OFFSET(S_IRUGO | S_IWUSR, + ad7152_show_ch2_offset, + ad7152_store_ch2_offset); + +static ssize_t ad7152_show_ch1_gain(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", chip->ch1_gain); +} + +static ssize_t ad7152_store_ch1_gain(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x10000)) { + ad7152_i2c_write(chip, AD7152_CH1_GAIN_HIGH, data >> 8); + ad7152_i2c_write(chip, AD7152_CH1_GAIN_LOW, data); + chip->ch1_gain = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_CH1_GAIN(S_IRUGO | S_IWUSR, + ad7152_show_ch1_gain, + ad7152_store_ch1_gain); + +static ssize_t ad7152_show_ch2_gain(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", chip->ch2_gain); +} + +static ssize_t ad7152_store_ch2_gain(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x10000)) { + ad7152_i2c_write(chip, AD7152_CH2_GAIN_HIGH, data >> 8); + ad7152_i2c_write(chip, AD7152_CH2_GAIN_LOW, data); + chip->ch2_gain = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_CH2_GAIN(S_IRUGO | S_IWUSR, + ad7152_show_ch2_gain, + ad7152_store_ch2_gain); + +static ssize_t ad7152_show_ch1_setup(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "0x%02x\n", chip->ch1_setup); +} + +static ssize_t ad7152_store_ch1_setup(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x100)) { + ad7152_i2c_write(chip, AD7152_CH1_SETUP, data); + chip->ch1_setup = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_CH1_SETUP(S_IRUGO | S_IWUSR, + ad7152_show_ch1_setup, + ad7152_store_ch1_setup); + +static ssize_t ad7152_show_ch2_setup(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "0x%02x\n", chip->ch2_setup); +} + +static ssize_t ad7152_store_ch2_setup(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x100)) { + ad7152_i2c_write(chip, AD7152_CH2_SETUP, data); + chip->ch2_setup = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_CH2_SETUP(S_IRUGO | S_IWUSR, + ad7152_show_ch2_setup, + ad7152_store_ch2_setup); + +static ssize_t ad7152_show_filter_rate_setup(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "0x%02x\n", chip->filter_rate_setup); +} + +static ssize_t ad7152_store_filter_rate_setup(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x100)) { + ad7152_i2c_write(chip, AD7152_CFG2, data); + chip->filter_rate_setup = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_FILTER_RATE_SETUP(S_IRUGO | S_IWUSR, + ad7152_show_filter_rate_setup, + ad7152_store_filter_rate_setup); + +static ssize_t ad7152_show_name(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7152_chip_info *chip = dev_info->dev_data; + return sprintf(buf, "%s\n", chip->name); +} + +static IIO_DEVICE_ATTR(name, S_IRUGO, ad7152_show_name, NULL, 0); + +static struct attribute *ad7152_attributes[] = { + &iio_dev_attr_available_conversion_modes.dev_attr.attr, + &iio_dev_attr_conversion_mode.dev_attr.attr, + &iio_dev_attr_ch1_gain.dev_attr.attr, + &iio_dev_attr_ch2_gain.dev_attr.attr, + &iio_dev_attr_ch1_offset.dev_attr.attr, + &iio_dev_attr_ch2_offset.dev_attr.attr, + &iio_dev_attr_ch1_value.dev_attr.attr, + &iio_dev_attr_ch2_value.dev_attr.attr, + &iio_dev_attr_ch1_setup.dev_attr.attr, + &iio_dev_attr_ch2_setup.dev_attr.attr, + &iio_dev_attr_filter_rate_setup.dev_attr.attr, + &iio_dev_attr_name.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad7152_attribute_group = { + .attrs = ad7152_attributes, +}; + +/* + * device probe and remove + */ + +static int __devinit ad7152_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret = 0; + struct ad7152_chip_info *chip = kzalloc(sizeof(*chip), GFP_KERNEL); + if (chip == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + /* this is only used for device removal purposes */ + i2c_set_clientdata(client, chip); + + chip->client = client; + chip->name = id->name; + + chip->indio_dev = iio_allocate_device(); + if (chip->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_chip; + } + + /* Echipabilish that the iio_dev is a child of the i2c device */ + chip->indio_dev->dev.parent = &client->dev; + chip->indio_dev->attrs = &ad7152_attribute_group; + chip->indio_dev->dev_data = (void *)(chip); + chip->indio_dev->driver_module = THIS_MODULE; + chip->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(chip->indio_dev); + if (ret) + goto error_free_dev; + + dev_err(&client->dev, "%s capacitive sensor registered\n", id->name); + + return 0; + +error_free_dev: + iio_free_device(chip->indio_dev); +error_free_chip: + kfree(chip); +error_ret: + return ret; +} + +static int __devexit ad7152_remove(struct i2c_client *client) +{ + struct ad7152_chip_info *chip = i2c_get_clientdata(client); + struct iio_dev *indio_dev = chip->indio_dev; + + if (client->irq && gpio_is_valid(irq_to_gpio(client->irq)) > 0) + iio_unregister_interrupt_line(indio_dev, 0); + iio_device_unregister(indio_dev); + kfree(chip); + + return 0; +} + +static const struct i2c_device_id ad7152_id[] = { + { "ad7152", 0 }, + { "ad7153", 0 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, ad7152_id); + +static struct i2c_driver ad7152_driver = { + .driver = { + .name = "ad7152", + }, + .probe = ad7152_probe, + .remove = __devexit_p(ad7152_remove), + .id_table = ad7152_id, +}; + +static __init int ad7152_init(void) +{ + return i2c_add_driver(&ad7152_driver); +} + +static __exit void ad7152_exit(void) +{ + i2c_del_driver(&ad7152_driver); +} + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices ad7152/3 capacitive sensor driver"); +MODULE_LICENSE("GPL v2"); + +module_init(ad7152_init); +module_exit(ad7152_exit); diff --git a/trunk/drivers/staging/iio/adc/ad7291.c b/trunk/drivers/staging/iio/adc/ad7291.c new file mode 100644 index 000000000000..34041a72aa52 --- /dev/null +++ b/trunk/drivers/staging/iio/adc/ad7291.c @@ -0,0 +1,1039 @@ +/* + * AD7291 digital temperature sensor driver supporting AD7291 + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +/* + * AD7291 registers definition + */ +#define AD7291_COMMAND 0 +#define AD7291_VOLTAGE 1 +#define AD7291_T_SENSE 2 +#define AD7291_T_AVERAGE 3 +#define AD7291_VOLTAGE_LIMIT_BASE 4 +#define AD7291_VOLTAGE_LIMIT_COUNT 8 +#define AD7291_T_SENSE_HIGH 0x1c +#define AD7291_T_SENSE_LOW 0x1d +#define AD7291_T_SENSE_HYST 0x1e +#define AD7291_VOLTAGE_ALERT_STATUS 0x1f +#define AD7291_T_ALERT_STATUS 0x20 + +/* + * AD7291 command + */ +#define AD7291_AUTOCYCLE 0x1 +#define AD7291_RESET 0x2 +#define AD7291_ALART_CLEAR 0x4 +#define AD7291_ALART_POLARITY 0x8 +#define AD7291_EXT_REF 0x10 +#define AD7291_NOISE_DELAY 0x20 +#define AD7291_T_SENSE_MASK 0x40 +#define AD7291_VOLTAGE_MASK 0xff00 +#define AD7291_VOLTAGE_OFFSET 0x8 + +/* + * AD7291 value masks + */ +#define AD7291_CHANNEL_MASK 0xf000 +#define AD7291_VALUE_MASK 0xfff +#define AD7291_T_VALUE_SIGN 0x400 +#define AD7291_T_VALUE_FLOAT_OFFSET 2 +#define AD7291_T_VALUE_FLOAT_MASK 0x2 + +/* + * struct ad7291_chip_info - chip specifc information + */ + +struct ad7291_chip_info { + const char *name; + struct i2c_client *client; + struct iio_dev *indio_dev; + struct work_struct thresh_work; + s64 last_timestamp; + u16 command; + u8 channels; /* Active voltage channels */ +}; + +/* + * struct ad7291_chip_info - chip specifc information + */ + +struct ad7291_limit_regs { + u16 data_high; + u16 data_low; + u16 hysteresis; +}; + +/* + * ad7291 register access by I2C + */ +static int ad7291_i2c_read(struct ad7291_chip_info *chip, u8 reg, u16 *data) +{ + struct i2c_client *client = chip->client; + int ret = 0; + + ret = i2c_smbus_read_word_data(client, reg); + if (ret < 0) { + dev_err(&client->dev, "I2C read error\n"); + return ret; + } + + *data = swab16((u16)ret); + + return 0; +} + +static int ad7291_i2c_write(struct ad7291_chip_info *chip, u8 reg, u16 data) +{ + struct i2c_client *client = chip->client; + int ret = 0; + + ret = i2c_smbus_write_word_data(client, reg, swab16(data)); + if (ret < 0) + dev_err(&client->dev, "I2C write error\n"); + + return ret; +} + +/* Returns negative errno, or else the number of words read. */ +static int ad7291_i2c_read_data(struct ad7291_chip_info *chip, u8 reg, u16 *data) +{ + struct i2c_client *client = chip->client; + u8 commands[4]; + int ret = 0; + int i, count; + + if (reg == AD7291_T_SENSE || reg == AD7291_T_AVERAGE) + count = 2; + else if (reg == AD7291_VOLTAGE) { + if (!chip->channels) { + dev_err(&client->dev, "No voltage channel is selected.\n"); + return -EINVAL; + } + count = 2 + chip->channels * 2; + } else { + dev_err(&client->dev, "I2C wrong data register\n"); + return -EINVAL; + } + + commands[0] = 0; + commands[1] = (chip->command >> 8) & 0xff; + commands[2] = chip->command & 0xff; + commands[3] = reg; + + ret = i2c_master_send(client, commands, 4); + if (ret < 0) { + dev_err(&client->dev, "I2C master send error\n"); + return ret; + } + + ret = i2c_master_recv(client, (u8 *)data, count); + if (ret < 0) { + dev_err(&client->dev, "I2C master receive error\n"); + return ret; + } + ret >>= 2; + + for (i = 0; i < ret; i++) + data[i] = swab16(data[i]); + + return ret; +} + +static ssize_t ad7291_show_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7291_chip_info *chip = dev_info->dev_data; + + if (chip->command & AD7291_AUTOCYCLE) + return sprintf(buf, "autocycle\n"); + else + return sprintf(buf, "command\n"); +} + +static ssize_t ad7291_store_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7291_chip_info *chip = dev_info->dev_data; + u16 command; + int ret; + + command = chip->command & (~AD7291_AUTOCYCLE); + if (strcmp(buf, "autocycle")) + command |= AD7291_AUTOCYCLE; + + ret = ad7291_i2c_write(chip, AD7291_COMMAND, command); + if (ret) + return -EIO; + + chip->command = command; + + return ret; +} + +static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, + ad7291_show_mode, + ad7291_store_mode, + 0); + +static ssize_t ad7291_show_available_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "command\nautocycle\n"); +} + +static IIO_DEVICE_ATTR(available_modes, S_IRUGO, ad7291_show_available_modes, NULL, 0); + +static ssize_t ad7291_store_reset(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7291_chip_info *chip = dev_info->dev_data; + u16 command; + int ret; + + command = chip->command | AD7291_RESET; + + ret = ad7291_i2c_write(chip, AD7291_COMMAND, command); + if (ret) + return -EIO; + + return ret; +} + +static IIO_DEVICE_ATTR(reset, S_IWUSR, + NULL, + ad7291_store_reset, + 0); + +static ssize_t ad7291_show_ext_ref(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7291_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", !!(chip->command & AD7291_EXT_REF)); +} + +static ssize_t ad7291_store_ext_ref(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7291_chip_info *chip = dev_info->dev_data; + u16 command; + int ret; + + command = chip->command & (~AD7291_EXT_REF); + if (strcmp(buf, "1")) + command |= AD7291_EXT_REF; + + ret = ad7291_i2c_write(chip, AD7291_COMMAND, command); + if (ret) + return -EIO; + + chip->command = command; + + return ret; +} + +static IIO_DEVICE_ATTR(ext_ref, S_IRUGO | S_IWUSR, + ad7291_show_ext_ref, + ad7291_store_ext_ref, + 0); + +static ssize_t ad7291_show_noise_delay(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7291_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", !!(chip->command & AD7291_NOISE_DELAY)); +} + +static ssize_t ad7291_store_noise_delay(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7291_chip_info *chip = dev_info->dev_data; + u16 command; + int ret; + + command = chip->command & (~AD7291_NOISE_DELAY); + if (strcmp(buf, "1")) + command |= AD7291_NOISE_DELAY; + + ret = ad7291_i2c_write(chip, AD7291_COMMAND, command); + if (ret) + return -EIO; + + chip->command = command; + + return ret; +} + +static IIO_DEVICE_ATTR(noise_delay, S_IRUGO | S_IWUSR, + ad7291_show_noise_delay, + ad7291_store_noise_delay, + 0); + +static ssize_t ad7291_show_t_sense(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7291_chip_info *chip = dev_info->dev_data; + u16 data; + char sign = ' '; + int ret; + + ret = ad7291_i2c_read_data(chip, AD7291_T_SENSE, &data); + if (ret) + return -EIO; + + if (data & AD7291_T_VALUE_SIGN) { + /* convert supplement to positive value */ + data = (AD7291_T_VALUE_SIGN << 1) - data; + sign = '-'; + } + + return sprintf(buf, "%c%d.%.2d\n", sign, + (data >> AD7291_T_VALUE_FLOAT_OFFSET), + (data & AD7291_T_VALUE_FLOAT_MASK) * 25); +} + +static IIO_DEVICE_ATTR(t_sense, S_IRUGO, ad7291_show_t_sense, NULL, 0); + +static ssize_t ad7291_show_t_average(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7291_chip_info *chip = dev_info->dev_data; + u16 data; + char sign = ' '; + int ret; + + ret = ad7291_i2c_read_data(chip, AD7291_T_AVERAGE, &data); + if (ret) + return -EIO; + + if (data & AD7291_T_VALUE_SIGN) { + /* convert supplement to positive value */ + data = (AD7291_T_VALUE_SIGN << 1) - data; + sign = '-'; + } + + return sprintf(buf, "%c%d.%.2d\n", sign, + (data >> AD7291_T_VALUE_FLOAT_OFFSET), + (data & AD7291_T_VALUE_FLOAT_MASK) * 25); +} + +static IIO_DEVICE_ATTR(t_average, S_IRUGO, ad7291_show_t_average, NULL, 0); + +static ssize_t ad7291_show_voltage(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7291_chip_info *chip = dev_info->dev_data; + u16 data[AD7291_VOLTAGE_LIMIT_COUNT]; + int i, size, ret; + + ret = ad7291_i2c_read_data(chip, AD7291_VOLTAGE, data); + if (ret) + return -EIO; + + for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT; i++) { + if (chip->command & (AD7291_T_SENSE_MASK << i)) { + ret = sprintf(buf, "channel[%d]=%d\n", i, + data[i] & AD7291_VALUE_MASK); + if (ret < 0) + break; + buf += ret; + size += ret; + } + } + + return size; +} + +static IIO_DEVICE_ATTR(voltage, S_IRUGO, ad7291_show_voltage, NULL, 0); + +static ssize_t ad7291_show_channel_mask(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7291_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "0x%x\n", (chip->command & AD7291_VOLTAGE_MASK) >> + AD7291_VOLTAGE_OFFSET); +} + +static ssize_t ad7291_store_channel_mask(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7291_chip_info *chip = dev_info->dev_data; + u16 command; + unsigned long data; + int i, ret; + + ret = strict_strtoul(buf, 16, &data); + if (ret || data > 0xff) + return -EINVAL; + + command = chip->command & (~AD7291_VOLTAGE_MASK); + command |= data << AD7291_VOLTAGE_OFFSET; + + ret = ad7291_i2c_write(chip, AD7291_COMMAND, command); + if (ret) + return -EIO; + + chip->command = command; + + for (i = 0, chip->channels = 0; i < AD7291_VOLTAGE_LIMIT_COUNT; i++) { + if (chip->command & (AD7291_T_SENSE_MASK << i)) + chip->channels++; + } + + return ret; +} + +static IIO_DEVICE_ATTR(channel_mask, S_IRUGO | S_IWUSR, + ad7291_show_channel_mask, + ad7291_store_channel_mask, + 0); + +static ssize_t ad7291_show_name(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7291_chip_info *chip = dev_info->dev_data; + return sprintf(buf, "%s\n", chip->name); +} + +static IIO_DEVICE_ATTR(name, S_IRUGO, ad7291_show_name, NULL, 0); + +static struct attribute *ad7291_attributes[] = { + &iio_dev_attr_available_modes.dev_attr.attr, + &iio_dev_attr_mode.dev_attr.attr, + &iio_dev_attr_reset.dev_attr.attr, + &iio_dev_attr_ext_ref.dev_attr.attr, + &iio_dev_attr_noise_delay.dev_attr.attr, + &iio_dev_attr_t_sense.dev_attr.attr, + &iio_dev_attr_t_average.dev_attr.attr, + &iio_dev_attr_voltage.dev_attr.attr, + &iio_dev_attr_channel_mask.dev_attr.attr, + &iio_dev_attr_name.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad7291_attribute_group = { + .attrs = ad7291_attributes, +}; + +/* + * temperature bound events + */ + +#define IIO_EVENT_CODE_AD7291_T_SENSE_HIGH IIO_BUFFER_EVENT_CODE(0) +#define IIO_EVENT_CODE_AD7291_T_SENSE_LOW IIO_BUFFER_EVENT_CODE(1) +#define IIO_EVENT_CODE_AD7291_T_AVG_HIGH IIO_BUFFER_EVENT_CODE(2) +#define IIO_EVENT_CODE_AD7291_T_AVG_LOW IIO_BUFFER_EVENT_CODE(3) +#define IIO_EVENT_CODE_AD7291_VOLTAGE_BASE IIO_BUFFER_EVENT_CODE(4) + +static void ad7291_interrupt_bh(struct work_struct *work_s) +{ + struct ad7291_chip_info *chip = + container_of(work_s, struct ad7291_chip_info, thresh_work); + u16 t_status, v_status; + u16 command; + int i; + + if (ad7291_i2c_read(chip, AD7291_T_ALERT_STATUS, &t_status)) + return; + + if (ad7291_i2c_read(chip, AD7291_VOLTAGE_ALERT_STATUS, &v_status)) + return; + + if (!(t_status || v_status)) + return; + + command = chip->command | AD7291_ALART_CLEAR; + ad7291_i2c_write(chip, AD7291_COMMAND, command); + + command = chip->command & ~AD7291_ALART_CLEAR; + ad7291_i2c_write(chip, AD7291_COMMAND, command); + + enable_irq(chip->client->irq); + + for (i = 0; i < 4; i++) { + if (t_status & (1 << i)) + iio_push_event(chip->indio_dev, 0, + IIO_EVENT_CODE_AD7291_T_SENSE_HIGH + i, + chip->last_timestamp); + } + + for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT*2; i++) { + if (v_status & (1 << i)) + iio_push_event(chip->indio_dev, 0, + IIO_EVENT_CODE_AD7291_VOLTAGE_BASE + i, + chip->last_timestamp); + } +} + +static int ad7291_interrupt(struct iio_dev *dev_info, + int index, + s64 timestamp, + int no_test) +{ + struct ad7291_chip_info *chip = dev_info->dev_data; + + chip->last_timestamp = timestamp; + schedule_work(&chip->thresh_work); + + return 0; +} + +IIO_EVENT_SH(ad7291, &ad7291_interrupt); + +static inline ssize_t ad7291_show_t_bound(struct device *dev, + struct device_attribute *attr, + u8 bound_reg, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7291_chip_info *chip = dev_info->dev_data; + u16 data; + char sign = ' '; + int ret; + + ret = ad7291_i2c_read(chip, bound_reg, &data); + if (ret) + return -EIO; + + data &= AD7291_VALUE_MASK; + if (data & AD7291_T_VALUE_SIGN) { + /* convert supplement to positive value */ + data = (AD7291_T_VALUE_SIGN << 1) - data; + sign = '-'; + } + + return sprintf(buf, "%c%d.%.2d\n", sign, + data >> AD7291_T_VALUE_FLOAT_OFFSET, + (data & AD7291_T_VALUE_FLOAT_MASK) * 25); +} + +static inline ssize_t ad7291_set_t_bound(struct device *dev, + struct device_attribute *attr, + u8 bound_reg, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7291_chip_info *chip = dev_info->dev_data; + long tmp1, tmp2; + u16 data; + char *pos; + int ret; + + pos = strchr(buf, '.'); + + ret = strict_strtol(buf, 10, &tmp1); + + if (ret || tmp1 > 127 || tmp1 < -128) + return -EINVAL; + + if (pos) { + len = strlen(pos); + if (len > AD7291_T_VALUE_FLOAT_OFFSET) + len = AD7291_T_VALUE_FLOAT_OFFSET; + pos[len] = 0; + ret = strict_strtol(pos, 10, &tmp2); + + if (!ret) + tmp2 = (tmp2 / 25) * 25; + } + + if (tmp1 < 0) + data = (u16)(-tmp1); + else + data = (u16)tmp1; + data = (data << AD7291_T_VALUE_FLOAT_OFFSET) | + (tmp2 & AD7291_T_VALUE_FLOAT_MASK); + if (tmp1 < 0) + /* convert positive value to supplyment */ + data = (AD7291_T_VALUE_SIGN << 1) - data; + + ret = ad7291_i2c_write(chip, bound_reg, data); + if (ret) + return -EIO; + + return ret; +} + +static ssize_t ad7291_show_t_sense_high(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return ad7291_show_t_bound(dev, attr, + AD7291_T_SENSE_HIGH, buf); +} + +static inline ssize_t ad7291_set_t_sense_high(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return ad7291_set_t_bound(dev, attr, + AD7291_T_SENSE_HIGH, buf, len); +} + +static ssize_t ad7291_show_t_sense_low(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return ad7291_show_t_bound(dev, attr, + AD7291_T_SENSE_LOW, buf); +} + +static inline ssize_t ad7291_set_t_sense_low(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return ad7291_set_t_bound(dev, attr, + AD7291_T_SENSE_LOW, buf, len); +} + +static ssize_t ad7291_show_t_sense_hyst(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return ad7291_show_t_bound(dev, attr, + AD7291_T_SENSE_HYST, buf); +} + +static inline ssize_t ad7291_set_t_sense_hyst(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return ad7291_set_t_bound(dev, attr, + AD7291_T_SENSE_HYST, buf, len); +} + +static inline ssize_t ad7291_show_v_bound(struct device *dev, + struct device_attribute *attr, + u8 bound_reg, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7291_chip_info *chip = dev_info->dev_data; + u16 data; + int ret; + + if (bound_reg < AD7291_VOLTAGE_LIMIT_BASE || + bound_reg >= AD7291_VOLTAGE_LIMIT_BASE + + AD7291_VOLTAGE_LIMIT_COUNT) + return -EINVAL; + + ret = ad7291_i2c_read(chip, bound_reg, &data); + if (ret) + return -EIO; + + data &= AD7291_VALUE_MASK; + + return sprintf(buf, "%d\n", data); +} + +static inline ssize_t ad7291_set_v_bound(struct device *dev, + struct device_attribute *attr, + u8 bound_reg, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7291_chip_info *chip = dev_info->dev_data; + unsigned long value; + u16 data; + int ret; + + if (bound_reg < AD7291_VOLTAGE_LIMIT_BASE || + bound_reg >= AD7291_VOLTAGE_LIMIT_BASE + + AD7291_VOLTAGE_LIMIT_COUNT) + return -EINVAL; + + ret = strict_strtoul(buf, 10, &value); + + if (ret || value >= 4096) + return -EINVAL; + + data = (u16)value; + ret = ad7291_i2c_write(chip, bound_reg, data); + if (ret) + return -EIO; + + return ret; +} + +static int ad7291_get_voltage_limit_regs(const char *channel) +{ + int index; + + if (strlen(channel) < 3 && channel[0] != 'v') + return -EINVAL; + + index = channel[1] - '0'; + if (index >= AD7291_VOLTAGE_LIMIT_COUNT) + return -EINVAL; + + return index; +} + +static ssize_t ad7291_show_voltage_high(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int regs; + + regs = ad7291_get_voltage_limit_regs(attr->attr.name); + + if (regs < 0) + return regs; + + return ad7291_show_t_bound(dev, attr, regs, buf); +} + +static inline ssize_t ad7291_set_voltage_high(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + int regs; + + regs = ad7291_get_voltage_limit_regs(attr->attr.name); + + if (regs < 0) + return regs; + + return ad7291_set_t_bound(dev, attr, regs, buf, len); +} + +static ssize_t ad7291_show_voltage_low(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int regs; + + regs = ad7291_get_voltage_limit_regs(attr->attr.name); + + if (regs < 0) + return regs; + + return ad7291_show_t_bound(dev, attr, regs+1, buf); +} + +static inline ssize_t ad7291_set_voltage_low(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + int regs; + + regs = ad7291_get_voltage_limit_regs(attr->attr.name); + + if (regs < 0) + return regs; + + return ad7291_set_t_bound(dev, attr, regs+1, buf, len); +} + +static ssize_t ad7291_show_voltage_hyst(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int regs; + + regs = ad7291_get_voltage_limit_regs(attr->attr.name); + + if (regs < 0) + return regs; + + return ad7291_show_t_bound(dev, attr, regs+2, buf); +} + +static inline ssize_t ad7291_set_voltage_hyst(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + int regs; + + regs = ad7291_get_voltage_limit_regs(attr->attr.name); + + if (regs < 0) + return regs; + + return ad7291_set_t_bound(dev, attr, regs+2, buf, len); +} + +IIO_EVENT_ATTR_SH(t_sense_high, iio_event_ad7291, + ad7291_show_t_sense_high, ad7291_set_t_sense_high, 0); +IIO_EVENT_ATTR_SH(t_sense_low, iio_event_ad7291, + ad7291_show_t_sense_low, ad7291_set_t_sense_low, 0); +IIO_EVENT_ATTR_SH(t_sense_hyst, iio_event_ad7291, + ad7291_show_t_sense_hyst, ad7291_set_t_sense_hyst, 0); + +IIO_EVENT_ATTR_SH(v0_high, iio_event_ad7291, + ad7291_show_voltage_high, ad7291_set_voltage_high, 0); +IIO_EVENT_ATTR_SH(v0_low, iio_event_ad7291, + ad7291_show_voltage_low, ad7291_set_voltage_low, 0); +IIO_EVENT_ATTR_SH(v0_hyst, iio_event_ad7291, + ad7291_show_voltage_hyst, ad7291_set_voltage_hyst, 0); +IIO_EVENT_ATTR_SH(v1_high, iio_event_ad7291, + ad7291_show_voltage_high, ad7291_set_voltage_high, 0); +IIO_EVENT_ATTR_SH(v1_low, iio_event_ad7291, + ad7291_show_voltage_low, ad7291_set_voltage_low, 0); +IIO_EVENT_ATTR_SH(v1_hyst, iio_event_ad7291, + ad7291_show_voltage_hyst, ad7291_set_voltage_hyst, 0); +IIO_EVENT_ATTR_SH(v2_high, iio_event_ad7291, + ad7291_show_voltage_high, ad7291_set_voltage_high, 0); +IIO_EVENT_ATTR_SH(v2_low, iio_event_ad7291, + ad7291_show_voltage_low, ad7291_set_voltage_low, 0); +IIO_EVENT_ATTR_SH(v2_hyst, iio_event_ad7291, + ad7291_show_voltage_hyst, ad7291_set_voltage_hyst, 0); +IIO_EVENT_ATTR_SH(v3_high, iio_event_ad7291, + ad7291_show_voltage_high, ad7291_set_voltage_high, 0); +IIO_EVENT_ATTR_SH(v3_low, iio_event_ad7291, + ad7291_show_voltage_low, ad7291_set_voltage_low, 0); +IIO_EVENT_ATTR_SH(v3_hyst, iio_event_ad7291, + ad7291_show_voltage_hyst, ad7291_set_voltage_hyst, 0); +IIO_EVENT_ATTR_SH(v4_high, iio_event_ad7291, + ad7291_show_voltage_high, ad7291_set_voltage_high, 0); +IIO_EVENT_ATTR_SH(v4_low, iio_event_ad7291, + ad7291_show_voltage_low, ad7291_set_voltage_low, 0); +IIO_EVENT_ATTR_SH(v4_hyst, iio_event_ad7291, + ad7291_show_voltage_hyst, ad7291_set_voltage_hyst, 0); +IIO_EVENT_ATTR_SH(v5_high, iio_event_ad7291, + ad7291_show_voltage_high, ad7291_set_voltage_high, 0); +IIO_EVENT_ATTR_SH(v5_low, iio_event_ad7291, + ad7291_show_voltage_low, ad7291_set_voltage_low, 0); +IIO_EVENT_ATTR_SH(v5_hyst, iio_event_ad7291, + ad7291_show_voltage_hyst, ad7291_set_voltage_hyst, 0); +IIO_EVENT_ATTR_SH(v6_high, iio_event_ad7291, + ad7291_show_voltage_high, ad7291_set_voltage_high, 0); +IIO_EVENT_ATTR_SH(v6_low, iio_event_ad7291, + ad7291_show_voltage_low, ad7291_set_voltage_low, 0); +IIO_EVENT_ATTR_SH(v6_hyst, iio_event_ad7291, + ad7291_show_voltage_hyst, ad7291_set_voltage_hyst, 0); +IIO_EVENT_ATTR_SH(v7_high, iio_event_ad7291, + ad7291_show_voltage_high, ad7291_set_voltage_high, 0); +IIO_EVENT_ATTR_SH(v7_low, iio_event_ad7291, + ad7291_show_voltage_low, ad7291_set_voltage_low, 0); +IIO_EVENT_ATTR_SH(v7_hyst, iio_event_ad7291, + ad7291_show_voltage_hyst, ad7291_set_voltage_hyst, 0); + +static struct attribute *ad7291_event_attributes[] = { + &iio_event_attr_t_sense_high.dev_attr.attr, + &iio_event_attr_t_sense_low.dev_attr.attr, + &iio_event_attr_t_sense_hyst.dev_attr.attr, + &iio_event_attr_v0_high.dev_attr.attr, + &iio_event_attr_v0_low.dev_attr.attr, + &iio_event_attr_v0_hyst.dev_attr.attr, + &iio_event_attr_v1_high.dev_attr.attr, + &iio_event_attr_v1_low.dev_attr.attr, + &iio_event_attr_v1_hyst.dev_attr.attr, + &iio_event_attr_v2_high.dev_attr.attr, + &iio_event_attr_v2_low.dev_attr.attr, + &iio_event_attr_v2_hyst.dev_attr.attr, + &iio_event_attr_v3_high.dev_attr.attr, + &iio_event_attr_v3_low.dev_attr.attr, + &iio_event_attr_v3_hyst.dev_attr.attr, + &iio_event_attr_v4_high.dev_attr.attr, + &iio_event_attr_v4_low.dev_attr.attr, + &iio_event_attr_v4_hyst.dev_attr.attr, + &iio_event_attr_v5_high.dev_attr.attr, + &iio_event_attr_v5_low.dev_attr.attr, + &iio_event_attr_v5_hyst.dev_attr.attr, + &iio_event_attr_v6_high.dev_attr.attr, + &iio_event_attr_v6_low.dev_attr.attr, + &iio_event_attr_v6_hyst.dev_attr.attr, + &iio_event_attr_v7_high.dev_attr.attr, + &iio_event_attr_v7_low.dev_attr.attr, + &iio_event_attr_v7_hyst.dev_attr.attr, + NULL, +}; + +static struct attribute_group ad7291_event_attribute_group = { + .attrs = ad7291_event_attributes, +}; + +/* + * device probe and remove + */ + +static int __devinit ad7291_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct ad7291_chip_info *chip; + int ret = 0; + + chip = kzalloc(sizeof(struct ad7291_chip_info), GFP_KERNEL); + + if (chip == NULL) + return -ENOMEM; + + /* this is only used for device removal purposes */ + i2c_set_clientdata(client, chip); + + chip->client = client; + chip->name = id->name; + chip->command = AD7291_NOISE_DELAY | AD7291_T_SENSE_MASK; + + chip->indio_dev = iio_allocate_device(); + if (chip->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_chip; + } + + chip->indio_dev->dev.parent = &client->dev; + chip->indio_dev->attrs = &ad7291_attribute_group; + chip->indio_dev->event_attrs = &ad7291_event_attribute_group; + chip->indio_dev->dev_data = (void *)chip; + chip->indio_dev->driver_module = THIS_MODULE; + chip->indio_dev->num_interrupt_lines = 1; + chip->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(chip->indio_dev); + if (ret) + goto error_free_dev; + + if (client->irq > 0) { + ret = iio_register_interrupt_line(client->irq, + chip->indio_dev, + 0, + IRQF_TRIGGER_LOW, + chip->name); + if (ret) + goto error_unreg_dev; + + /* + * The event handler list element refer to iio_event_ad7291. + * All event attributes bind to the same event handler. + * So, only register event handler once. + */ + iio_add_event_to_list(&iio_event_ad7291, + &chip->indio_dev->interrupts[0]->ev_list); + + INIT_WORK(&chip->thresh_work, ad7291_interrupt_bh); + + /* set irq polarity low level */ + chip->command |= AD7291_ALART_POLARITY; + } + + ret = ad7291_i2c_write(chip, AD7291_COMMAND, chip->command); + if (ret) { + ret = -EIO; + goto error_unreg_irq; + } + + dev_info(&client->dev, "%s temperature sensor registered.\n", + id->name); + + return 0; + +error_unreg_irq: + iio_unregister_interrupt_line(chip->indio_dev, 0); +error_unreg_dev: + iio_device_unregister(chip->indio_dev); +error_free_dev: + iio_free_device(chip->indio_dev); +error_free_chip: + kfree(chip); + + return ret; +} + +static int __devexit ad7291_remove(struct i2c_client *client) +{ + struct ad7291_chip_info *chip = i2c_get_clientdata(client); + struct iio_dev *indio_dev = chip->indio_dev; + + if (client->irq) + iio_unregister_interrupt_line(indio_dev, 0); + iio_device_unregister(indio_dev); + iio_free_device(chip->indio_dev); + kfree(chip); + + return 0; +} + +static const struct i2c_device_id ad7291_id[] = { + { "ad7291", 0 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, ad7291_id); + +static struct i2c_driver ad7291_driver = { + .driver = { + .name = "ad7291", + }, + .probe = ad7291_probe, + .remove = __devexit_p(ad7291_remove), + .id_table = ad7291_id, +}; + +static __init int ad7291_init(void) +{ + return i2c_add_driver(&ad7291_driver); +} + +static __exit void ad7291_exit(void) +{ + i2c_del_driver(&ad7291_driver); +} + +MODULE_AUTHOR("Sonic Zhang "); +MODULE_DESCRIPTION("Analog Devices AD7291 digital" + " temperature sensor driver"); +MODULE_LICENSE("GPL v2"); + +module_init(ad7291_init); +module_exit(ad7291_exit); diff --git a/trunk/drivers/staging/iio/adc/ad7298.c b/trunk/drivers/staging/iio/adc/ad7298.c new file mode 100644 index 000000000000..1a080c977637 --- /dev/null +++ b/trunk/drivers/staging/iio/adc/ad7298.c @@ -0,0 +1,501 @@ +/* + * AD7298 digital temperature sensor driver supporting AD7298 + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +/* + * AD7298 command + */ +#define AD7298_PD 0x1 +#define AD7298_T_AVG_MASK 0x2 +#define AD7298_EXT_REF 0x4 +#define AD7298_T_SENSE_MASK 0x20 +#define AD7298_VOLTAGE_MASK 0x3fc0 +#define AD7298_VOLTAGE_OFFSET 0x6 +#define AD7298_VOLTAGE_LIMIT_COUNT 8 +#define AD7298_REPEAT 0x40 +#define AD7298_WRITE 0x80 + +/* + * AD7298 value masks + */ +#define AD7298_CHANNEL_MASK 0xf000 +#define AD7298_VALUE_MASK 0xfff +#define AD7298_T_VALUE_SIGN 0x400 +#define AD7298_T_VALUE_FLOAT_OFFSET 2 +#define AD7298_T_VALUE_FLOAT_MASK 0x2 + +/* + * struct ad7298_chip_info - chip specifc information + */ + +struct ad7298_chip_info { + const char *name; + struct spi_device *spi_dev; + struct iio_dev *indio_dev; + u16 command; + u16 busy_pin; + u8 channels; /* Active voltage channels */ +}; + +/* + * ad7298 register access by SPI + */ +static int ad7298_spi_write(struct ad7298_chip_info *chip, u16 data) +{ + struct spi_device *spi_dev = chip->spi_dev; + int ret = 0; + + data |= AD7298_WRITE; + data = cpu_to_be16(data); + ret = spi_write(spi_dev, (u8 *)&data, sizeof(data)); + if (ret < 0) + dev_err(&spi_dev->dev, "SPI write error\n"); + + return ret; +} + +static int ad7298_spi_read(struct ad7298_chip_info *chip, u16 mask, u16 *data) +{ + struct spi_device *spi_dev = chip->spi_dev; + int ret = 0; + u8 count = chip->channels; + u16 command; + int i; + + if (mask & AD7298_T_SENSE_MASK) { + command = chip->command & ~(AD7298_T_AVG_MASK | AD7298_VOLTAGE_MASK); + command |= AD7298_T_SENSE_MASK; + count = 1; + } else if (mask & AD7298_T_AVG_MASK) { + command = chip->command & ~AD7298_VOLTAGE_MASK; + command |= AD7298_T_SENSE_MASK | AD7298_T_AVG_MASK; + count = 2; + } else if (mask & AD7298_VOLTAGE_MASK) { + command = chip->command & ~(AD7298_T_AVG_MASK | AD7298_T_SENSE_MASK); + count = chip->channels; + } + + ret = ad7298_spi_write(chip, chip->command); + if (ret < 0) { + dev_err(&spi_dev->dev, "SPI write command error\n"); + return ret; + } + + ret = spi_read(spi_dev, (u8 *)&command, sizeof(command)); + if (ret < 0) { + dev_err(&spi_dev->dev, "SPI read error\n"); + return ret; + } + + i = 10000; + while (i && gpio_get_value(chip->busy_pin)) { + cpu_relax(); + i--; + } + if (!i) { + dev_err(&spi_dev->dev, "Always in busy convertion.\n"); + return -EBUSY; + } + + for (i = 0; i < count; i++) { + ret = spi_read(spi_dev, (u8 *)&data[i], sizeof(data[i])); + if (ret < 0) { + dev_err(&spi_dev->dev, "SPI read error\n"); + return ret; + } + *data = be16_to_cpu(data[i]); + } + + return 0; +} + +static ssize_t ad7298_show_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7298_chip_info *chip = dev_info->dev_data; + + if (chip->command & AD7298_REPEAT) + return sprintf(buf, "repeat\n"); + else + return sprintf(buf, "normal\n"); +} + +static ssize_t ad7298_store_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7298_chip_info *chip = dev_info->dev_data; + + if (strcmp(buf, "repeat")) + chip->command |= AD7298_REPEAT; + else + chip->command &= (~AD7298_REPEAT); + + return 1; +} + +static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, + ad7298_show_mode, + ad7298_store_mode, + 0); + +static ssize_t ad7298_show_available_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "normal\nrepeat\n"); +} + +static IIO_DEVICE_ATTR(available_modes, S_IRUGO, ad7298_show_available_modes, NULL, 0); + +static ssize_t ad7298_store_reset(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7298_chip_info *chip = dev_info->dev_data; + u16 command; + int ret; + + command = chip->command & ~AD7298_PD; + + ret = ad7298_spi_write(chip, command); + if (ret) + return -EIO; + + command = chip->command | AD7298_PD; + + ret = ad7298_spi_write(chip, command); + if (ret) + return -EIO; + + return len; +} + +static IIO_DEVICE_ATTR(reset, S_IWUSR, + NULL, + ad7298_store_reset, + 0); + +static ssize_t ad7298_show_ext_ref(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7298_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", !!(chip->command & AD7298_EXT_REF)); +} + +static ssize_t ad7298_store_ext_ref(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7298_chip_info *chip = dev_info->dev_data; + u16 command; + int ret; + + command = chip->command & (~AD7298_EXT_REF); + if (strcmp(buf, "1")) + command |= AD7298_EXT_REF; + + ret = ad7298_spi_write(chip, command); + if (ret) + return -EIO; + + chip->command = command; + + return len; +} + +static IIO_DEVICE_ATTR(ext_ref, S_IRUGO | S_IWUSR, + ad7298_show_ext_ref, + ad7298_store_ext_ref, + 0); + +static ssize_t ad7298_show_t_sense(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7298_chip_info *chip = dev_info->dev_data; + u16 data; + char sign = ' '; + int ret; + + ret = ad7298_spi_read(chip, AD7298_T_SENSE_MASK, &data); + if (ret) + return -EIO; + + if (data & AD7298_T_VALUE_SIGN) { + /* convert supplement to positive value */ + data = (AD7298_T_VALUE_SIGN << 1) - data; + sign = '-'; + } + + return sprintf(buf, "%c%d.%.2d\n", sign, + (data >> AD7298_T_VALUE_FLOAT_OFFSET), + (data & AD7298_T_VALUE_FLOAT_MASK) * 25); +} + +static IIO_DEVICE_ATTR(t_sense, S_IRUGO, ad7298_show_t_sense, NULL, 0); + +static ssize_t ad7298_show_t_average(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7298_chip_info *chip = dev_info->dev_data; + u16 data[2]; + char sign = ' '; + int ret; + + ret = ad7298_spi_read(chip, AD7298_T_AVG_MASK, data); + if (ret) + return -EIO; + + if (data[1] & AD7298_T_VALUE_SIGN) { + /* convert supplement to positive value */ + data[1] = (AD7298_T_VALUE_SIGN << 1) - data[1]; + sign = '-'; + } + + return sprintf(buf, "%c%d.%.2d\n", sign, + (data[1] >> AD7298_T_VALUE_FLOAT_OFFSET), + (data[1] & AD7298_T_VALUE_FLOAT_MASK) * 25); +} + +static IIO_DEVICE_ATTR(t_average, S_IRUGO, ad7298_show_t_average, NULL, 0); + +static ssize_t ad7298_show_voltage(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7298_chip_info *chip = dev_info->dev_data; + u16 data[AD7298_VOLTAGE_LIMIT_COUNT]; + int i, size, ret; + + ret = ad7298_spi_read(chip, AD7298_VOLTAGE_MASK, data); + if (ret) + return -EIO; + + for (i = 0; i < AD7298_VOLTAGE_LIMIT_COUNT; i++) { + if (chip->command & (AD7298_T_SENSE_MASK << i)) { + ret = sprintf(buf, "channel[%d]=%d\n", i, + data[i] & AD7298_VALUE_MASK); + if (ret < 0) + break; + buf += ret; + size += ret; + } + } + + return size; +} + +static IIO_DEVICE_ATTR(voltage, S_IRUGO, ad7298_show_voltage, NULL, 0); + +static ssize_t ad7298_show_channel_mask(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7298_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "0x%x\n", (chip->command & AD7298_VOLTAGE_MASK) >> + AD7298_VOLTAGE_OFFSET); +} + +static ssize_t ad7298_store_channel_mask(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7298_chip_info *chip = dev_info->dev_data; + unsigned long data; + int i, ret; + + ret = strict_strtoul(buf, 16, &data); + if (ret || data > 0xff) + return -EINVAL; + + chip->command &= (~AD7298_VOLTAGE_MASK); + chip->command |= data << AD7298_VOLTAGE_OFFSET; + + for (i = 0, chip->channels = 0; i < AD7298_VOLTAGE_LIMIT_COUNT; i++) { + if (chip->command & (AD7298_T_SENSE_MASK << i)) + chip->channels++; + } + + return ret; +} + +static IIO_DEVICE_ATTR(channel_mask, S_IRUGO | S_IWUSR, + ad7298_show_channel_mask, + ad7298_store_channel_mask, + 0); + +static ssize_t ad7298_show_name(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7298_chip_info *chip = dev_info->dev_data; + return sprintf(buf, "%s\n", chip->name); +} + +static IIO_DEVICE_ATTR(name, S_IRUGO, ad7298_show_name, NULL, 0); + +static struct attribute *ad7298_attributes[] = { + &iio_dev_attr_available_modes.dev_attr.attr, + &iio_dev_attr_mode.dev_attr.attr, + &iio_dev_attr_reset.dev_attr.attr, + &iio_dev_attr_ext_ref.dev_attr.attr, + &iio_dev_attr_t_sense.dev_attr.attr, + &iio_dev_attr_t_average.dev_attr.attr, + &iio_dev_attr_voltage.dev_attr.attr, + &iio_dev_attr_channel_mask.dev_attr.attr, + &iio_dev_attr_name.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad7298_attribute_group = { + .attrs = ad7298_attributes, +}; + +/* + * device probe and remove + */ +static int __devinit ad7298_probe(struct spi_device *spi_dev) +{ + struct ad7298_chip_info *chip; + unsigned short *pins = spi_dev->dev.platform_data; + int ret = 0; + + chip = kzalloc(sizeof(struct ad7298_chip_info), GFP_KERNEL); + + if (chip == NULL) + return -ENOMEM; + + /* this is only used for device removal purposes */ + dev_set_drvdata(&spi_dev->dev, chip); + + chip->spi_dev = spi_dev; + chip->name = spi_dev->modalias; + chip->busy_pin = pins[0]; + + ret = gpio_request(chip->busy_pin, chip->name); + if (ret) { + dev_err(&spi_dev->dev, "Fail to request busy gpio PIN %d.\n", + chip->busy_pin); + goto error_free_chip; + } + gpio_direction_input(chip->busy_pin); + + chip->indio_dev = iio_allocate_device(); + if (chip->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_gpio; + } + + chip->indio_dev->dev.parent = &spi_dev->dev; + chip->indio_dev->attrs = &ad7298_attribute_group; + chip->indio_dev->dev_data = (void *)chip; + chip->indio_dev->driver_module = THIS_MODULE; + chip->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(chip->indio_dev); + if (ret) + goto error_free_dev; + + dev_info(&spi_dev->dev, "%s temperature sensor and ADC registered.\n", + chip->name); + + return 0; + +error_free_dev: + iio_free_device(chip->indio_dev); +error_free_gpio: + gpio_free(chip->busy_pin); +error_free_chip: + kfree(chip); + + return ret; +} + +static int __devexit ad7298_remove(struct spi_device *spi_dev) +{ + struct ad7298_chip_info *chip = dev_get_drvdata(&spi_dev->dev); + struct iio_dev *indio_dev = chip->indio_dev; + + dev_set_drvdata(&spi_dev->dev, NULL); + iio_device_unregister(indio_dev); + iio_free_device(chip->indio_dev); + gpio_free(chip->busy_pin); + kfree(chip); + + return 0; +} + +static const struct spi_device_id ad7298_id[] = { + { "ad7298", 0 }, + {} +}; + +MODULE_DEVICE_TABLE(spi, ad7298_id); + +static struct spi_driver ad7298_driver = { + .driver = { + .name = "ad7298", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = ad7298_probe, + .remove = __devexit_p(ad7298_remove), + .id_table = ad7298_id, +}; + +static __init int ad7298_init(void) +{ + return spi_register_driver(&ad7298_driver); +} + +static __exit void ad7298_exit(void) +{ + spi_unregister_driver(&ad7298_driver); +} + +MODULE_AUTHOR("Sonic Zhang "); +MODULE_DESCRIPTION("Analog Devices AD7298 digital" + " temperature sensor and ADC driver"); +MODULE_LICENSE("GPL v2"); + +module_init(ad7298_init); +module_exit(ad7298_exit); diff --git a/trunk/drivers/staging/iio/adc/ad7314.c b/trunk/drivers/staging/iio/adc/ad7314.c new file mode 100644 index 000000000000..8c17b1fe9026 --- /dev/null +++ b/trunk/drivers/staging/iio/adc/ad7314.c @@ -0,0 +1,308 @@ +/* + * AD7314 digital temperature sensor driver for AD7314, ADT7301 and ADT7302 + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +/* + * AD7314 power mode + */ +#define AD7314_PD 0x2000 + +/* + * AD7314 temperature masks + */ +#define AD7314_TEMP_SIGN 0x200 +#define AD7314_TEMP_MASK 0x7FE0 +#define AD7314_TEMP_OFFSET 5 +#define AD7314_TEMP_FLOAT_OFFSET 2 +#define AD7314_TEMP_FLOAT_MASK 0x3 + +/* + * ADT7301 and ADT7302 temperature masks + */ +#define ADT7301_TEMP_SIGN 0x2000 +#define ADT7301_TEMP_MASK 0x2FFF +#define ADT7301_TEMP_FLOAT_OFFSET 5 +#define ADT7301_TEMP_FLOAT_MASK 0x1F + +/* + * struct ad7314_chip_info - chip specifc information + */ + +struct ad7314_chip_info { + const char *name; + struct spi_device *spi_dev; + struct iio_dev *indio_dev; + s64 last_timestamp; + u8 mode; +}; + +/* + * ad7314 register access by SPI + */ + +static int ad7314_spi_read(struct ad7314_chip_info *chip, u16 *data) +{ + struct spi_device *spi_dev = chip->spi_dev; + int ret = 0; + u16 value; + + ret = spi_read(spi_dev, (u8 *)&value, sizeof(value)); + if (ret < 0) { + dev_err(&spi_dev->dev, "SPI read error\n"); + return ret; + } + + *data = be16_to_cpu((u16)value); + + return ret; +} + +static int ad7314_spi_write(struct ad7314_chip_info *chip, u16 data) +{ + struct spi_device *spi_dev = chip->spi_dev; + int ret = 0; + u16 value = cpu_to_be16(data); + + ret = spi_write(spi_dev, (u8 *)&value, sizeof(value)); + if (ret < 0) + dev_err(&spi_dev->dev, "SPI write error\n"); + + return ret; +} + +static ssize_t ad7314_show_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7314_chip_info *chip = dev_info->dev_data; + + if (chip->mode) + return sprintf(buf, "power-save\n"); + else + return sprintf(buf, "full\n"); +} + +static ssize_t ad7314_store_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7314_chip_info *chip = dev_info->dev_data; + u16 mode = 0; + int ret; + + if (!strcmp(buf, "full")) + mode = AD7314_PD; + + ret = ad7314_spi_write(chip, mode); + if (ret) + return -EIO; + + chip->mode = mode; + + return len; +} + +static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, + ad7314_show_mode, + ad7314_store_mode, + 0); + +static ssize_t ad7314_show_available_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "full\npower-save\n"); +} + +static IIO_DEVICE_ATTR(available_modes, S_IRUGO, ad7314_show_available_modes, NULL, 0); + +static ssize_t ad7314_show_temperature(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7314_chip_info *chip = dev_info->dev_data; + u16 data; + char sign = ' '; + int ret; + + if (chip->mode) { + ret = ad7314_spi_write(chip, 0); + if (ret) + return -EIO; + } + + ret = ad7314_spi_read(chip, &data); + if (ret) + return -EIO; + + if (chip->mode) + ad7314_spi_write(chip, chip->mode); + + if (strcmp(chip->name, "ad7314")) { + data = (data & AD7314_TEMP_MASK) >> + AD7314_TEMP_OFFSET; + if (data & AD7314_TEMP_SIGN) { + data = (AD7314_TEMP_SIGN << 1) - data; + sign = '-'; + } + + return sprintf(buf, "%c%d.%.2d\n", sign, + data >> AD7314_TEMP_FLOAT_OFFSET, + (data & AD7314_TEMP_FLOAT_MASK) * 25); + } else { + data &= ADT7301_TEMP_MASK; + if (data & ADT7301_TEMP_SIGN) { + data = (ADT7301_TEMP_SIGN << 1) - data; + sign = '-'; + } + + return sprintf(buf, "%c%d.%.5d\n", sign, + data >> ADT7301_TEMP_FLOAT_OFFSET, + (data & ADT7301_TEMP_FLOAT_MASK) * 3125); + } +} + +static IIO_DEVICE_ATTR(temperature, S_IRUGO, ad7314_show_temperature, NULL, 0); + +static ssize_t ad7314_show_name(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7314_chip_info *chip = dev_info->dev_data; + return sprintf(buf, "%s\n", chip->name); +} + +static IIO_DEVICE_ATTR(name, S_IRUGO, ad7314_show_name, NULL, 0); + +static struct attribute *ad7314_attributes[] = { + &iio_dev_attr_available_modes.dev_attr.attr, + &iio_dev_attr_mode.dev_attr.attr, + &iio_dev_attr_temperature.dev_attr.attr, + &iio_dev_attr_name.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad7314_attribute_group = { + .attrs = ad7314_attributes, +}; + +/* + * device probe and remove + */ + +static int __devinit ad7314_probe(struct spi_device *spi_dev) +{ + struct ad7314_chip_info *chip; + int ret = 0; + + chip = kzalloc(sizeof(struct ad7314_chip_info), GFP_KERNEL); + + if (chip == NULL) + return -ENOMEM; + + /* this is only used for device removal purposes */ + dev_set_drvdata(&spi_dev->dev, chip); + + chip->spi_dev = spi_dev; + chip->name = spi_dev->modalias; + + chip->indio_dev = iio_allocate_device(); + if (chip->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_chip; + } + + chip->indio_dev->dev.parent = &spi_dev->dev; + chip->indio_dev->attrs = &ad7314_attribute_group; + chip->indio_dev->dev_data = (void *)chip; + chip->indio_dev->driver_module = THIS_MODULE; + + ret = iio_device_register(chip->indio_dev); + if (ret) + goto error_free_dev; + + dev_info(&spi_dev->dev, "%s temperature sensor registered.\n", + chip->name); + + return 0; +error_free_dev: + iio_free_device(chip->indio_dev); +error_free_chip: + kfree(chip); + + return ret; +} + +static int __devexit ad7314_remove(struct spi_device *spi_dev) +{ + struct ad7314_chip_info *chip = dev_get_drvdata(&spi_dev->dev); + struct iio_dev *indio_dev = chip->indio_dev; + + dev_set_drvdata(&spi_dev->dev, NULL); + if (spi_dev->irq) + iio_unregister_interrupt_line(indio_dev, 0); + iio_device_unregister(indio_dev); + iio_free_device(chip->indio_dev); + kfree(chip); + + return 0; +} + +static const struct spi_device_id ad7314_id[] = { + { "adt7301", 0 }, + { "adt7302", 0 }, + { "ad7314", 0 }, + {} +}; + +static struct spi_driver ad7314_driver = { + .driver = { + .name = "ad7314", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = ad7314_probe, + .remove = __devexit_p(ad7314_remove), + .id_table = ad7314_id, +}; + +static __init int ad7314_init(void) +{ + return spi_register_driver(&ad7314_driver); +} + +static __exit void ad7314_exit(void) +{ + spi_unregister_driver(&ad7314_driver); +} + +MODULE_AUTHOR("Sonic Zhang "); +MODULE_DESCRIPTION("Analog Devices AD7314, ADT7301 and ADT7302 digital" + " temperature sensor driver"); +MODULE_LICENSE("GPL v2"); + +module_init(ad7314_init); +module_exit(ad7314_exit); diff --git a/trunk/drivers/staging/iio/adc/ad7745.c b/trunk/drivers/staging/iio/adc/ad7745.c new file mode 100644 index 000000000000..ab7ef8450ae2 --- /dev/null +++ b/trunk/drivers/staging/iio/adc/ad7745.c @@ -0,0 +1,734 @@ +/* + * AD774X capacitive sensor driver supporting AD7745/6/7 + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +/* + * AD774X registers definition + */ + +#define AD774X_STATUS 0 +#define AD774X_STATUS_RDY (1 << 2) +#define AD774X_STATUS_RDYVT (1 << 1) +#define AD774X_STATUS_RDYCAP (1 << 0) +#define AD774X_CAP_DATA_HIGH 1 +#define AD774X_CAP_DATA_MID 2 +#define AD774X_CAP_DATA_LOW 3 +#define AD774X_VT_DATA_HIGH 4 +#define AD774X_VT_DATA_MID 5 +#define AD774X_VT_DATA_LOW 6 +#define AD774X_CAP_SETUP 7 +#define AD774X_VT_SETUP 8 +#define AD774X_EXEC_SETUP 9 +#define AD774X_CFG 10 +#define AD774X_CAPDACA 11 +#define AD774X_CAPDACB 12 +#define AD774X_CAPDAC_EN (1 << 7) +#define AD774X_CAP_OFFH 13 +#define AD774X_CAP_OFFL 14 +#define AD774X_CAP_GAINH 15 +#define AD774X_CAP_GAINL 16 +#define AD774X_VOLT_GAINH 17 +#define AD774X_VOLT_GAINL 18 + +#define AD774X_MAX_CONV_MODE 6 + +/* + * struct ad774x_chip_info - chip specifc information + */ + +struct ad774x_chip_info { + const char *name; + struct i2c_client *client; + struct iio_dev *indio_dev; + struct work_struct thresh_work; + bool inter; + s64 last_timestamp; + u16 cap_offs; /* Capacitive offset */ + u16 cap_gain; /* Capacitive gain calibration */ + u16 volt_gain; /* Voltage gain calibration */ + u8 cap_setup; + u8 vt_setup; + u8 exec_setup; + + char *conversion_mode; +}; + +struct ad774x_conversion_mode { + char *name; + u8 reg_cfg; +}; + +struct ad774x_conversion_mode ad774x_conv_mode_table[AD774X_MAX_CONV_MODE] = { + { "idle", 0 }, + { "continuous-conversion", 1 }, + { "single-conversion", 2 }, + { "power-down", 3 }, + { "offset-calibration", 5 }, + { "gain-calibration", 6 }, +}; + +/* + * ad774x register access by I2C + */ + +static int ad774x_i2c_read(struct ad774x_chip_info *chip, u8 reg, u8 *data, int len) +{ + struct i2c_client *client = chip->client; + int ret; + + ret = i2c_master_send(client, ®, 1); + if (ret < 0) { + dev_err(&client->dev, "I2C write error\n"); + return ret; + } + + ret = i2c_master_recv(client, data, len); + if (ret < 0) { + dev_err(&client->dev, "I2C read error\n"); + return ret; + } + + return ret; +} + +static int ad774x_i2c_write(struct ad774x_chip_info *chip, u8 reg, u8 data) +{ + struct i2c_client *client = chip->client; + int ret; + + u8 tx[2] = { + reg, + data, + }; + + ret = i2c_master_send(client, tx, 2); + if (ret < 0) + dev_err(&client->dev, "I2C write error\n"); + + return ret; +} + +/* + * sysfs nodes + */ + +#define IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(_show) \ + IIO_DEVICE_ATTR(available_conversion_modes, S_IRUGO, _show, NULL, 0) +#define IIO_DEV_ATTR_CONVERSION_MODE(_mode, _show, _store) \ + IIO_DEVICE_ATTR(conversion_mode, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_CAP_SETUP(_mode, _show, _store) \ + IIO_DEVICE_ATTR(cap_setup, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_VT_SETUP(_mode, _show, _store) \ + IIO_DEVICE_ATTR(in0_setup, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_EXEC_SETUP(_mode, _show, _store) \ + IIO_DEVICE_ATTR(exec_setup, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_VOLT_GAIN(_mode, _show, _store) \ + IIO_DEVICE_ATTR(in0_gain, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_CAP_OFFS(_mode, _show, _store) \ + IIO_DEVICE_ATTR(cap_offs, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_CAP_GAIN(_mode, _show, _store) \ + IIO_DEVICE_ATTR(cap_gain, _mode, _show, _store, 0) +#define IIO_DEV_ATTR_CAP_DATA(_show) \ + IIO_DEVICE_ATTR(cap0_raw, S_IRUGO, _show, NULL, 0) +#define IIO_DEV_ATTR_VT_DATA(_show) \ + IIO_DEVICE_ATTR(in0_raw, S_IRUGO, _show, NULL, 0) + +static ssize_t ad774x_show_conversion_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int i; + int len = 0; + + for (i = 0; i < AD774X_MAX_CONV_MODE; i++) + len += sprintf(buf + len, "%s ", ad774x_conv_mode_table[i].name); + + len += sprintf(buf + len, "\n"); + + return len; +} + +static IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(ad774x_show_conversion_modes); + +static ssize_t ad774x_show_conversion_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%s\n", chip->conversion_mode); +} + +static ssize_t ad774x_store_conversion_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + u8 cfg; + int i; + + ad774x_i2c_read(chip, AD774X_CFG, &cfg, 1); + + for (i = 0; i < AD774X_MAX_CONV_MODE; i++) { + if (strncmp(buf, ad774x_conv_mode_table[i].name, + strlen(ad774x_conv_mode_table[i].name) - 1) == 0) { + chip->conversion_mode = ad774x_conv_mode_table[i].name; + cfg |= 0x18 | ad774x_conv_mode_table[i].reg_cfg; + ad774x_i2c_write(chip, AD774X_CFG, cfg); + return len; + } + } + + dev_err(dev, "not supported conversion mode\n"); + + return -EINVAL; +} + +static IIO_DEV_ATTR_CONVERSION_MODE(S_IRUGO | S_IWUSR, + ad774x_show_conversion_mode, + ad774x_store_conversion_mode); + +static ssize_t ad774x_show_dac_value(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + u8 data; + + ad774x_i2c_read(chip, this_attr->address, &data, 1); + + return sprintf(buf, "%02x\n", data & 0x7F); +} + +static ssize_t ad774x_store_dac_value(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if (!ret) { + ad774x_i2c_write(chip, this_attr->address, + (data ? AD774X_CAPDAC_EN : 0) | (data & 0x7F)); + return len; + } + + return -EINVAL; +} + +static IIO_DEVICE_ATTR(capdac0_raw, S_IRUGO | S_IWUSR, + ad774x_show_dac_value, + ad774x_store_dac_value, + AD774X_CAPDACA); + +static IIO_DEVICE_ATTR(capdac1_raw, S_IRUGO | S_IWUSR, + ad774x_show_dac_value, + ad774x_store_dac_value, + AD774X_CAPDACB); + +static ssize_t ad774x_show_cap_setup(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "0x%02x\n", chip->cap_setup); +} + +static ssize_t ad774x_store_cap_setup(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x100)) { + ad774x_i2c_write(chip, AD774X_CAP_SETUP, data); + chip->cap_setup = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_CAP_SETUP(S_IRUGO | S_IWUSR, + ad774x_show_cap_setup, + ad774x_store_cap_setup); + +static ssize_t ad774x_show_vt_setup(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "0x%02x\n", chip->vt_setup); +} + +static ssize_t ad774x_store_vt_setup(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x100)) { + ad774x_i2c_write(chip, AD774X_VT_SETUP, data); + chip->vt_setup = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_VT_SETUP(S_IRUGO | S_IWUSR, + ad774x_show_vt_setup, + ad774x_store_vt_setup); + +static ssize_t ad774x_show_exec_setup(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "0x%02x\n", chip->exec_setup); +} + +static ssize_t ad774x_store_exec_setup(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x100)) { + ad774x_i2c_write(chip, AD774X_EXEC_SETUP, data); + chip->exec_setup = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_EXEC_SETUP(S_IRUGO | S_IWUSR, + ad774x_show_exec_setup, + ad774x_store_exec_setup); + +static ssize_t ad774x_show_volt_gain(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", chip->volt_gain); +} + +static ssize_t ad774x_store_volt_gain(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x10000)) { + ad774x_i2c_write(chip, AD774X_VOLT_GAINH, data >> 8); + ad774x_i2c_write(chip, AD774X_VOLT_GAINL, data); + chip->volt_gain = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_VOLT_GAIN(S_IRUGO | S_IWUSR, + ad774x_show_volt_gain, + ad774x_store_volt_gain); + +static ssize_t ad774x_show_cap_data(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + unsigned long data; + char tmp[3]; + + ad774x_i2c_read(chip, AD774X_CAP_DATA_HIGH, tmp, 3); + data = ((int)tmp[0] << 16) | ((int)tmp[1] << 8) | (int)tmp[2]; + + return sprintf(buf, "%ld\n", data); +} + +static IIO_DEV_ATTR_CAP_DATA(ad774x_show_cap_data); + +static ssize_t ad774x_show_vt_data(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + unsigned long data; + char tmp[3]; + + ad774x_i2c_read(chip, AD774X_VT_DATA_HIGH, tmp, 3); + data = ((int)tmp[0] << 16) | ((int)tmp[1] << 8) | (int)tmp[2]; + + return sprintf(buf, "%ld\n", data); +} + +static IIO_DEV_ATTR_VT_DATA(ad774x_show_vt_data); + +static ssize_t ad774x_show_cap_offs(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", chip->cap_offs); +} + +static ssize_t ad774x_store_cap_offs(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x10000)) { + ad774x_i2c_write(chip, AD774X_CAP_OFFH, data >> 8); + ad774x_i2c_write(chip, AD774X_CAP_OFFL, data); + chip->cap_offs = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_CAP_OFFS(S_IRUGO | S_IWUSR, + ad774x_show_cap_offs, + ad774x_store_cap_offs); + +static ssize_t ad774x_show_cap_gain(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", chip->cap_gain); +} + +static ssize_t ad774x_store_cap_gain(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + + if ((!ret) && (data < 0x10000)) { + ad774x_i2c_write(chip, AD774X_CAP_GAINH, data >> 8); + ad774x_i2c_write(chip, AD774X_CAP_GAINL, data); + chip->cap_gain = data; + return len; + } + + return -EINVAL; +} + +static IIO_DEV_ATTR_CAP_GAIN(S_IRUGO | S_IWUSR, + ad774x_show_cap_gain, + ad774x_store_cap_gain); + +static ssize_t ad774x_show_name(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad774x_chip_info *chip = dev_info->dev_data; + return sprintf(buf, "%s\n", chip->name); +} + +static IIO_DEVICE_ATTR(name, S_IRUGO, ad774x_show_name, NULL, 0); + +static struct attribute *ad774x_attributes[] = { + &iio_dev_attr_available_conversion_modes.dev_attr.attr, + &iio_dev_attr_conversion_mode.dev_attr.attr, + &iio_dev_attr_cap_setup.dev_attr.attr, + &iio_dev_attr_in0_setup.dev_attr.attr, + &iio_dev_attr_exec_setup.dev_attr.attr, + &iio_dev_attr_cap_offs.dev_attr.attr, + &iio_dev_attr_cap_gain.dev_attr.attr, + &iio_dev_attr_in0_gain.dev_attr.attr, + &iio_dev_attr_in0_raw.dev_attr.attr, + &iio_dev_attr_cap0_raw.dev_attr.attr, + &iio_dev_attr_capdac0_raw.dev_attr.attr, + &iio_dev_attr_capdac1_raw.dev_attr.attr, + &iio_dev_attr_name.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad774x_attribute_group = { + .attrs = ad774x_attributes, +}; + +/* + * data ready events + */ + +#define IIO_EVENT_CODE_CAP_RDY IIO_BUFFER_EVENT_CODE(0) +#define IIO_EVENT_CODE_VT_RDY IIO_BUFFER_EVENT_CODE(1) + +#define IIO_EVENT_ATTR_CAP_RDY_SH(_evlist, _show, _store, _mask) \ + IIO_EVENT_ATTR_SH(cap_rdy, _evlist, _show, _store, _mask) + +#define IIO_EVENT_ATTR_VT_RDY_SH(_evlist, _show, _store, _mask) \ + IIO_EVENT_ATTR_SH(vt_rdy, _evlist, _show, _store, _mask) + +static void ad774x_interrupt_handler_bh(struct work_struct *work_s) +{ + struct ad774x_chip_info *chip = + container_of(work_s, struct ad774x_chip_info, thresh_work); + u8 int_status; + + enable_irq(chip->client->irq); + + ad774x_i2c_read(chip, AD774X_STATUS, &int_status, 1); + + if (int_status & AD774X_STATUS_RDYCAP) + iio_push_event(chip->indio_dev, 0, + IIO_EVENT_CODE_CAP_RDY, + chip->last_timestamp); + + if (int_status & AD774X_STATUS_RDYVT) + iio_push_event(chip->indio_dev, 0, + IIO_EVENT_CODE_VT_RDY, + chip->last_timestamp); +} + +static int ad774x_interrupt_handler_th(struct iio_dev *dev_info, + int index, + s64 timestamp, + int no_test) +{ + struct ad774x_chip_info *chip = dev_info->dev_data; + + chip->last_timestamp = timestamp; + schedule_work(&chip->thresh_work); + + return 0; +} + +IIO_EVENT_SH(data_rdy, &ad774x_interrupt_handler_th); + +static ssize_t ad774x_query_out_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + /* + * AD774X provides one /RDY pin, which can be used as interrupt + * but the pin is not configurable + */ + return sprintf(buf, "1\n"); +} + +static ssize_t ad774x_set_out_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return len; +} + +IIO_EVENT_ATTR_CAP_RDY_SH(iio_event_data_rdy, ad774x_query_out_mode, ad774x_set_out_mode, 0); +IIO_EVENT_ATTR_VT_RDY_SH(iio_event_data_rdy, ad774x_query_out_mode, ad774x_set_out_mode, 0); + +static struct attribute *ad774x_event_attributes[] = { + &iio_event_attr_cap_rdy.dev_attr.attr, + &iio_event_attr_vt_rdy.dev_attr.attr, + NULL, +}; + +static struct attribute_group ad774x_event_attribute_group = { + .attrs = ad774x_event_attributes, +}; + +/* + * device probe and remove + */ + +static int __devinit ad774x_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret = 0, regdone = 0; + struct ad774x_chip_info *chip = kzalloc(sizeof(*chip), GFP_KERNEL); + if (chip == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + /* this is only used for device removal purposes */ + i2c_set_clientdata(client, chip); + + chip->client = client; + chip->name = id->name; + + chip->indio_dev = iio_allocate_device(); + if (chip->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_chip; + } + + /* Establish that the iio_dev is a child of the i2c device */ + chip->indio_dev->dev.parent = &client->dev; + chip->indio_dev->attrs = &ad774x_attribute_group; + chip->indio_dev->event_attrs = &ad774x_event_attribute_group; + chip->indio_dev->dev_data = (void *)(chip); + chip->indio_dev->driver_module = THIS_MODULE; + chip->indio_dev->num_interrupt_lines = 1; + chip->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(chip->indio_dev); + if (ret) + goto error_free_dev; + regdone = 1; + + if (client->irq) { + ret = iio_register_interrupt_line(client->irq, + chip->indio_dev, + 0, + IRQF_TRIGGER_FALLING, + "ad774x"); + if (ret) + goto error_free_dev; + + iio_add_event_to_list(iio_event_attr_cap_rdy.listel, + &chip->indio_dev->interrupts[0]->ev_list); + + INIT_WORK(&chip->thresh_work, ad774x_interrupt_handler_bh); + } + + dev_err(&client->dev, "%s capacitive sensor registered, irq: %d\n", id->name, client->irq); + + return 0; + +error_free_dev: + if (regdone) + iio_device_unregister(chip->indio_dev); + else + iio_free_device(chip->indio_dev); +error_free_chip: + kfree(chip); +error_ret: + return ret; +} + +static int __devexit ad774x_remove(struct i2c_client *client) +{ + struct ad774x_chip_info *chip = i2c_get_clientdata(client); + struct iio_dev *indio_dev = chip->indio_dev; + + if (client->irq) + iio_unregister_interrupt_line(indio_dev, 0); + iio_device_unregister(indio_dev); + kfree(chip); + + return 0; +} + +static const struct i2c_device_id ad774x_id[] = { + { "ad7745", 0 }, + { "ad7746", 0 }, + { "ad7747", 0 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, ad774x_id); + +static struct i2c_driver ad774x_driver = { + .driver = { + .name = "ad774x", + }, + .probe = ad774x_probe, + .remove = __devexit_p(ad774x_remove), + .id_table = ad774x_id, +}; + +static __init int ad774x_init(void) +{ + return i2c_add_driver(&ad774x_driver); +} + +static __exit void ad774x_exit(void) +{ + i2c_del_driver(&ad774x_driver); +} + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices ad7745/6/7 capacitive sensor driver"); +MODULE_LICENSE("GPL v2"); + +module_init(ad774x_init); +module_exit(ad774x_exit); diff --git a/trunk/drivers/staging/iio/adc/ad7816.c b/trunk/drivers/staging/iio/adc/ad7816.c new file mode 100644 index 000000000000..ad7415a6b8d9 --- /dev/null +++ b/trunk/drivers/staging/iio/adc/ad7816.c @@ -0,0 +1,535 @@ +/* + * AD7816 digital temperature sensor driver supporting AD7816/7/8 + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +/* + * AD7816 config masks + */ +#define AD7816_FULL 0x1 +#define AD7816_PD 0x2 +#define AD7816_CS_MASK 0x7 +#define AD7816_CS_MAX 0x4 + +/* + * AD7816 temperature masks + */ +#define AD7816_VALUE_OFFSET 6 +#define AD7816_BOUND_VALUE_BASE 0x8 +#define AD7816_BOUND_VALUE_MIN -95 +#define AD7816_BOUND_VALUE_MAX 152 +#define AD7816_TEMP_FLOAT_OFFSET 2 +#define AD7816_TEMP_FLOAT_MASK 0x3 + + +/* + * struct ad7816_chip_info - chip specifc information + */ + +struct ad7816_chip_info { + const char *name; + struct spi_device *spi_dev; + struct iio_dev *indio_dev; + struct work_struct thresh_work; + s64 last_timestamp; + u16 rdwr_pin; + u16 convert_pin; + u16 busy_pin; + u8 oti_data[AD7816_CS_MAX+1]; + u8 channel_id; /* 0 always be temperature */ + u8 mode; +}; + +/* + * ad7816 data access by SPI + */ +static int ad7816_spi_read(struct ad7816_chip_info *chip, u16 *data) +{ + struct spi_device *spi_dev = chip->spi_dev; + int ret = 0; + + gpio_set_value(chip->rdwr_pin, 1); + gpio_set_value(chip->rdwr_pin, 0); + ret = spi_write(spi_dev, &chip->channel_id, sizeof(chip->channel_id)); + if (ret < 0) { + dev_err(&spi_dev->dev, "SPI channel setting error\n"); + return ret; + } + gpio_set_value(chip->rdwr_pin, 1); + + + if (chip->mode == AD7816_PD) { /* operating mode 2 */ + gpio_set_value(chip->convert_pin, 1); + gpio_set_value(chip->convert_pin, 0); + } else { /* operating mode 1 */ + gpio_set_value(chip->convert_pin, 0); + gpio_set_value(chip->convert_pin, 1); + } + + while (gpio_get_value(chip->busy_pin)) + cpu_relax(); + + gpio_set_value(chip->rdwr_pin, 0); + gpio_set_value(chip->rdwr_pin, 1); + ret = spi_read(spi_dev, (u8 *)data, sizeof(*data)); + if (ret < 0) { + dev_err(&spi_dev->dev, "SPI data read error\n"); + return ret; + } + + *data = be16_to_cpu(*data); + + return ret; +} + +static int ad7816_spi_write(struct ad7816_chip_info *chip, u8 data) +{ + struct spi_device *spi_dev = chip->spi_dev; + int ret = 0; + + gpio_set_value(chip->rdwr_pin, 1); + gpio_set_value(chip->rdwr_pin, 0); + ret = spi_write(spi_dev, &data, sizeof(data)); + if (ret < 0) + dev_err(&spi_dev->dev, "SPI oti data write error\n"); + + return ret; +} + +static ssize_t ad7816_show_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7816_chip_info *chip = dev_info->dev_data; + + if (chip->mode) + return sprintf(buf, "power-save\n"); + else + return sprintf(buf, "full\n"); +} + +static ssize_t ad7816_store_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7816_chip_info *chip = dev_info->dev_data; + + if (strcmp(buf, "full")) { + gpio_set_value(chip->rdwr_pin, 1); + chip->mode = AD7816_FULL; + } else { + gpio_set_value(chip->rdwr_pin, 0); + chip->mode = AD7816_PD; + } + + return len; +} + +static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, + ad7816_show_mode, + ad7816_store_mode, + 0); + +static ssize_t ad7816_show_available_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "full\npower-save\n"); +} + +static IIO_DEVICE_ATTR(available_modes, S_IRUGO, ad7816_show_available_modes, NULL, 0); + +static ssize_t ad7816_show_channel(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7816_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", chip->channel_id); +} + +static ssize_t ad7816_store_channel(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7816_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + + ret = strict_strtoul(buf, 10, &data); + if (ret) + return -EINVAL; + + if (data > AD7816_CS_MAX && data != AD7816_CS_MASK) { + dev_err(&chip->spi_dev->dev, "Invalid channel id %lu for %s.\n", + data, chip->name); + return -EINVAL; + } else if (strcmp(chip->name, "ad7818") == 0 && data > 1) { + dev_err(&chip->spi_dev->dev, + "Invalid channel id %lu for ad7818.\n", data); + return -EINVAL; + } else if (strcmp(chip->name, "ad7816") == 0 && data > 0) { + dev_err(&chip->spi_dev->dev, + "Invalid channel id %lu for ad7816.\n", data); + return -EINVAL; + } + + chip->channel_id = data; + + return len; +} + +static IIO_DEVICE_ATTR(channel, S_IRUGO | S_IWUSR, + ad7816_show_channel, + ad7816_store_channel, + 0); + + +static ssize_t ad7816_show_value(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7816_chip_info *chip = dev_info->dev_data; + u16 data; + s8 value; + int ret; + + ret = ad7816_spi_read(chip, &data); + if (ret) + return -EIO; + + data >>= AD7816_VALUE_OFFSET; + + if (chip->channel_id == 0) { + value = (s8)((data >> AD7816_TEMP_FLOAT_OFFSET) - 103); + data &= AD7816_TEMP_FLOAT_MASK; + if (value < 0) + data = (1 << AD7816_TEMP_FLOAT_OFFSET) - data; + return sprintf(buf, "%d.%.2d\n", value, data * 25); + } else + return sprintf(buf, "%u\n", data); +} + +static IIO_DEVICE_ATTR(value, S_IRUGO, ad7816_show_value, NULL, 0); + +static ssize_t ad7816_show_name(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7816_chip_info *chip = dev_info->dev_data; + return sprintf(buf, "%s\n", chip->name); +} + +static IIO_DEVICE_ATTR(name, S_IRUGO, ad7816_show_name, NULL, 0); + +static struct attribute *ad7816_attributes[] = { + &iio_dev_attr_available_modes.dev_attr.attr, + &iio_dev_attr_mode.dev_attr.attr, + &iio_dev_attr_channel.dev_attr.attr, + &iio_dev_attr_value.dev_attr.attr, + &iio_dev_attr_name.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad7816_attribute_group = { + .attrs = ad7816_attributes, +}; + +/* + * temperature bound events + */ + +#define IIO_EVENT_CODE_AD7816_OTI IIO_BUFFER_EVENT_CODE(0) + +static void ad7816_interrupt_bh(struct work_struct *work_s) +{ + struct ad7816_chip_info *chip = + container_of(work_s, struct ad7816_chip_info, thresh_work); + + enable_irq(chip->spi_dev->irq); + + iio_push_event(chip->indio_dev, 0, + IIO_EVENT_CODE_AD7816_OTI, + chip->last_timestamp); +} + +static int ad7816_interrupt(struct iio_dev *dev_info, + int index, + s64 timestamp, + int no_test) +{ + struct ad7816_chip_info *chip = dev_info->dev_data; + + chip->last_timestamp = timestamp; + schedule_work(&chip->thresh_work); + + return 0; +} + +IIO_EVENT_SH(ad7816, &ad7816_interrupt); + +static ssize_t ad7816_show_oti(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7816_chip_info *chip = dev_info->dev_data; + int value; + + if (chip->channel_id > AD7816_CS_MAX) { + dev_err(dev, "Invalid oti channel id %d.\n", chip->channel_id); + return -EINVAL; + } else if (chip->channel_id == 0) { + value = AD7816_BOUND_VALUE_MIN + + (chip->oti_data[chip->channel_id] - + AD7816_BOUND_VALUE_BASE); + return sprintf(buf, "%d\n", value); + } else + return sprintf(buf, "%u\n", chip->oti_data[chip->channel_id]); +} + +static inline ssize_t ad7816_set_oti(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct ad7816_chip_info *chip = dev_info->dev_data; + long value; + u8 data; + int ret; + + ret = strict_strtol(buf, 10, &value); + + if (chip->channel_id > AD7816_CS_MAX) { + dev_err(dev, "Invalid oti channel id %d.\n", chip->channel_id); + return -EINVAL; + } else if (chip->channel_id == 0) { + if (ret || value < AD7816_BOUND_VALUE_MIN || + value > AD7816_BOUND_VALUE_MAX) + return -EINVAL; + + data = (u8)(value - AD7816_BOUND_VALUE_MIN + + AD7816_BOUND_VALUE_BASE); + } else { + if (ret || value < AD7816_BOUND_VALUE_BASE || value > 255) + return -EINVAL; + + data = (u8)value; + } + + ret = ad7816_spi_write(chip, data); + if (ret) + return -EIO; + + chip->oti_data[chip->channel_id] = data; + + return len; +} + +IIO_EVENT_ATTR_SH(oti, iio_event_ad7816, + ad7816_show_oti, ad7816_set_oti, 0); + +static struct attribute *ad7816_event_attributes[] = { + &iio_event_attr_oti.dev_attr.attr, + NULL, +}; + +static struct attribute_group ad7816_event_attribute_group = { + .attrs = ad7816_event_attributes, +}; + +/* + * device probe and remove + */ + +static int __devinit ad7816_probe(struct spi_device *spi_dev) +{ + struct ad7816_chip_info *chip; + unsigned short *pins = spi_dev->dev.platform_data; + int ret = 0; + int i; + + if (!pins) { + dev_err(&spi_dev->dev, "No necessary GPIO platform data.\n"); + return -EINVAL; + } + + chip = kzalloc(sizeof(struct ad7816_chip_info), GFP_KERNEL); + + if (chip == NULL) + return -ENOMEM; + + /* this is only used for device removal purposes */ + dev_set_drvdata(&spi_dev->dev, chip); + + chip->spi_dev = spi_dev; + chip->name = spi_dev->modalias; + for (i = 0; i <= AD7816_CS_MAX; i++) + chip->oti_data[i] = 203; + chip->rdwr_pin = pins[0]; + chip->convert_pin = pins[1]; + chip->busy_pin = pins[2]; + + ret = gpio_request(chip->rdwr_pin, chip->name); + if (ret) { + dev_err(&spi_dev->dev, "Fail to request rdwr gpio PIN %d.\n", + chip->rdwr_pin); + goto error_free_chip; + } + gpio_direction_input(chip->rdwr_pin); + ret = gpio_request(chip->convert_pin, chip->name); + if (ret) { + dev_err(&spi_dev->dev, "Fail to request convert gpio PIN %d.\n", + chip->convert_pin); + goto error_free_gpio_rdwr; + } + gpio_direction_input(chip->convert_pin); + ret = gpio_request(chip->busy_pin, chip->name); + if (ret) { + dev_err(&spi_dev->dev, "Fail to request busy gpio PIN %d.\n", + chip->busy_pin); + goto error_free_gpio_convert; + } + gpio_direction_input(chip->busy_pin); + + chip->indio_dev = iio_allocate_device(); + if (chip->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_gpio; + } + + chip->indio_dev->dev.parent = &spi_dev->dev; + chip->indio_dev->attrs = &ad7816_attribute_group; + chip->indio_dev->event_attrs = &ad7816_event_attribute_group; + chip->indio_dev->dev_data = (void *)chip; + chip->indio_dev->driver_module = THIS_MODULE; + chip->indio_dev->num_interrupt_lines = 1; + chip->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(chip->indio_dev); + if (ret) + goto error_free_dev; + + if (spi_dev->irq) { + /* Only low trigger is supported in ad7816/7/8 */ + ret = iio_register_interrupt_line(spi_dev->irq, + chip->indio_dev, + 0, + IRQF_TRIGGER_LOW, + chip->name); + if (ret) + goto error_unreg_dev; + + /* + * The event handler list element refer to iio_event_ad7816. + * All event attributes bind to the same event handler. + * So, only register event handler once. + */ + iio_add_event_to_list(&iio_event_ad7816, + &chip->indio_dev->interrupts[0]->ev_list); + + INIT_WORK(&chip->thresh_work, ad7816_interrupt_bh); + } + + dev_info(&spi_dev->dev, "%s temperature sensor and ADC registered.\n", + chip->name); + + return 0; + +error_unreg_dev: + iio_device_unregister(chip->indio_dev); +error_free_dev: + iio_free_device(chip->indio_dev); +error_free_gpio: + gpio_free(chip->busy_pin); +error_free_gpio_convert: + gpio_free(chip->convert_pin); +error_free_gpio_rdwr: + gpio_free(chip->rdwr_pin); +error_free_chip: + kfree(chip); + + return ret; +} + +static int __devexit ad7816_remove(struct spi_device *spi_dev) +{ + struct ad7816_chip_info *chip = dev_get_drvdata(&spi_dev->dev); + struct iio_dev *indio_dev = chip->indio_dev; + + dev_set_drvdata(&spi_dev->dev, NULL); + if (spi_dev->irq) + iio_unregister_interrupt_line(indio_dev, 0); + iio_device_unregister(indio_dev); + iio_free_device(chip->indio_dev); + gpio_free(chip->busy_pin); + gpio_free(chip->convert_pin); + gpio_free(chip->rdwr_pin); + kfree(chip); + + return 0; +} + +static const struct spi_device_id ad7816_id[] = { + { "ad7816", 0 }, + { "ad7817", 0 }, + { "ad7818", 0 }, + {} +}; + +MODULE_DEVICE_TABLE(spi, ad7816_id); + +static struct spi_driver ad7816_driver = { + .driver = { + .name = "ad7816", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = ad7816_probe, + .remove = __devexit_p(ad7816_remove), + .id_table = ad7816_id, +}; + +static __init int ad7816_init(void) +{ + return spi_register_driver(&ad7816_driver); +} + +static __exit void ad7816_exit(void) +{ + spi_unregister_driver(&ad7816_driver); +} + +MODULE_AUTHOR("Sonic Zhang "); +MODULE_DESCRIPTION("Analog Devices AD7816/7/8 digital" + " temperature sensor driver"); +MODULE_LICENSE("GPL v2"); + +module_init(ad7816_init); +module_exit(ad7816_exit); diff --git a/trunk/drivers/staging/iio/adc/adt7310.c b/trunk/drivers/staging/iio/adc/adt7310.c new file mode 100644 index 000000000000..771a409ee94c --- /dev/null +++ b/trunk/drivers/staging/iio/adc/adt7310.c @@ -0,0 +1,952 @@ +/* + * ADT7310 digital temperature sensor driver supporting ADT7310 + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +/* + * ADT7310 registers definition + */ + +#define ADT7310_STATUS 0 +#define ADT7310_CONFIG 1 +#define ADT7310_TEMPERATURE 2 +#define ADT7310_ID 3 +#define ADT7310_T_CRIT 4 +#define ADT7310_T_HYST 5 +#define ADT7310_T_ALARM_HIGH 6 +#define ADT7310_T_ALARM_LOW 7 + +/* + * ADT7310 status + */ +#define ADT7310_STAT_T_LOW 0x10 +#define ADT7310_STAT_T_HIGH 0x20 +#define ADT7310_STAT_T_CRIT 0x40 +#define ADT7310_STAT_NOT_RDY 0x80 + +/* + * ADT7310 config + */ +#define ADT7310_FAULT_QUEUE_MASK 0x3 +#define ADT7310_CT_POLARITY 0x4 +#define ADT7310_INT_POLARITY 0x8 +#define ADT7310_EVENT_MODE 0x10 +#define ADT7310_MODE_MASK 0x60 +#define ADT7310_ONESHOT 0x20 +#define ADT7310_SPS 0x40 +#define ADT7310_PD 0x60 +#define ADT7310_RESOLUTION 0x80 + +/* + * ADT7310 masks + */ +#define ADT7310_T16_VALUE_SIGN 0x8000 +#define ADT7310_T16_VALUE_FLOAT_OFFSET 7 +#define ADT7310_T16_VALUE_FLOAT_MASK 0x7F +#define ADT7310_T13_VALUE_SIGN 0x1000 +#define ADT7310_T13_VALUE_OFFSET 3 +#define ADT7310_T13_VALUE_FLOAT_OFFSET 4 +#define ADT7310_T13_VALUE_FLOAT_MASK 0xF +#define ADT7310_T_HYST_MASK 0xF +#define ADT7310_DEVICE_ID_MASK 0x7 +#define ADT7310_MANUFACTORY_ID_MASK 0xF8 +#define ADT7310_MANUFACTORY_ID_OFFSET 3 + + +#define ADT7310_CMD_REG_MASK 0x28 +#define ADT7310_CMD_REG_OFFSET 3 +#define ADT7310_CMD_READ 0x40 +#define ADT7310_CMD_CON_READ 0x4 + +#define ADT7310_IRQS 2 + +/* + * struct adt7310_chip_info - chip specifc information + */ + +struct adt7310_chip_info { + const char *name; + struct spi_device *spi_dev; + struct iio_dev *indio_dev; + struct work_struct thresh_work; + s64 last_timestamp; + u8 config; +}; + +/* + * adt7310 register access by SPI + */ + +static int adt7310_spi_read_word(struct adt7310_chip_info *chip, u8 reg, u16 *data) +{ + struct spi_device *spi_dev = chip->spi_dev; + u8 command = (reg << ADT7310_CMD_REG_OFFSET) & ADT7310_CMD_REG_MASK; + int ret = 0; + + command |= ADT7310_CMD_READ; + ret = spi_write(spi_dev, &command, sizeof(command)); + if (ret < 0) { + dev_err(&spi_dev->dev, "SPI write command error\n"); + return ret; + } + + ret = spi_read(spi_dev, (u8 *)data, sizeof(*data)); + if (ret < 0) { + dev_err(&spi_dev->dev, "SPI read word error\n"); + return ret; + } + + *data = be16_to_cpu(*data); + + return 0; +} + +static int adt7310_spi_write_word(struct adt7310_chip_info *chip, u8 reg, u16 data) +{ + struct spi_device *spi_dev = chip->spi_dev; + u8 buf[3]; + int ret = 0; + + buf[0] = (reg << ADT7310_CMD_REG_OFFSET) & ADT7310_CMD_REG_MASK; + buf[1] = (u8)(data >> 8); + buf[2] = (u8)(data & 0xFF); + + ret = spi_write(spi_dev, buf, 3); + if (ret < 0) { + dev_err(&spi_dev->dev, "SPI write word error\n"); + return ret; + } + + return ret; +} + +static int adt7310_spi_read_byte(struct adt7310_chip_info *chip, u8 reg, u8 *data) +{ + struct spi_device *spi_dev = chip->spi_dev; + u8 command = (reg << ADT7310_CMD_REG_OFFSET) & ADT7310_CMD_REG_MASK; + int ret = 0; + + command |= ADT7310_CMD_READ; + ret = spi_write(spi_dev, &command, sizeof(command)); + if (ret < 0) { + dev_err(&spi_dev->dev, "SPI write command error\n"); + return ret; + } + + ret = spi_read(spi_dev, data, sizeof(*data)); + if (ret < 0) { + dev_err(&spi_dev->dev, "SPI read byte error\n"); + return ret; + } + + return 0; +} + +static int adt7310_spi_write_byte(struct adt7310_chip_info *chip, u8 reg, u8 data) +{ + struct spi_device *spi_dev = chip->spi_dev; + u8 buf[2]; + int ret = 0; + + buf[0] = (reg << ADT7310_CMD_REG_OFFSET) & ADT7310_CMD_REG_MASK; + buf[1] = data; + + ret = spi_write(spi_dev, buf, 2); + if (ret < 0) { + dev_err(&spi_dev->dev, "SPI write byte error\n"); + return ret; + } + + return ret; +} + +static ssize_t adt7310_show_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7310_chip_info *chip = dev_info->dev_data; + u8 config; + + config = chip->config & ADT7310_MODE_MASK; + + switch (config) { + case ADT7310_PD: + return sprintf(buf, "power-down\n"); + case ADT7310_ONESHOT: + return sprintf(buf, "one-shot\n"); + case ADT7310_SPS: + return sprintf(buf, "sps\n"); + default: + return sprintf(buf, "full\n"); + } +} + +static ssize_t adt7310_store_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7310_chip_info *chip = dev_info->dev_data; + u16 config; + int ret; + + ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); + if (ret) + return -EIO; + + config = chip->config & (~ADT7310_MODE_MASK); + if (strcmp(buf, "power-down")) + config |= ADT7310_PD; + else if (strcmp(buf, "one-shot")) + config |= ADT7310_ONESHOT; + else if (strcmp(buf, "sps")) + config |= ADT7310_SPS; + + ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, config); + if (ret) + return -EIO; + + chip->config = config; + + return len; +} + +static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, + adt7310_show_mode, + adt7310_store_mode, + 0); + +static ssize_t adt7310_show_available_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "full\none-shot\nsps\npower-down\n"); +} + +static IIO_DEVICE_ATTR(available_modes, S_IRUGO, adt7310_show_available_modes, NULL, 0); + +static ssize_t adt7310_show_resolution(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7310_chip_info *chip = dev_info->dev_data; + int ret; + int bits; + + ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); + if (ret) + return -EIO; + + if (chip->config & ADT7310_RESOLUTION) + bits = 16; + else + bits = 13; + + return sprintf(buf, "%d bits\n", bits); +} + +static ssize_t adt7310_store_resolution(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7310_chip_info *chip = dev_info->dev_data; + unsigned long data; + u16 config; + int ret; + + ret = strict_strtoul(buf, 10, &data); + if (ret) + return -EINVAL; + + ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); + if (ret) + return -EIO; + + config = chip->config & (~ADT7310_RESOLUTION); + if (data) + config |= ADT7310_RESOLUTION; + + ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, config); + if (ret) + return -EIO; + + chip->config = config; + + return len; +} + +static IIO_DEVICE_ATTR(resolution, S_IRUGO | S_IWUSR, + adt7310_show_resolution, + adt7310_store_resolution, + 0); + +static ssize_t adt7310_show_id(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7310_chip_info *chip = dev_info->dev_data; + u8 id; + int ret; + + ret = adt7310_spi_read_byte(chip, ADT7310_ID, &id); + if (ret) + return -EIO; + + return sprintf(buf, "device id: 0x%x\nmanufactory id: 0x%x\n", + id & ADT7310_DEVICE_ID_MASK, + (id & ADT7310_MANUFACTORY_ID_MASK) >> ADT7310_MANUFACTORY_ID_OFFSET); +} + +static IIO_DEVICE_ATTR(id, S_IRUGO | S_IWUSR, + adt7310_show_id, + NULL, + 0); + +static ssize_t adt7310_convert_temperature(struct adt7310_chip_info *chip, + u16 data, char *buf) +{ + char sign = ' '; + + if (chip->config & ADT7310_RESOLUTION) { + if (data & ADT7310_T16_VALUE_SIGN) { + /* convert supplement to positive value */ + data = (u16)((ADT7310_T16_VALUE_SIGN << 1) - (u32)data); + sign = '-'; + } + return sprintf(buf, "%c%d.%.7d\n", sign, + (data >> ADT7310_T16_VALUE_FLOAT_OFFSET), + (data & ADT7310_T16_VALUE_FLOAT_MASK) * 78125); + } else { + if (data & ADT7310_T13_VALUE_SIGN) { + /* convert supplement to positive value */ + data >>= ADT7310_T13_VALUE_OFFSET; + data = (ADT7310_T13_VALUE_SIGN << 1) - data; + sign = '-'; + } + return sprintf(buf, "%c%d.%.4d\n", sign, + (data >> ADT7310_T13_VALUE_FLOAT_OFFSET), + (data & ADT7310_T13_VALUE_FLOAT_MASK) * 625); + } +} + +static ssize_t adt7310_show_value(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7310_chip_info *chip = dev_info->dev_data; + u8 status; + u16 data; + int ret, i = 0; + + do { + ret = adt7310_spi_read_byte(chip, ADT7310_STATUS, &status); + if (ret) + return -EIO; + i++; + if (i == 10000) + return -EIO; + } while (status & ADT7310_STAT_NOT_RDY); + + ret = adt7310_spi_read_word(chip, ADT7310_TEMPERATURE, &data); + if (ret) + return -EIO; + + return adt7310_convert_temperature(chip, data, buf); +} + +static IIO_DEVICE_ATTR(value, S_IRUGO, adt7310_show_value, NULL, 0); + +static ssize_t adt7310_show_name(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7310_chip_info *chip = dev_info->dev_data; + return sprintf(buf, "%s\n", chip->name); +} + +static IIO_DEVICE_ATTR(name, S_IRUGO, adt7310_show_name, NULL, 0); + +static struct attribute *adt7310_attributes[] = { + &iio_dev_attr_available_modes.dev_attr.attr, + &iio_dev_attr_mode.dev_attr.attr, + &iio_dev_attr_resolution.dev_attr.attr, + &iio_dev_attr_id.dev_attr.attr, + &iio_dev_attr_value.dev_attr.attr, + &iio_dev_attr_name.dev_attr.attr, + NULL, +}; + +static const struct attribute_group adt7310_attribute_group = { + .attrs = adt7310_attributes, +}; + +/* + * temperature bound events + */ + +#define IIO_EVENT_CODE_ADT7310_ABOVE_ALARM IIO_BUFFER_EVENT_CODE(0) +#define IIO_EVENT_CODE_ADT7310_BELLOW_ALARM IIO_BUFFER_EVENT_CODE(1) +#define IIO_EVENT_CODE_ADT7310_ABOVE_CRIT IIO_BUFFER_EVENT_CODE(2) + +static void adt7310_interrupt_bh(struct work_struct *work_s) +{ + struct adt7310_chip_info *chip = + container_of(work_s, struct adt7310_chip_info, thresh_work); + u8 status; + + if (adt7310_spi_read_byte(chip, ADT7310_STATUS, &status)) + return; + + if (status & ADT7310_STAT_T_HIGH) + iio_push_event(chip->indio_dev, 0, + IIO_EVENT_CODE_ADT7310_ABOVE_ALARM, + chip->last_timestamp); + if (status & ADT7310_STAT_T_LOW) + iio_push_event(chip->indio_dev, 0, + IIO_EVENT_CODE_ADT7310_BELLOW_ALARM, + chip->last_timestamp); + if (status & ADT7310_STAT_T_CRIT) + iio_push_event(chip->indio_dev, 0, + IIO_EVENT_CODE_ADT7310_ABOVE_CRIT, + chip->last_timestamp); +} + +static int adt7310_interrupt(struct iio_dev *dev_info, + int index, + s64 timestamp, + int no_test) +{ + struct adt7310_chip_info *chip = dev_info->dev_data; + + chip->last_timestamp = timestamp; + schedule_work(&chip->thresh_work); + + return 0; +} + +IIO_EVENT_SH(adt7310, &adt7310_interrupt); +IIO_EVENT_SH(adt7310_ct, &adt7310_interrupt); + +static ssize_t adt7310_show_event_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7310_chip_info *chip = dev_info->dev_data; + int ret; + + ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); + if (ret) + return -EIO; + + if (chip->config & ADT7310_EVENT_MODE) + return sprintf(buf, "interrupt\n"); + else + return sprintf(buf, "comparator\n"); +} + +static ssize_t adt7310_set_event_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7310_chip_info *chip = dev_info->dev_data; + u16 config; + int ret; + + ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); + if (ret) + return -EIO; + + config = chip->config &= ~ADT7310_EVENT_MODE; + if (strcmp(buf, "comparator") != 0) + config |= ADT7310_EVENT_MODE; + + ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, config); + if (ret) + return -EIO; + + chip->config = config; + + return len; +} + +static ssize_t adt7310_show_available_event_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "comparator\ninterrupt\n"); +} + +static ssize_t adt7310_show_fault_queue(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7310_chip_info *chip = dev_info->dev_data; + int ret; + + ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); + if (ret) + return -EIO; + + return sprintf(buf, "%d\n", chip->config & ADT7310_FAULT_QUEUE_MASK); +} + +static ssize_t adt7310_set_fault_queue(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7310_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + u8 config; + + ret = strict_strtoul(buf, 10, &data); + if (ret || data > 3) + return -EINVAL; + + ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); + if (ret) + return -EIO; + + config = chip->config & ~ADT7310_FAULT_QUEUE_MASK; + config |= data; + ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, config); + if (ret) + return -EIO; + + chip->config = config; + + return len; +} + +static inline ssize_t adt7310_show_t_bound(struct device *dev, + struct device_attribute *attr, + u8 bound_reg, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7310_chip_info *chip = dev_info->dev_data; + u16 data; + int ret; + + ret = adt7310_spi_read_word(chip, bound_reg, &data); + if (ret) + return -EIO; + + return adt7310_convert_temperature(chip, data, buf); +} + +static inline ssize_t adt7310_set_t_bound(struct device *dev, + struct device_attribute *attr, + u8 bound_reg, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7310_chip_info *chip = dev_info->dev_data; + long tmp1, tmp2; + u16 data; + char *pos; + int ret; + + pos = strchr(buf, '.'); + + ret = strict_strtol(buf, 10, &tmp1); + + if (ret || tmp1 > 127 || tmp1 < -128) + return -EINVAL; + + if (pos) { + len = strlen(pos); + + if (chip->config & ADT7310_RESOLUTION) { + if (len > ADT7310_T16_VALUE_FLOAT_OFFSET) + len = ADT7310_T16_VALUE_FLOAT_OFFSET; + pos[len] = 0; + ret = strict_strtol(pos, 10, &tmp2); + + if (!ret) + tmp2 = (tmp2 / 78125) * 78125; + } else { + if (len > ADT7310_T13_VALUE_FLOAT_OFFSET) + len = ADT7310_T13_VALUE_FLOAT_OFFSET; + pos[len] = 0; + ret = strict_strtol(pos, 10, &tmp2); + + if (!ret) + tmp2 = (tmp2 / 625) * 625; + } + } + + if (tmp1 < 0) + data = (u16)(-tmp1); + else + data = (u16)tmp1; + + if (chip->config & ADT7310_RESOLUTION) { + data = (data << ADT7310_T16_VALUE_FLOAT_OFFSET) | + (tmp2 & ADT7310_T16_VALUE_FLOAT_MASK); + + if (tmp1 < 0) + /* convert positive value to supplyment */ + data = (u16)((ADT7310_T16_VALUE_SIGN << 1) - (u32)data); + } else { + data = (data << ADT7310_T13_VALUE_FLOAT_OFFSET) | + (tmp2 & ADT7310_T13_VALUE_FLOAT_MASK); + + if (tmp1 < 0) + /* convert positive value to supplyment */ + data = (ADT7310_T13_VALUE_SIGN << 1) - data; + data <<= ADT7310_T13_VALUE_OFFSET; + } + + ret = adt7310_spi_write_word(chip, bound_reg, data); + if (ret) + return -EIO; + + return len; +} + +static ssize_t adt7310_show_t_alarm_high(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return adt7310_show_t_bound(dev, attr, + ADT7310_T_ALARM_HIGH, buf); +} + +static inline ssize_t adt7310_set_t_alarm_high(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return adt7310_set_t_bound(dev, attr, + ADT7310_T_ALARM_HIGH, buf, len); +} + +static ssize_t adt7310_show_t_alarm_low(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return adt7310_show_t_bound(dev, attr, + ADT7310_T_ALARM_LOW, buf); +} + +static inline ssize_t adt7310_set_t_alarm_low(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return adt7310_set_t_bound(dev, attr, + ADT7310_T_ALARM_LOW, buf, len); +} + +static ssize_t adt7310_show_t_crit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return adt7310_show_t_bound(dev, attr, + ADT7310_T_CRIT, buf); +} + +static inline ssize_t adt7310_set_t_crit(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return adt7310_set_t_bound(dev, attr, + ADT7310_T_CRIT, buf, len); +} + +static ssize_t adt7310_show_t_hyst(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7310_chip_info *chip = dev_info->dev_data; + int ret; + u8 t_hyst; + + ret = adt7310_spi_read_byte(chip, ADT7310_T_HYST, &t_hyst); + if (ret) + return -EIO; + + return sprintf(buf, "%d\n", t_hyst & ADT7310_T_HYST_MASK); +} + +static inline ssize_t adt7310_set_t_hyst(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7310_chip_info *chip = dev_info->dev_data; + int ret; + unsigned long data; + u8 t_hyst; + + ret = strict_strtol(buf, 10, &data); + + if (ret || data > ADT7310_T_HYST_MASK) + return -EINVAL; + + t_hyst = (u8)data; + + ret = adt7310_spi_write_byte(chip, ADT7310_T_HYST, t_hyst); + if (ret) + return -EIO; + + return len; +} + +IIO_EVENT_ATTR_SH(event_mode, iio_event_adt7310, + adt7310_show_event_mode, adt7310_set_event_mode, 0); +IIO_EVENT_ATTR_SH(available_event_modes, iio_event_adt7310, + adt7310_show_available_event_modes, NULL, 0); +IIO_EVENT_ATTR_SH(fault_queue, iio_event_adt7310, + adt7310_show_fault_queue, adt7310_set_fault_queue, 0); +IIO_EVENT_ATTR_SH(t_alarm_high, iio_event_adt7310, + adt7310_show_t_alarm_high, adt7310_set_t_alarm_high, 0); +IIO_EVENT_ATTR_SH(t_alarm_low, iio_event_adt7310, + adt7310_show_t_alarm_low, adt7310_set_t_alarm_low, 0); +IIO_EVENT_ATTR_SH(t_crit, iio_event_adt7310_ct, + adt7310_show_t_crit, adt7310_set_t_crit, 0); +IIO_EVENT_ATTR_SH(t_hyst, iio_event_adt7310, + adt7310_show_t_hyst, adt7310_set_t_hyst, 0); + +static struct attribute *adt7310_event_int_attributes[] = { + &iio_event_attr_event_mode.dev_attr.attr, + &iio_event_attr_available_event_modes.dev_attr.attr, + &iio_event_attr_fault_queue.dev_attr.attr, + &iio_event_attr_t_alarm_high.dev_attr.attr, + &iio_event_attr_t_alarm_low.dev_attr.attr, + &iio_event_attr_t_hyst.dev_attr.attr, + NULL, +}; + +static struct attribute *adt7310_event_ct_attributes[] = { + &iio_event_attr_event_mode.dev_attr.attr, + &iio_event_attr_available_event_modes.dev_attr.attr, + &iio_event_attr_fault_queue.dev_attr.attr, + &iio_event_attr_t_crit.dev_attr.attr, + &iio_event_attr_t_hyst.dev_attr.attr, + NULL, +}; + +static struct attribute_group adt7310_event_attribute_group[ADT7310_IRQS] = { + { + .attrs = adt7310_event_int_attributes, + }, + { + .attrs = adt7310_event_ct_attributes, + } +}; + +/* + * device probe and remove + */ + +static int __devinit adt7310_probe(struct spi_device *spi_dev) +{ + struct adt7310_chip_info *chip; + int ret = 0; + unsigned long *adt7310_platform_data = spi_dev->dev.platform_data; + unsigned long irq_flags; + + chip = kzalloc(sizeof(struct adt7310_chip_info), GFP_KERNEL); + + if (chip == NULL) + return -ENOMEM; + + /* this is only used for device removal purposes */ + dev_set_drvdata(&spi_dev->dev, chip); + + chip->spi_dev = spi_dev; + chip->name = spi_dev->modalias; + + chip->indio_dev = iio_allocate_device(); + if (chip->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_chip; + } + + chip->indio_dev->dev.parent = &spi_dev->dev; + chip->indio_dev->attrs = &adt7310_attribute_group; + chip->indio_dev->event_attrs = adt7310_event_attribute_group; + chip->indio_dev->dev_data = (void *)chip; + chip->indio_dev->driver_module = THIS_MODULE; + chip->indio_dev->num_interrupt_lines = ADT7310_IRQS; + chip->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(chip->indio_dev); + if (ret) + goto error_free_dev; + + /* CT critcal temperature event. line 0 */ + if (spi_dev->irq) { + if (adt7310_platform_data[2]) + irq_flags = adt7310_platform_data[2]; + else + irq_flags = IRQF_TRIGGER_LOW; + ret = iio_register_interrupt_line(spi_dev->irq, + chip->indio_dev, + 0, + irq_flags, + chip->name); + if (ret) + goto error_unreg_dev; + + /* + * The event handler list element refer to iio_event_adt7310. + * All event attributes bind to the same event handler. + * One event handler can only be added to one event list. + */ + iio_add_event_to_list(&iio_event_adt7310, + &chip->indio_dev->interrupts[0]->ev_list); + } + + /* INT bound temperature alarm event. line 1 */ + if (adt7310_platform_data[0]) { + ret = iio_register_interrupt_line(adt7310_platform_data[0], + chip->indio_dev, + 1, + adt7310_platform_data[1], + chip->name); + if (ret) + goto error_unreg_ct_irq; + + /* + * The event handler list element refer to iio_event_adt7310. + * All event attributes bind to the same event handler. + * One event handler can only be added to one event list. + */ + iio_add_event_to_list(&iio_event_adt7310_ct, + &chip->indio_dev->interrupts[1]->ev_list); + } + + if (spi_dev->irq && adt7310_platform_data[0]) { + INIT_WORK(&chip->thresh_work, adt7310_interrupt_bh); + + ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); + if (ret) { + ret = -EIO; + goto error_unreg_int_irq; + } + + /* set irq polarity low level */ + chip->config &= ~ADT7310_CT_POLARITY; + + if (adt7310_platform_data[1] & IRQF_TRIGGER_HIGH) + chip->config |= ADT7310_INT_POLARITY; + else + chip->config &= ~ADT7310_INT_POLARITY; + + ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, chip->config); + if (ret) { + ret = -EIO; + goto error_unreg_int_irq; + } + } + + dev_info(&spi_dev->dev, "%s temperature sensor registered.\n", + chip->name); + + return 0; + +error_unreg_int_irq: + iio_unregister_interrupt_line(chip->indio_dev, 1); +error_unreg_ct_irq: + iio_unregister_interrupt_line(chip->indio_dev, 0); +error_unreg_dev: + iio_device_unregister(chip->indio_dev); +error_free_dev: + iio_free_device(chip->indio_dev); +error_free_chip: + kfree(chip); + + return ret; +} + +static int __devexit adt7310_remove(struct spi_device *spi_dev) +{ + struct adt7310_chip_info *chip = dev_get_drvdata(&spi_dev->dev); + struct iio_dev *indio_dev = chip->indio_dev; + unsigned long *adt7310_platform_data = spi_dev->dev.platform_data; + + dev_set_drvdata(&spi_dev->dev, NULL); + if (adt7310_platform_data[0]) + iio_unregister_interrupt_line(indio_dev, 1); + if (spi_dev->irq) + iio_unregister_interrupt_line(indio_dev, 0); + iio_device_unregister(indio_dev); + iio_free_device(chip->indio_dev); + kfree(chip); + + return 0; +} + +static const struct spi_device_id adt7310_id[] = { + { "adt7310", 0 }, + {} +}; + +MODULE_DEVICE_TABLE(spi, adt7310_id); + +static struct spi_driver adt7310_driver = { + .driver = { + .name = "adt7310", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = adt7310_probe, + .remove = __devexit_p(adt7310_remove), + .id_table = adt7310_id, +}; + +static __init int adt7310_init(void) +{ + return spi_register_driver(&adt7310_driver); +} + +static __exit void adt7310_exit(void) +{ + spi_unregister_driver(&adt7310_driver); +} + +MODULE_AUTHOR("Sonic Zhang "); +MODULE_DESCRIPTION("Analog Devices ADT7310 digital" + " temperature sensor driver"); +MODULE_LICENSE("GPL v2"); + +module_init(adt7310_init); +module_exit(adt7310_exit); diff --git a/trunk/drivers/staging/iio/adc/adt7410.c b/trunk/drivers/staging/iio/adc/adt7410.c new file mode 100644 index 000000000000..c345f27ec7fc --- /dev/null +++ b/trunk/drivers/staging/iio/adc/adt7410.c @@ -0,0 +1,915 @@ +/* + * ADT7410 digital temperature sensor driver supporting ADT7410 + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +/* + * ADT7410 registers definition + */ + +#define ADT7410_TEMPERATURE 0 +#define ADT7410_STATUS 2 +#define ADT7410_CONFIG 3 +#define ADT7410_T_ALARM_HIGH 4 +#define ADT7410_T_ALARM_LOW 6 +#define ADT7410_T_CRIT 8 +#define ADT7410_T_HYST 0xA +#define ADT7410_ID 0xB +#define ADT7410_RESET 0x2F + +/* + * ADT7410 status + */ +#define ADT7410_STAT_T_LOW 0x10 +#define ADT7410_STAT_T_HIGH 0x20 +#define ADT7410_STAT_T_CRIT 0x40 +#define ADT7410_STAT_NOT_RDY 0x80 + +/* + * ADT7410 config + */ +#define ADT7410_FAULT_QUEUE_MASK 0x3 +#define ADT7410_CT_POLARITY 0x4 +#define ADT7410_INT_POLARITY 0x8 +#define ADT7410_EVENT_MODE 0x10 +#define ADT7410_MODE_MASK 0x60 +#define ADT7410_ONESHOT 0x20 +#define ADT7410_SPS 0x40 +#define ADT7410_PD 0x60 +#define ADT7410_RESOLUTION 0x80 + +/* + * ADT7410 masks + */ +#define ADT7410_T16_VALUE_SIGN 0x8000 +#define ADT7410_T16_VALUE_FLOAT_OFFSET 7 +#define ADT7410_T16_VALUE_FLOAT_MASK 0x7F +#define ADT7410_T13_VALUE_SIGN 0x1000 +#define ADT7410_T13_VALUE_OFFSET 3 +#define ADT7410_T13_VALUE_FLOAT_OFFSET 4 +#define ADT7410_T13_VALUE_FLOAT_MASK 0xF +#define ADT7410_T_HYST_MASK 0xF +#define ADT7410_DEVICE_ID_MASK 0xF +#define ADT7410_MANUFACTORY_ID_MASK 0xF0 +#define ADT7410_MANUFACTORY_ID_OFFSET 4 + +#define ADT7410_IRQS 2 + +/* + * struct adt7410_chip_info - chip specifc information + */ + +struct adt7410_chip_info { + const char *name; + struct i2c_client *client; + struct iio_dev *indio_dev; + struct work_struct thresh_work; + s64 last_timestamp; + u8 config; +}; + +/* + * adt7410 register access by I2C + */ + +static int adt7410_i2c_read_word(struct adt7410_chip_info *chip, u8 reg, u16 *data) +{ + struct i2c_client *client = chip->client; + int ret = 0; + + ret = i2c_smbus_read_word_data(client, reg); + if (ret < 0) { + dev_err(&client->dev, "I2C read error\n"); + return ret; + } + + *data = swab16((u16)ret); + + return 0; +} + +static int adt7410_i2c_write_word(struct adt7410_chip_info *chip, u8 reg, u16 data) +{ + struct i2c_client *client = chip->client; + int ret = 0; + + ret = i2c_smbus_write_word_data(client, reg, swab16(data)); + if (ret < 0) + dev_err(&client->dev, "I2C write error\n"); + + return ret; +} + +static int adt7410_i2c_read_byte(struct adt7410_chip_info *chip, u8 reg, u8 *data) +{ + struct i2c_client *client = chip->client; + int ret = 0; + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret < 0) { + dev_err(&client->dev, "I2C read error\n"); + return ret; + } + + *data = (u8)ret; + + return 0; +} + +static int adt7410_i2c_write_byte(struct adt7410_chip_info *chip, u8 reg, u8 data) +{ + struct i2c_client *client = chip->client; + int ret = 0; + + ret = i2c_smbus_write_byte_data(client, reg, data); + if (ret < 0) + dev_err(&client->dev, "I2C write error\n"); + + return ret; +} + +static ssize_t adt7410_show_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7410_chip_info *chip = dev_info->dev_data; + u8 config; + + config = chip->config & ADT7410_MODE_MASK; + + switch (config) { + case ADT7410_PD: + return sprintf(buf, "power-down\n"); + case ADT7410_ONESHOT: + return sprintf(buf, "one-shot\n"); + case ADT7410_SPS: + return sprintf(buf, "sps\n"); + default: + return sprintf(buf, "full\n"); + } +} + +static ssize_t adt7410_store_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7410_chip_info *chip = dev_info->dev_data; + u16 config; + int ret; + + ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config); + if (ret) + return -EIO; + + config = chip->config & (~ADT7410_MODE_MASK); + if (strcmp(buf, "power-down")) + config |= ADT7410_PD; + else if (strcmp(buf, "one-shot")) + config |= ADT7410_ONESHOT; + else if (strcmp(buf, "sps")) + config |= ADT7410_SPS; + + ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, config); + if (ret) + return -EIO; + + chip->config = config; + + return ret; +} + +static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, + adt7410_show_mode, + adt7410_store_mode, + 0); + +static ssize_t adt7410_show_available_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "full\none-shot\nsps\npower-down\n"); +} + +static IIO_DEVICE_ATTR(available_modes, S_IRUGO, adt7410_show_available_modes, NULL, 0); + +static ssize_t adt7410_show_resolution(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7410_chip_info *chip = dev_info->dev_data; + int ret; + int bits; + + ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config); + if (ret) + return -EIO; + + if (chip->config & ADT7410_RESOLUTION) + bits = 16; + else + bits = 13; + + return sprintf(buf, "%d bits\n", bits); +} + +static ssize_t adt7410_store_resolution(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7410_chip_info *chip = dev_info->dev_data; + unsigned long data; + u16 config; + int ret; + + ret = strict_strtoul(buf, 10, &data); + if (ret) + return -EINVAL; + + ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config); + if (ret) + return -EIO; + + config = chip->config & (~ADT7410_RESOLUTION); + if (data) + config |= ADT7410_RESOLUTION; + + ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, config); + if (ret) + return -EIO; + + chip->config = config; + + return ret; +} + +static IIO_DEVICE_ATTR(resolution, S_IRUGO | S_IWUSR, + adt7410_show_resolution, + adt7410_store_resolution, + 0); + +static ssize_t adt7410_show_id(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7410_chip_info *chip = dev_info->dev_data; + u8 id; + int ret; + + ret = adt7410_i2c_read_byte(chip, ADT7410_ID, &id); + if (ret) + return -EIO; + + return sprintf(buf, "device id: 0x%x\nmanufactory id: 0x%x\n", + id & ADT7410_DEVICE_ID_MASK, + (id & ADT7410_MANUFACTORY_ID_MASK) >> ADT7410_MANUFACTORY_ID_OFFSET); +} + +static IIO_DEVICE_ATTR(id, S_IRUGO | S_IWUSR, + adt7410_show_id, + NULL, + 0); + +static ssize_t adt7410_convert_temperature(struct adt7410_chip_info *chip, + u16 data, char *buf) +{ + char sign = ' '; + + if (chip->config & ADT7410_RESOLUTION) { + if (data & ADT7410_T16_VALUE_SIGN) { + /* convert supplement to positive value */ + data = (u16)((ADT7410_T16_VALUE_SIGN << 1) - (u32)data); + sign = '-'; + } + return sprintf(buf, "%c%d.%.7d\n", sign, + (data >> ADT7410_T16_VALUE_FLOAT_OFFSET), + (data & ADT7410_T16_VALUE_FLOAT_MASK) * 78125); + } else { + if (data & ADT7410_T13_VALUE_SIGN) { + /* convert supplement to positive value */ + data >>= ADT7410_T13_VALUE_OFFSET; + data = (ADT7410_T13_VALUE_SIGN << 1) - data; + sign = '-'; + } + return sprintf(buf, "%c%d.%.4d\n", sign, + (data >> ADT7410_T13_VALUE_FLOAT_OFFSET), + (data & ADT7410_T13_VALUE_FLOAT_MASK) * 625); + } +} + +static ssize_t adt7410_show_value(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7410_chip_info *chip = dev_info->dev_data; + u8 status; + u16 data; + int ret, i = 0; + + do { + ret = adt7410_i2c_read_byte(chip, ADT7410_STATUS, &status); + if (ret) + return -EIO; + i++; + if (i == 10000) + return -EIO; + } while (status & ADT7410_STAT_NOT_RDY); + + ret = adt7410_i2c_read_word(chip, ADT7410_TEMPERATURE, &data); + if (ret) + return -EIO; + + return adt7410_convert_temperature(chip, data, buf); +} + +static IIO_DEVICE_ATTR(value, S_IRUGO, adt7410_show_value, NULL, 0); + +static ssize_t adt7410_show_name(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7410_chip_info *chip = dev_info->dev_data; + return sprintf(buf, "%s\n", chip->name); +} + +static IIO_DEVICE_ATTR(name, S_IRUGO, adt7410_show_name, NULL, 0); + +static struct attribute *adt7410_attributes[] = { + &iio_dev_attr_available_modes.dev_attr.attr, + &iio_dev_attr_mode.dev_attr.attr, + &iio_dev_attr_resolution.dev_attr.attr, + &iio_dev_attr_id.dev_attr.attr, + &iio_dev_attr_value.dev_attr.attr, + &iio_dev_attr_name.dev_attr.attr, + NULL, +}; + +static const struct attribute_group adt7410_attribute_group = { + .attrs = adt7410_attributes, +}; + +/* + * temperature bound events + */ + +#define IIO_EVENT_CODE_ADT7410_ABOVE_ALARM IIO_BUFFER_EVENT_CODE(0) +#define IIO_EVENT_CODE_ADT7410_BELLOW_ALARM IIO_BUFFER_EVENT_CODE(1) +#define IIO_EVENT_CODE_ADT7410_ABOVE_CRIT IIO_BUFFER_EVENT_CODE(2) + +static void adt7410_interrupt_bh(struct work_struct *work_s) +{ + struct adt7410_chip_info *chip = + container_of(work_s, struct adt7410_chip_info, thresh_work); + u8 status; + + if (adt7410_i2c_read_byte(chip, ADT7410_STATUS, &status)) + return; + + enable_irq(chip->client->irq); + + if (status & ADT7410_STAT_T_HIGH) + iio_push_event(chip->indio_dev, 0, + IIO_EVENT_CODE_ADT7410_ABOVE_ALARM, + chip->last_timestamp); + if (status & ADT7410_STAT_T_LOW) + iio_push_event(chip->indio_dev, 0, + IIO_EVENT_CODE_ADT7410_BELLOW_ALARM, + chip->last_timestamp); + if (status & ADT7410_STAT_T_CRIT) + iio_push_event(chip->indio_dev, 0, + IIO_EVENT_CODE_ADT7410_ABOVE_CRIT, + chip->last_timestamp); +} + +static int adt7410_interrupt(struct iio_dev *dev_info, + int index, + s64 timestamp, + int no_test) +{ + struct adt7410_chip_info *chip = dev_info->dev_data; + + chip->last_timestamp = timestamp; + schedule_work(&chip->thresh_work); + + return 0; +} + +IIO_EVENT_SH(adt7410, &adt7410_interrupt); +IIO_EVENT_SH(adt7410_ct, &adt7410_interrupt); + +static ssize_t adt7410_show_event_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7410_chip_info *chip = dev_info->dev_data; + int ret; + + ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config); + if (ret) + return -EIO; + + if (chip->config & ADT7410_EVENT_MODE) + return sprintf(buf, "interrupt\n"); + else + return sprintf(buf, "comparator\n"); +} + +static ssize_t adt7410_set_event_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7410_chip_info *chip = dev_info->dev_data; + u16 config; + int ret; + + ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config); + if (ret) + return -EIO; + + config = chip->config &= ~ADT7410_EVENT_MODE; + if (strcmp(buf, "comparator") != 0) + config |= ADT7410_EVENT_MODE; + + ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, config); + if (ret) + return -EIO; + + chip->config = config; + + return ret; +} + +static ssize_t adt7410_show_available_event_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "comparator\ninterrupt\n"); +} + +static ssize_t adt7410_show_fault_queue(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7410_chip_info *chip = dev_info->dev_data; + int ret; + + ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config); + if (ret) + return -EIO; + + return sprintf(buf, "%d\n", chip->config & ADT7410_FAULT_QUEUE_MASK); +} + +static ssize_t adt7410_set_fault_queue(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7410_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + u8 config; + + ret = strict_strtoul(buf, 10, &data); + if (ret || data > 3) + return -EINVAL; + + ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config); + if (ret) + return -EIO; + + config = chip->config & ~ADT7410_FAULT_QUEUE_MASK; + config |= data; + ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, config); + if (ret) + return -EIO; + + chip->config = config; + + return ret; +} + +static inline ssize_t adt7410_show_t_bound(struct device *dev, + struct device_attribute *attr, + u8 bound_reg, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7410_chip_info *chip = dev_info->dev_data; + u16 data; + int ret; + + ret = adt7410_i2c_read_word(chip, bound_reg, &data); + if (ret) + return -EIO; + + return adt7410_convert_temperature(chip, data, buf); +} + +static inline ssize_t adt7410_set_t_bound(struct device *dev, + struct device_attribute *attr, + u8 bound_reg, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7410_chip_info *chip = dev_info->dev_data; + long tmp1, tmp2; + u16 data; + char *pos; + int ret; + + pos = strchr(buf, '.'); + + ret = strict_strtol(buf, 10, &tmp1); + + if (ret || tmp1 > 127 || tmp1 < -128) + return -EINVAL; + + if (pos) { + len = strlen(pos); + + if (chip->config & ADT7410_RESOLUTION) { + if (len > ADT7410_T16_VALUE_FLOAT_OFFSET) + len = ADT7410_T16_VALUE_FLOAT_OFFSET; + pos[len] = 0; + ret = strict_strtol(pos, 10, &tmp2); + + if (!ret) + tmp2 = (tmp2 / 78125) * 78125; + } else { + if (len > ADT7410_T13_VALUE_FLOAT_OFFSET) + len = ADT7410_T13_VALUE_FLOAT_OFFSET; + pos[len] = 0; + ret = strict_strtol(pos, 10, &tmp2); + + if (!ret) + tmp2 = (tmp2 / 625) * 625; + } + } + + if (tmp1 < 0) + data = (u16)(-tmp1); + else + data = (u16)tmp1; + + if (chip->config & ADT7410_RESOLUTION) { + data = (data << ADT7410_T16_VALUE_FLOAT_OFFSET) | + (tmp2 & ADT7410_T16_VALUE_FLOAT_MASK); + + if (tmp1 < 0) + /* convert positive value to supplyment */ + data = (u16)((ADT7410_T16_VALUE_SIGN << 1) - (u32)data); + } else { + data = (data << ADT7410_T13_VALUE_FLOAT_OFFSET) | + (tmp2 & ADT7410_T13_VALUE_FLOAT_MASK); + + if (tmp1 < 0) + /* convert positive value to supplyment */ + data = (ADT7410_T13_VALUE_SIGN << 1) - data; + data <<= ADT7410_T13_VALUE_OFFSET; + } + + ret = adt7410_i2c_write_word(chip, bound_reg, data); + if (ret) + return -EIO; + + return ret; +} + +static ssize_t adt7410_show_t_alarm_high(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return adt7410_show_t_bound(dev, attr, + ADT7410_T_ALARM_HIGH, buf); +} + +static inline ssize_t adt7410_set_t_alarm_high(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return adt7410_set_t_bound(dev, attr, + ADT7410_T_ALARM_HIGH, buf, len); +} + +static ssize_t adt7410_show_t_alarm_low(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return adt7410_show_t_bound(dev, attr, + ADT7410_T_ALARM_LOW, buf); +} + +static inline ssize_t adt7410_set_t_alarm_low(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return adt7410_set_t_bound(dev, attr, + ADT7410_T_ALARM_LOW, buf, len); +} + +static ssize_t adt7410_show_t_crit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return adt7410_show_t_bound(dev, attr, + ADT7410_T_CRIT, buf); +} + +static inline ssize_t adt7410_set_t_crit(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return adt7410_set_t_bound(dev, attr, + ADT7410_T_CRIT, buf, len); +} + +static ssize_t adt7410_show_t_hyst(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7410_chip_info *chip = dev_info->dev_data; + int ret; + u8 t_hyst; + + ret = adt7410_i2c_read_byte(chip, ADT7410_T_HYST, &t_hyst); + if (ret) + return -EIO; + + return sprintf(buf, "%d\n", t_hyst & ADT7410_T_HYST_MASK); +} + +static inline ssize_t adt7410_set_t_hyst(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7410_chip_info *chip = dev_info->dev_data; + int ret; + unsigned long data; + u8 t_hyst; + + ret = strict_strtol(buf, 10, &data); + + if (ret || data > ADT7410_T_HYST_MASK) + return -EINVAL; + + t_hyst = (u8)data; + + ret = adt7410_i2c_write_byte(chip, ADT7410_T_HYST, t_hyst); + if (ret) + return -EIO; + + return ret; +} + +IIO_EVENT_ATTR_SH(event_mode, iio_event_adt7410, + adt7410_show_event_mode, adt7410_set_event_mode, 0); +IIO_EVENT_ATTR_SH(available_event_modes, iio_event_adt7410, + adt7410_show_available_event_modes, NULL, 0); +IIO_EVENT_ATTR_SH(fault_queue, iio_event_adt7410, + adt7410_show_fault_queue, adt7410_set_fault_queue, 0); +IIO_EVENT_ATTR_SH(t_alarm_high, iio_event_adt7410, + adt7410_show_t_alarm_high, adt7410_set_t_alarm_high, 0); +IIO_EVENT_ATTR_SH(t_alarm_low, iio_event_adt7410, + adt7410_show_t_alarm_low, adt7410_set_t_alarm_low, 0); +IIO_EVENT_ATTR_SH(t_crit, iio_event_adt7410_ct, + adt7410_show_t_crit, adt7410_set_t_crit, 0); +IIO_EVENT_ATTR_SH(t_hyst, iio_event_adt7410, + adt7410_show_t_hyst, adt7410_set_t_hyst, 0); + +static struct attribute *adt7410_event_int_attributes[] = { + &iio_event_attr_event_mode.dev_attr.attr, + &iio_event_attr_available_event_modes.dev_attr.attr, + &iio_event_attr_fault_queue.dev_attr.attr, + &iio_event_attr_t_alarm_high.dev_attr.attr, + &iio_event_attr_t_alarm_low.dev_attr.attr, + &iio_event_attr_t_hyst.dev_attr.attr, + NULL, +}; + +static struct attribute *adt7410_event_ct_attributes[] = { + &iio_event_attr_event_mode.dev_attr.attr, + &iio_event_attr_available_event_modes.dev_attr.attr, + &iio_event_attr_fault_queue.dev_attr.attr, + &iio_event_attr_t_crit.dev_attr.attr, + &iio_event_attr_t_hyst.dev_attr.attr, + NULL, +}; + +static struct attribute_group adt7410_event_attribute_group[ADT7410_IRQS] = { + { + .attrs = adt7410_event_int_attributes, + }, + { + .attrs = adt7410_event_ct_attributes, + } +}; + +/* + * device probe and remove + */ + +static int __devinit adt7410_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct adt7410_chip_info *chip; + int ret = 0; + unsigned long *adt7410_platform_data = client->dev.platform_data; + + chip = kzalloc(sizeof(struct adt7410_chip_info), GFP_KERNEL); + + if (chip == NULL) + return -ENOMEM; + + /* this is only used for device removal purposes */ + i2c_set_clientdata(client, chip); + + chip->client = client; + chip->name = id->name; + + chip->indio_dev = iio_allocate_device(); + if (chip->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_chip; + } + + chip->indio_dev->dev.parent = &client->dev; + chip->indio_dev->attrs = &adt7410_attribute_group; + chip->indio_dev->event_attrs = adt7410_event_attribute_group; + chip->indio_dev->dev_data = (void *)chip; + chip->indio_dev->driver_module = THIS_MODULE; + chip->indio_dev->num_interrupt_lines = ADT7410_IRQS; + chip->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(chip->indio_dev); + if (ret) + goto error_free_dev; + + /* CT critcal temperature event. line 0 */ + if (client->irq) { + ret = iio_register_interrupt_line(client->irq, + chip->indio_dev, + 0, + IRQF_TRIGGER_LOW, + chip->name); + if (ret) + goto error_unreg_dev; + + /* + * The event handler list element refer to iio_event_adt7410. + * All event attributes bind to the same event handler. + * One event handler can only be added to one event list. + */ + iio_add_event_to_list(&iio_event_adt7410, + &chip->indio_dev->interrupts[0]->ev_list); + } + + /* INT bound temperature alarm event. line 1 */ + if (adt7410_platform_data[0]) { + ret = iio_register_interrupt_line(adt7410_platform_data[0], + chip->indio_dev, + 1, + adt7410_platform_data[1], + chip->name); + if (ret) + goto error_unreg_ct_irq; + + /* + * The event handler list element refer to iio_event_adt7410. + * All event attributes bind to the same event handler. + * One event handler can only be added to one event list. + */ + iio_add_event_to_list(&iio_event_adt7410_ct, + &chip->indio_dev->interrupts[1]->ev_list); + } + + if (client->irq && adt7410_platform_data[0]) { + INIT_WORK(&chip->thresh_work, adt7410_interrupt_bh); + + ret = adt7410_i2c_read_byte(chip, ADT7410_CONFIG, &chip->config); + if (ret) { + ret = -EIO; + goto error_unreg_int_irq; + } + + /* set irq polarity low level */ + chip->config &= ~ADT7410_CT_POLARITY; + + if (adt7410_platform_data[1] & IRQF_TRIGGER_HIGH) + chip->config |= ADT7410_INT_POLARITY; + else + chip->config &= ~ADT7410_INT_POLARITY; + + ret = adt7410_i2c_write_byte(chip, ADT7410_CONFIG, chip->config); + if (ret) { + ret = -EIO; + goto error_unreg_int_irq; + } + } + + dev_info(&client->dev, "%s temperature sensor registered.\n", + id->name); + + return 0; + +error_unreg_int_irq: + iio_unregister_interrupt_line(chip->indio_dev, 1); +error_unreg_ct_irq: + iio_unregister_interrupt_line(chip->indio_dev, 0); +error_unreg_dev: + iio_device_unregister(chip->indio_dev); +error_free_dev: + iio_free_device(chip->indio_dev); +error_free_chip: + kfree(chip); + + return ret; +} + +static int __devexit adt7410_remove(struct i2c_client *client) +{ + struct adt7410_chip_info *chip = i2c_get_clientdata(client); + struct iio_dev *indio_dev = chip->indio_dev; + unsigned long *adt7410_platform_data = client->dev.platform_data; + + if (adt7410_platform_data[0]) + iio_unregister_interrupt_line(indio_dev, 1); + if (client->irq) + iio_unregister_interrupt_line(indio_dev, 0); + iio_device_unregister(indio_dev); + iio_free_device(chip->indio_dev); + kfree(chip); + + return 0; +} + +static const struct i2c_device_id adt7410_id[] = { + { "adt7410", 0 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, adt7410_id); + +static struct i2c_driver adt7410_driver = { + .driver = { + .name = "adt7410", + }, + .probe = adt7410_probe, + .remove = __devexit_p(adt7410_remove), + .id_table = adt7410_id, +}; + +static __init int adt7410_init(void) +{ + return i2c_add_driver(&adt7410_driver); +} + +static __exit void adt7410_exit(void) +{ + i2c_del_driver(&adt7410_driver); +} + +MODULE_AUTHOR("Sonic Zhang "); +MODULE_DESCRIPTION("Analog Devices ADT7410 digital" + " temperature sensor driver"); +MODULE_LICENSE("GPL v2"); + +module_init(adt7410_init); +module_exit(adt7410_exit); diff --git a/trunk/drivers/staging/iio/adc/adt75.c b/trunk/drivers/staging/iio/adc/adt75.c new file mode 100644 index 000000000000..aff4d31eb89c --- /dev/null +++ b/trunk/drivers/staging/iio/adc/adt75.c @@ -0,0 +1,732 @@ +/* + * ADT75 digital temperature sensor driver supporting ADT75 + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +/* + * ADT75 registers definition + */ + +#define ADT75_TEMPERATURE 0 +#define ADT75_CONFIG 1 +#define ADT75_T_HYST 2 +#define ADT75_T_OS 3 +#define ADT75_ONESHOT 4 + +/* + * ADT75 config + */ +#define ADT75_PD 0x1 +#define ADT75_OS_INT 0x2 +#define ADT75_OS_POLARITY 0x4 +#define ADT75_FAULT_QUEUE_MASK 0x18 +#define ADT75_FAULT_QUEUE_OFFSET 3 +#define ADT75_SMBUS_ALART 0x8 + +/* + * ADT75 masks + */ +#define ADT75_VALUE_SIGN 0x800 +#define ADT75_VALUE_OFFSET 4 +#define ADT75_VALUE_FLOAT_OFFSET 4 +#define ADT75_VALUE_FLOAT_MASK 0xF + + +/* + * struct adt75_chip_info - chip specifc information + */ + +struct adt75_chip_info { + const char *name; + struct i2c_client *client; + struct iio_dev *indio_dev; + struct work_struct thresh_work; + s64 last_timestamp; + u8 config; +}; + +/* + * adt75 register access by I2C + */ + +static int adt75_i2c_read(struct adt75_chip_info *chip, u8 reg, u8 *data) +{ + struct i2c_client *client = chip->client; + int ret = 0, len; + + ret = i2c_smbus_write_byte(client, reg); + if (ret < 0) { + dev_err(&client->dev, "I2C read register address error\n"); + return ret; + } + + if (reg == ADT75_CONFIG || reg == ADT75_ONESHOT) + len = 1; + else + len = 2; + + ret = i2c_master_recv(client, data, len); + if (ret < 0) { + dev_err(&client->dev, "I2C read error\n"); + return ret; + } + + return ret; +} + +static int adt75_i2c_write(struct adt75_chip_info *chip, u8 reg, u8 data) +{ + struct i2c_client *client = chip->client; + int ret = 0; + + if (reg == ADT75_CONFIG || reg == ADT75_ONESHOT) + ret = i2c_smbus_write_byte_data(client, reg, data); + else + ret = i2c_smbus_write_word_data(client, reg, data); + + if (ret < 0) + dev_err(&client->dev, "I2C write error\n"); + + return ret; +} + +static ssize_t adt75_show_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt75_chip_info *chip = dev_info->dev_data; + + if (chip->config & ADT75_PD) + return sprintf(buf, "power-save\n"); + else + return sprintf(buf, "full\n"); +} + +static ssize_t adt75_store_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt75_chip_info *chip = dev_info->dev_data; + int ret; + u8 config; + + ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config); + if (ret) + return -EIO; + + config = chip->config & ~ADT75_PD; + if (!strcmp(buf, "full")) + config |= ADT75_PD; + + ret = adt75_i2c_write(chip, ADT75_CONFIG, config); + if (ret) + return -EIO; + + chip->config = config; + + return ret; +} + +static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, + adt75_show_mode, + adt75_store_mode, + 0); + +static ssize_t adt75_show_available_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "full\npower-down\n"); +} + +static IIO_DEVICE_ATTR(available_modes, S_IRUGO, adt75_show_available_modes, NULL, 0); + +static ssize_t adt75_show_oneshot(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt75_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", !!(chip->config & ADT75_ONESHOT)); +} + +static ssize_t adt75_store_oneshot(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt75_chip_info *chip = dev_info->dev_data; + unsigned long data = 0; + int ret; + u8 config; + + ret = strict_strtoul(buf, 10, &data); + if (ret) + return -EINVAL; + + + ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config); + if (ret) + return -EIO; + + config = chip->config & ~ADT75_ONESHOT; + if (data) + config |= ADT75_ONESHOT; + + ret = adt75_i2c_write(chip, ADT75_CONFIG, config); + if (ret) + return -EIO; + + chip->config = config; + + return ret; +} + +static IIO_DEVICE_ATTR(oneshot, S_IRUGO | S_IWUSR, + adt75_show_oneshot, + adt75_store_oneshot, + 0); + +static ssize_t adt75_show_value(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt75_chip_info *chip = dev_info->dev_data; + u16 data; + char sign = ' '; + int ret; + + if (chip->config & ADT75_PD) { + dev_err(dev, "Can't read value in power-down mode.\n"); + return -EIO; + } + + if (chip->config & ADT75_ONESHOT) { + /* write to active converter */ + ret = i2c_smbus_write_byte(chip->client, ADT75_ONESHOT); + if (ret) + return -EIO; + } + + ret = adt75_i2c_read(chip, ADT75_TEMPERATURE, (u8 *)&data); + if (ret) + return -EIO; + + data = swab16(data) >> ADT75_VALUE_OFFSET; + if (data & ADT75_VALUE_SIGN) { + /* convert supplement to positive value */ + data = (ADT75_VALUE_SIGN << 1) - data; + sign = '-'; + } + + return sprintf(buf, "%c%d.%.4d\n", sign, + (data >> ADT75_VALUE_FLOAT_OFFSET), + (data & ADT75_VALUE_FLOAT_MASK) * 625); +} + +static IIO_DEVICE_ATTR(value, S_IRUGO, adt75_show_value, NULL, 0); + +static ssize_t adt75_show_name(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt75_chip_info *chip = dev_info->dev_data; + return sprintf(buf, "%s\n", chip->name); +} + +static IIO_DEVICE_ATTR(name, S_IRUGO, adt75_show_name, NULL, 0); + +static struct attribute *adt75_attributes[] = { + &iio_dev_attr_available_modes.dev_attr.attr, + &iio_dev_attr_mode.dev_attr.attr, + &iio_dev_attr_oneshot.dev_attr.attr, + &iio_dev_attr_value.dev_attr.attr, + &iio_dev_attr_name.dev_attr.attr, + NULL, +}; + +static const struct attribute_group adt75_attribute_group = { + .attrs = adt75_attributes, +}; + +/* + * temperature bound events + */ + +#define IIO_EVENT_CODE_ADT75_OTI IIO_BUFFER_EVENT_CODE(0) + +static void adt75_interrupt_bh(struct work_struct *work_s) +{ + struct adt75_chip_info *chip = + container_of(work_s, struct adt75_chip_info, thresh_work); + + enable_irq(chip->client->irq); + + iio_push_event(chip->indio_dev, 0, + IIO_EVENT_CODE_ADT75_OTI, + chip->last_timestamp); +} + +static int adt75_interrupt(struct iio_dev *dev_info, + int index, + s64 timestamp, + int no_test) +{ + struct adt75_chip_info *chip = dev_info->dev_data; + + chip->last_timestamp = timestamp; + schedule_work(&chip->thresh_work); + + return 0; +} + +IIO_EVENT_SH(adt75, &adt75_interrupt); + +static ssize_t adt75_show_oti_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt75_chip_info *chip = dev_info->dev_data; + int ret; + + /* retrive ALART status */ + ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config); + if (ret) + return -EIO; + + if (chip->config & ADT75_OS_INT) + return sprintf(buf, "interrupt\n"); + else + return sprintf(buf, "comparator\n"); +} + +static ssize_t adt75_set_oti_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt75_chip_info *chip = dev_info->dev_data; + int ret; + u8 config; + + /* retrive ALART status */ + ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config); + if (ret) + return -EIO; + + config = chip->config & ~ADT75_OS_INT; + if (strcmp(buf, "comparator") != 0) + config |= ADT75_OS_INT; + + ret = adt75_i2c_write(chip, ADT75_CONFIG, config); + if (ret) + return -EIO; + + chip->config = config; + + return ret; +} + +static ssize_t adt75_show_available_oti_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "comparator\ninterrupt\n"); +} + +static ssize_t adt75_show_smbus_alart(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt75_chip_info *chip = dev_info->dev_data; + int ret; + + /* retrive ALART status */ + ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config); + if (ret) + return -EIO; + + return sprintf(buf, "%d\n", !!(chip->config & ADT75_SMBUS_ALART)); +} + +static ssize_t adt75_set_smbus_alart(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt75_chip_info *chip = dev_info->dev_data; + unsigned long data = 0; + int ret; + u8 config; + + ret = strict_strtoul(buf, 10, &data); + if (ret) + return -EINVAL; + + /* retrive ALART status */ + ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config); + if (ret) + return -EIO; + + config = chip->config & ~ADT75_SMBUS_ALART; + if (data) + config |= ADT75_SMBUS_ALART; + + ret = adt75_i2c_write(chip, ADT75_CONFIG, config); + if (ret) + return -EIO; + + chip->config = config; + + return ret; +} + +static ssize_t adt75_show_fault_queue(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt75_chip_info *chip = dev_info->dev_data; + int ret; + + /* retrive ALART status */ + ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config); + if (ret) + return -EIO; + + return sprintf(buf, "%d\n", (chip->config & ADT75_FAULT_QUEUE_MASK) >> + ADT75_FAULT_QUEUE_OFFSET); +} + +static ssize_t adt75_set_fault_queue(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt75_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + u8 config; + + ret = strict_strtoul(buf, 10, &data); + if (ret || data > 3) + return -EINVAL; + + /* retrive ALART status */ + ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config); + if (ret) + return -EIO; + + config = chip->config & ~ADT75_FAULT_QUEUE_MASK; + config |= (data << ADT75_FAULT_QUEUE_OFFSET); + ret = adt75_i2c_write(chip, ADT75_CONFIG, config); + if (ret) + return -EIO; + + chip->config = config; + + return ret; +} +static inline ssize_t adt75_show_t_bound(struct device *dev, + struct device_attribute *attr, + u8 bound_reg, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt75_chip_info *chip = dev_info->dev_data; + u16 data; + char sign = ' '; + int ret; + + ret = adt75_i2c_read(chip, bound_reg, (u8 *)&data); + if (ret) + return -EIO; + + data = swab16(data) >> ADT75_VALUE_OFFSET; + if (data & ADT75_VALUE_SIGN) { + /* convert supplement to positive value */ + data = (ADT75_VALUE_SIGN << 1) - data; + sign = '-'; + } + + return sprintf(buf, "%c%d.%.4d\n", sign, + (data >> ADT75_VALUE_FLOAT_OFFSET), + (data & ADT75_VALUE_FLOAT_MASK) * 625); +} + +static inline ssize_t adt75_set_t_bound(struct device *dev, + struct device_attribute *attr, + u8 bound_reg, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt75_chip_info *chip = dev_info->dev_data; + long tmp1, tmp2; + u16 data; + char *pos; + int ret; + + pos = strchr(buf, '.'); + + ret = strict_strtol(buf, 10, &tmp1); + + if (ret || tmp1 > 127 || tmp1 < -128) + return -EINVAL; + + if (pos) { + len = strlen(pos); + if (len > ADT75_VALUE_FLOAT_OFFSET) + len = ADT75_VALUE_FLOAT_OFFSET; + pos[len] = 0; + ret = strict_strtol(pos, 10, &tmp2); + + if (!ret) + tmp2 = (tmp2 / 625) * 625; + } + + if (tmp1 < 0) + data = (u16)(-tmp1); + else + data = (u16)tmp1; + data = (data << ADT75_VALUE_FLOAT_OFFSET) | (tmp2 & ADT75_VALUE_FLOAT_MASK); + if (tmp1 < 0) + /* convert positive value to supplyment */ + data = (ADT75_VALUE_SIGN << 1) - data; + data <<= ADT75_VALUE_OFFSET; + data = swab16(data); + + ret = adt75_i2c_write(chip, bound_reg, (u8)data); + if (ret) + return -EIO; + + return ret; +} + +static ssize_t adt75_show_t_os(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return adt75_show_t_bound(dev, attr, + ADT75_T_OS, buf); +} + +static inline ssize_t adt75_set_t_os(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return adt75_set_t_bound(dev, attr, + ADT75_T_OS, buf, len); +} + +static ssize_t adt75_show_t_hyst(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return adt75_show_t_bound(dev, attr, + ADT75_T_HYST, buf); +} + +static inline ssize_t adt75_set_t_hyst(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return adt75_set_t_bound(dev, attr, + ADT75_T_HYST, buf, len); +} + +IIO_EVENT_ATTR_SH(oti_mode, iio_event_adt75, + adt75_show_oti_mode, adt75_set_oti_mode, 0); +IIO_EVENT_ATTR_SH(available_oti_modes, iio_event_adt75, + adt75_show_available_oti_modes, NULL, 0); +IIO_EVENT_ATTR_SH(smbus_alart, iio_event_adt75, + adt75_show_smbus_alart, adt75_set_smbus_alart, 0); +IIO_EVENT_ATTR_SH(fault_queue, iio_event_adt75, + adt75_show_fault_queue, adt75_set_fault_queue, 0); +IIO_EVENT_ATTR_SH(t_os, iio_event_adt75, + adt75_show_t_os, adt75_set_t_os, 0); +IIO_EVENT_ATTR_SH(t_hyst, iio_event_adt75, + adt75_show_t_hyst, adt75_set_t_hyst, 0); + +static struct attribute *adt75_event_attributes[] = { + &iio_event_attr_oti_mode.dev_attr.attr, + &iio_event_attr_available_oti_modes.dev_attr.attr, + &iio_event_attr_smbus_alart.dev_attr.attr, + &iio_event_attr_fault_queue.dev_attr.attr, + &iio_event_attr_t_os.dev_attr.attr, + &iio_event_attr_t_hyst.dev_attr.attr, + NULL, +}; + +static struct attribute_group adt75_event_attribute_group = { + .attrs = adt75_event_attributes, +}; + +/* + * device probe and remove + */ + +static int __devinit adt75_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct adt75_chip_info *chip; + int ret = 0; + + chip = kzalloc(sizeof(struct adt75_chip_info), GFP_KERNEL); + + if (chip == NULL) + return -ENOMEM; + + /* this is only used for device removal purposes */ + i2c_set_clientdata(client, chip); + + chip->client = client; + chip->name = id->name; + + chip->indio_dev = iio_allocate_device(); + if (chip->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_chip; + } + + chip->indio_dev->dev.parent = &client->dev; + chip->indio_dev->attrs = &adt75_attribute_group; + chip->indio_dev->event_attrs = &adt75_event_attribute_group; + chip->indio_dev->dev_data = (void *)chip; + chip->indio_dev->driver_module = THIS_MODULE; + chip->indio_dev->num_interrupt_lines = 1; + chip->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(chip->indio_dev); + if (ret) + goto error_free_dev; + + if (client->irq > 0) { + ret = iio_register_interrupt_line(client->irq, + chip->indio_dev, + 0, + IRQF_TRIGGER_LOW, + chip->name); + if (ret) + goto error_unreg_dev; + + /* + * The event handler list element refer to iio_event_adt75. + * All event attributes bind to the same event handler. + * So, only register event handler once. + */ + iio_add_event_to_list(&iio_event_adt75, + &chip->indio_dev->interrupts[0]->ev_list); + + INIT_WORK(&chip->thresh_work, adt75_interrupt_bh); + + ret = adt75_i2c_read(chip, ADT75_CONFIG, &chip->config); + if (ret) { + ret = -EIO; + goto error_unreg_irq; + } + + /* set irq polarity low level */ + chip->config &= ~ADT75_OS_POLARITY; + + ret = adt75_i2c_write(chip, ADT75_CONFIG, chip->config); + if (ret) { + ret = -EIO; + goto error_unreg_irq; + } + } + + dev_info(&client->dev, "%s temperature sensor registered.\n", + id->name); + + return 0; +error_unreg_irq: + iio_unregister_interrupt_line(chip->indio_dev, 0); +error_unreg_dev: + iio_device_unregister(chip->indio_dev); +error_free_dev: + iio_free_device(chip->indio_dev); +error_free_chip: + kfree(chip); + + return ret; +} + +static int __devexit adt75_remove(struct i2c_client *client) +{ + struct adt75_chip_info *chip = i2c_get_clientdata(client); + struct iio_dev *indio_dev = chip->indio_dev; + + if (client->irq) + iio_unregister_interrupt_line(indio_dev, 0); + iio_device_unregister(indio_dev); + iio_free_device(chip->indio_dev); + kfree(chip); + + return 0; +} + +static const struct i2c_device_id adt75_id[] = { + { "adt75", 0 }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, adt75_id); + +static struct i2c_driver adt75_driver = { + .driver = { + .name = "adt75", + }, + .probe = adt75_probe, + .remove = __devexit_p(adt75_remove), + .id_table = adt75_id, +}; + +static __init int adt75_init(void) +{ + return i2c_add_driver(&adt75_driver); +} + +static __exit void adt75_exit(void) +{ + i2c_del_driver(&adt75_driver); +} + +MODULE_AUTHOR("Sonic Zhang "); +MODULE_DESCRIPTION("Analog Devices ADT75 digital" + " temperature sensor driver"); +MODULE_LICENSE("GPL v2"); + +module_init(adt75_init); +module_exit(adt75_exit); diff --git a/trunk/drivers/staging/iio/addac/Kconfig b/trunk/drivers/staging/iio/addac/Kconfig new file mode 100644 index 000000000000..9847baf02700 --- /dev/null +++ b/trunk/drivers/staging/iio/addac/Kconfig @@ -0,0 +1,25 @@ +# +# ADDAC drivers +# +comment "Analog digital bi-direction convertors" + +config ADT7316 + tristate "Analog Devices ADT7316/7/8 ADT7516/7/9 temperature sensor, ADC and DAC driver" + help + Say yes here to build support for Analog Devices ADT7316, ADT7317, ADT7318 + and ADT7516, ADT7517, ADT7519 temperature sensors, ADC and DAC. + +config ADT7316_SPI + tristate "support SPI bus connection" + depends on SPI && ADT7316 + default y + help + Say yes here to build SPI bus support for Analog Devices ADT7316/7/8 + and ADT7516/7/9. + +config ADT7316_I2C + tristate "support I2C bus connection" + depends on I2C && ADT7316 + help + Say yes here to build I2C bus support for Analog Devices ADT7316/7/8 + and ADT7516/7/9. diff --git a/trunk/drivers/staging/iio/addac/Makefile b/trunk/drivers/staging/iio/addac/Makefile new file mode 100644 index 000000000000..4c7686133692 --- /dev/null +++ b/trunk/drivers/staging/iio/addac/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for industrial I/O ADDAC drivers +# + +obj-$(CONFIG_ADT7316) += adt7316.o +obj-$(CONFIG_ADT7316_SPI) += adt7316-spi.o +obj-$(CONFIG_ADT7316_I2C) += adt7316-i2c.o diff --git a/trunk/drivers/staging/iio/addac/adt7316-i2c.c b/trunk/drivers/staging/iio/addac/adt7316-i2c.c new file mode 100644 index 000000000000..52d1ea349635 --- /dev/null +++ b/trunk/drivers/staging/iio/addac/adt7316-i2c.c @@ -0,0 +1,170 @@ +/* + * I2C bus driver for ADT7316/7/8 ADT7516/7/9 digital temperature + * sensor, ADC and DAC + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include + +#include "adt7316.h" + +/* + * adt7316 register access by I2C + */ +static int adt7316_i2c_read(void *client, u8 reg, u8 *data) +{ + struct i2c_client *cl = client; + int ret = 0; + + ret = i2c_smbus_write_byte(cl, reg); + if (ret < 0) { + dev_err(&cl->dev, "I2C fail to select reg\n"); + return ret; + } + + ret = i2c_smbus_read_byte(client); + if (ret < 0) { + dev_err(&cl->dev, "I2C read error\n"); + return ret; + } + + return 0; +} + +static int adt7316_i2c_write(void *client, u8 reg, u8 data) +{ + struct i2c_client *cl = client; + int ret = 0; + + ret = i2c_smbus_write_byte_data(cl, reg, data); + if (ret < 0) + dev_err(&cl->dev, "I2C write error\n"); + + return ret; +} + +static int adt7316_i2c_multi_read(void *client, u8 reg, u8 count, u8 *data) +{ + struct i2c_client *cl = client; + int i, ret = 0; + + if (count > ADT7316_REG_MAX_ADDR) + count = ADT7316_REG_MAX_ADDR; + + for (i = 0; i < count; i++) { + ret = adt7316_i2c_read(cl, reg, &data[i]); + if (ret < 0) { + dev_err(&cl->dev, "I2C multi read error\n"); + return ret; + } + } + + return 0; +} + +static int adt7316_i2c_multi_write(void *client, u8 reg, u8 count, u8 *data) +{ + struct i2c_client *cl = client; + int i, ret = 0; + + if (count > ADT7316_REG_MAX_ADDR) + count = ADT7316_REG_MAX_ADDR; + + for (i = 0; i < count; i++) { + ret = adt7316_i2c_write(cl, reg, data[i]); + if (ret < 0) { + dev_err(&cl->dev, "I2C multi write error\n"); + return ret; + } + } + + return 0; +} + +/* + * device probe and remove + */ + +static int __devinit adt7316_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct adt7316_bus bus = { + .client = client, + .irq = client->irq, + .irq_flags = IRQF_TRIGGER_LOW, + .read = adt7316_i2c_read, + .write = adt7316_i2c_write, + .multi_read = adt7316_i2c_multi_read, + .multi_write = adt7316_i2c_multi_write, + }; + + return adt7316_probe(&client->dev, &bus, id->name); +} + +static int __devexit adt7316_i2c_remove(struct i2c_client *client) +{ + return adt7316_remove(&client->dev);; +} + +static const struct i2c_device_id adt7316_i2c_id[] = { + { "adt7316", 0 }, + { "adt7317", 0 }, + { "adt7318", 0 }, + { "adt7516", 0 }, + { "adt7517", 0 }, + { "adt7519", 0 }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, adt7316_i2c_id); + +#ifdef CONFIG_PM +static int adt7316_i2c_suspend(struct i2c_client *client, pm_message_t message) +{ + return adt7316_disable(&client->dev); +} + +static int adt7316_i2c_resume(struct i2c_client *client) +{ + return adt7316_enable(&client->dev); +} +#else +# define adt7316_i2c_suspend NULL +# define adt7316_i2c_resume NULL +#endif + +static struct i2c_driver adt7316_driver = { + .driver = { + .name = "adt7316", + .owner = THIS_MODULE, + }, + .probe = adt7316_i2c_probe, + .remove = __devexit_p(adt7316_i2c_remove), + .suspend = adt7316_i2c_suspend, + .resume = adt7316_i2c_resume, + .id_table = adt7316_i2c_id, +}; + +static __init int adt7316_i2c_init(void) +{ + return i2c_add_driver(&adt7316_driver); +} + +static __exit void adt7316_i2c_exit(void) +{ + i2c_del_driver(&adt7316_driver); +} + +MODULE_AUTHOR("Sonic Zhang "); +MODULE_DESCRIPTION("I2C bus driver for Analog Devices ADT7316/7/9 and" + "ADT7516/7/8 digital temperature sensor, ADC and DAC"); +MODULE_LICENSE("GPL v2"); + +module_init(adt7316_i2c_init); +module_exit(adt7316_i2c_exit); diff --git a/trunk/drivers/staging/iio/addac/adt7316-spi.c b/trunk/drivers/staging/iio/addac/adt7316-spi.c new file mode 100644 index 000000000000..369d4d01ed97 --- /dev/null +++ b/trunk/drivers/staging/iio/addac/adt7316-spi.c @@ -0,0 +1,180 @@ +/* + * API bus driver for ADT7316/7/8 ADT7516/7/9 digital temperature + * sensor, ADC and DAC + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include + +#include "adt7316.h" + +#define ADT7316_SPI_MAX_FREQ_HZ 5000000 +#define ADT7316_SPI_CMD_READ 0x91 +#define ADT7316_SPI_CMD_WRITE 0x90 + +/* + * adt7316 register access by SPI + */ + +static int adt7316_spi_multi_read(void *client, u8 reg, u8 count, u8 *data) +{ + struct spi_device *spi_dev = client; + u8 cmd[2]; + int ret = 0; + + if (count > ADT7316_REG_MAX_ADDR) + count = ADT7316_REG_MAX_ADDR; + + cmd[0] = ADT7316_SPI_CMD_WRITE; + cmd[1] = reg; + + ret = spi_write(spi_dev, cmd, 2); + if (ret < 0) { + dev_err(&spi_dev->dev, "SPI fail to select reg\n"); + return ret; + } + + cmd[0] = ADT7316_SPI_CMD_READ; + + ret = spi_write_then_read(spi_dev, cmd, 1, data, count); + if (ret < 0) { + dev_err(&spi_dev->dev, "SPI read data error\n"); + return ret; + } + + return 0; +} + +static int adt7316_spi_multi_write(void *client, u8 reg, u8 count, u8 *data) +{ + struct spi_device *spi_dev = client; + u8 buf[ADT7316_REG_MAX_ADDR + 2]; + int i, ret = 0; + + if (count > ADT7316_REG_MAX_ADDR) + count = ADT7316_REG_MAX_ADDR; + + buf[0] = ADT7316_SPI_CMD_WRITE; + buf[1] = reg; + for (i = 0; i < count; i++) + buf[i + 2] = data[i]; + + ret = spi_write(spi_dev, buf, count + 2); + if (ret < 0) { + dev_err(&spi_dev->dev, "SPI write error\n"); + return ret; + } + + return ret; +} + +static int adt7316_spi_read(void *client, u8 reg, u8 *data) +{ + return adt7316_spi_multi_read(client, reg, 1, data); +} + +static int adt7316_spi_write(void *client, u8 reg, u8 val) +{ + return adt7316_spi_multi_write(client, reg, 1, &val); +} + +/* + * device probe and remove + */ + +static int __devinit adt7316_spi_probe(struct spi_device *spi_dev) +{ + struct adt7316_bus bus = { + .client = spi_dev, + .irq = spi_dev->irq, + .irq_flags = IRQF_TRIGGER_LOW, + .read = adt7316_spi_read, + .write = adt7316_spi_write, + .multi_read = adt7316_spi_multi_read, + .multi_write = adt7316_spi_multi_write, + }; + + /* don't exceed max specified SPI CLK frequency */ + if (spi_dev->max_speed_hz > ADT7316_SPI_MAX_FREQ_HZ) { + dev_err(&spi_dev->dev, "SPI CLK %d Hz?\n", + spi_dev->max_speed_hz); + return -EINVAL; + } + + /* switch from default I2C protocol to SPI protocol */ + adt7316_spi_write(spi_dev, 0, 0); + adt7316_spi_write(spi_dev, 0, 0); + adt7316_spi_write(spi_dev, 0, 0); + + return adt7316_probe(&spi_dev->dev, &bus, spi_dev->modalias); +} + +static int __devexit adt7316_spi_remove(struct spi_device *spi_dev) +{ + return adt7316_remove(&spi_dev->dev); +} + +static const struct spi_device_id adt7316_spi_id[] = { + { "adt7316", 0 }, + { "adt7317", 0 }, + { "adt7318", 0 }, + { "adt7516", 0 }, + { "adt7517", 0 }, + { "adt7519", 0 }, + { } +}; + +MODULE_DEVICE_TABLE(spi, adt7316_spi_id); + +#ifdef CONFIG_PM +static int adt7316_spi_suspend(struct spi_device *spi_dev, pm_message_t message) +{ + return adt7316_disable(&spi_dev->dev); +} + +static int adt7316_spi_resume(struct spi_device *spi_dev) +{ + return adt7316_enable(&spi_dev->dev); +} +#else +# define adt7316_spi_suspend NULL +# define adt7316_spi_resume NULL +#endif + +static struct spi_driver adt7316_driver = { + .driver = { + .name = "adt7316", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = adt7316_spi_probe, + .remove = __devexit_p(adt7316_spi_remove), + .suspend = adt7316_spi_suspend, + .resume = adt7316_spi_resume, + .id_table = adt7316_spi_id, +}; + +static __init int adt7316_spi_init(void) +{ + return spi_register_driver(&adt7316_driver); +} + +static __exit void adt7316_spi_exit(void) +{ + spi_unregister_driver(&adt7316_driver); +} + +MODULE_AUTHOR("Sonic Zhang "); +MODULE_DESCRIPTION("SPI bus driver for Analog Devices ADT7316/7/8 and" + "ADT7516/7/9 digital temperature sensor, ADC and DAC"); +MODULE_LICENSE("GPL v2"); + +module_init(adt7316_spi_init); +module_exit(adt7316_spi_exit); diff --git a/trunk/drivers/staging/iio/addac/adt7316.c b/trunk/drivers/staging/iio/addac/adt7316.c new file mode 100644 index 000000000000..d1b5b13629d9 --- /dev/null +++ b/trunk/drivers/staging/iio/addac/adt7316.c @@ -0,0 +1,2402 @@ +/* + * ADT7316 digital temperature sensor driver supporting ADT7316/7/8 ADT7516/7/9 + * + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "adt7316.h" + +/* + * ADT7316 registers definition + */ +#define ADT7316_INT_STAT1 0x0 +#define ADT7316_INT_STAT2 0x1 +#define ADT7316_LSB_IN_TEMP_VDD 0x3 +#define ADT7316_LSB_IN_TEMP_MASK 0x3 +#define ADT7316_LSB_VDD_MASK 0xC +#define ADT7316_LSB_VDD_OFFSET 2 +#define ADT7316_LSB_EX_TEMP_AIN 0x4 +#define ADT7316_LSB_EX_TEMP_MASK 0x3 +#define ADT7516_LSB_AIN_SHIFT 2 +#define ADT7316_AD_MSB_DATA_BASE 0x6 +#define ADT7316_AD_MSB_DATA_REGS 3 +#define ADT7516_AD_MSB_DATA_REGS 6 +#define ADT7316_MSB_VDD 0x6 +#define ADT7316_MSB_IN_TEMP 0x7 +#define ADT7316_MSB_EX_TEMP 0x8 +#define ADT7516_MSB_AIN1 0x8 +#define ADT7516_MSB_AIN2 0x9 +#define ADT7516_MSB_AIN3 0xA +#define ADT7516_MSB_AIN4 0xB +#define ADT7316_DA_DATA_BASE 0x10 +#define ADT7316_DA_MSB_DATA_REGS 4 +#define ADT7316_LSB_DAC_A 0x10 +#define ADT7316_MSB_DAC_A 0x11 +#define ADT7316_LSB_DAC_B 0x12 +#define ADT7316_MSB_DAC_B 0x13 +#define ADT7316_LSB_DAC_C 0x14 +#define ADT7316_MSB_DAC_C 0x15 +#define ADT7316_LSB_DAC_D 0x16 +#define ADT7316_MSB_DAC_D 0x17 +#define ADT7316_CONFIG1 0x18 +#define ADT7316_CONFIG2 0x19 +#define ADT7316_CONFIG3 0x1A +#define ADT7316_LDAC_CONFIG 0x1B +#define ADT7316_DAC_CONFIG 0x1C +#define ADT7316_INT_MASK1 0x1D +#define ADT7316_INT_MASK2 0x1E +#define ADT7316_IN_TEMP_OFFSET 0x1F +#define ADT7316_EX_TEMP_OFFSET 0x20 +#define ADT7316_IN_ANALOG_TEMP_OFFSET 0x21 +#define ADT7316_EX_ANALOG_TEMP_OFFSET 0x22 +#define ADT7316_VDD_HIGH 0x23 +#define ADT7316_VDD_LOW 0x24 +#define ADT7316_IN_TEMP_HIGH 0x25 +#define ADT7316_IN_TEMP_LOW 0x26 +#define ADT7316_EX_TEMP_HIGH 0x27 +#define ADT7316_EX_TEMP_LOW 0x28 +#define ADT7516_AIN2_HIGH 0x2B +#define ADT7516_AIN2_LOW 0x2C +#define ADT7516_AIN3_HIGH 0x2D +#define ADT7516_AIN3_LOW 0x2E +#define ADT7516_AIN4_HIGH 0x2F +#define ADT7516_AIN4_LOW 0x30 +#define ADT7316_DEVICE_ID 0x4D +#define ADT7316_MANUFACTURE_ID 0x4E +#define ADT7316_DEVICE_REV 0x4F +#define ADT7316_SPI_LOCK_STAT 0x7F + +/* + * ADT7316 config1 + */ +#define ADT7316_EN 0x1 +#define ADT7516_SEL_EX_TEMP 0x4 +#define ADT7516_SEL_AIN1_2_EX_TEMP_MASK 0x6 +#define ADT7516_SEL_AIN3 0x8 +#define ADT7316_INT_EN 0x20 +#define ADT7316_INT_POLARITY 0x40 +#define ADT7316_PD 0x80 + +/* + * ADT7316 config2 + */ +#define ADT7316_AD_SINGLE_CH_MASK 0x3 +#define ADT7516_AD_SINGLE_CH_MASK 0x7 +#define ADT7316_AD_SINGLE_CH_VDD 0 +#define ADT7316_AD_SINGLE_CH_IN 1 +#define ADT7316_AD_SINGLE_CH_EX 2 +#define ADT7516_AD_SINGLE_CH_AIN1 2 +#define ADT7516_AD_SINGLE_CH_AIN2 3 +#define ADT7516_AD_SINGLE_CH_AIN3 4 +#define ADT7516_AD_SINGLE_CH_AIN4 5 +#define ADT7316_AD_SINGLE_CH_MODE 0x10 +#define ADT7316_DISABLE_AVERAGING 0x20 +#define ADT7316_EN_SMBUS_TIMEOUT 0x40 +#define ADT7316_RESET 0x80 + +/* + * ADT7316 config3 + */ +#define ADT7316_ADCLK_22_5 0x1 +#define ADT7316_DA_HIGH_RESOLUTION 0x2 +#define ADT7316_DA_EN_VIA_DAC_LDCA 0x4 +#define ADT7516_AIN_IN_VREF 0x10 +#define ADT7316_EN_IN_TEMP_PROP_DACA 0x20 +#define ADT7316_EN_EX_TEMP_PROP_DACB 0x40 + +/* + * ADT7316 DAC config + */ +#define ADT7316_DA_2VREF_CH_MASK 0xF +#define ADT7316_DA_EN_MODE_MASK 0x30 +#define ADT7316_DA_EN_MODE_SINGLE 0x00 +#define ADT7316_DA_EN_MODE_AB_CD 0x10 +#define ADT7316_DA_EN_MODE_ABCD 0x20 +#define ADT7316_DA_EN_MODE_LDAC 0x30 +#define ADT7316_VREF_BYPASS_DAC_AB 0x40 +#define ADT7316_VREF_BYPASS_DAC_CD 0x80 + +/* + * ADT7316 LDAC config + */ +#define ADT7316_LDAC_EN_DA_MASK 0xF +#define ADT7316_DAC_IN_VREF 0x10 +#define ADT7516_DAC_AB_IN_VREF 0x10 +#define ADT7516_DAC_CD_IN_VREF 0x20 +#define ADT7516_DAC_IN_VREF_OFFSET 4 +#define ADT7516_DAC_IN_VREF_MASK 0x30 + +/* + * ADT7316 INT_MASK2 + */ +#define ADT7316_INT_MASK2_VDD 0x10 + +/* + * ADT7316 value masks + */ +#define ADT7316_VALUE_MASK 0xfff +#define ADT7316_T_VALUE_SIGN 0x400 +#define ADT7316_T_VALUE_FLOAT_OFFSET 2 +#define ADT7316_T_VALUE_FLOAT_MASK 0x2 + +/* + * Chip ID + */ +#define ID_ADT7316 0x1 +#define ID_ADT7317 0x2 +#define ID_ADT7318 0x3 +#define ID_ADT7516 0x11 +#define ID_ADT7517 0x12 +#define ID_ADT7519 0x14 + +#define ID_FAMILY_MASK 0xF0 +#define ID_ADT73XX 0x0 +#define ID_ADT75XX 0x10 + +/* + * struct adt7316_chip_info - chip specifc information + */ + +struct adt7316_chip_info { + const char *name; + struct iio_dev *indio_dev; + struct work_struct thresh_work; + s64 last_timestamp; + struct adt7316_bus bus; + u16 ldac_pin; + u16 int_mask; /* 0x2f */ + u8 config1; + u8 config2; + u8 config3; + u8 dac_config; /* DAC config */ + u8 ldac_config; /* LDAC config */ + u8 dac_bits; /* 8, 10, 12 */ + u8 id; /* chip id */ +}; + +/* + * Logic interrupt mask for user application to enable + * interrupts. + */ +#define ADT7316_IN_TEMP_HIGH_INT_MASK 0x1 +#define ADT7316_IN_TEMP_LOW_INT_MASK 0x2 +#define ADT7316_EX_TEMP_HIGH_INT_MASK 0x4 +#define ADT7316_EX_TEMP_LOW_INT_MASK 0x8 +#define ADT7316_EX_TEMP_FAULT_INT_MASK 0x10 +#define ADT7516_AIN1_INT_MASK 0x4 +#define ADT7516_AIN2_INT_MASK 0x20 +#define ADT7516_AIN3_INT_MASK 0x40 +#define ADT7516_AIN4_INT_MASK 0x80 +#define ADT7316_VDD_INT_MASK 0x100 +#define ADT7316_TEMP_INT_MASK 0x1F +#define ADT7516_AIN_INT_MASK 0xE0 +#define ADT7316_TEMP_AIN_INT_MASK \ + (ADT7316_TEMP_INT_MASK | ADT7316_TEMP_INT_MASK) + +/* + * struct adt7316_chip_info - chip specifc information + */ + +struct adt7316_limit_regs { + u16 data_high; + u16 data_low; +}; + +static ssize_t adt7316_show_enabled(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_EN)); +} + +static ssize_t _adt7316_store_enabled(struct adt7316_chip_info *chip, + int enable) +{ + u8 config1; + int ret; + + if (enable) + config1 = chip->config1 | ADT7316_EN; + else + config1 = chip->config1 & ~ADT7316_EN; + + ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG1, config1); + if (ret) + return -EIO; + + chip->config1 = config1; + + return ret; + +} + +static ssize_t adt7316_store_enabled(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + int enable; + + if (!memcmp(buf, "1", 1)) + enable = 1; + else + enable = 0; + + if (_adt7316_store_enabled(chip, enable) < 0) + return -EIO; + else + return len; +} + +static IIO_DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, + adt7316_show_enabled, + adt7316_store_enabled, + 0); + +static ssize_t adt7316_show_select_ex_temp(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX) + return -EPERM; + + return sprintf(buf, "%d\n", !!(chip->config1 & ADT7516_SEL_EX_TEMP)); +} + +static ssize_t adt7316_store_select_ex_temp(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 config1; + int ret; + + if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX) + return -EPERM; + + config1 = chip->config1 & (~ADT7516_SEL_EX_TEMP); + if (!memcmp(buf, "1", 1)) + config1 |= ADT7516_SEL_EX_TEMP; + + ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG1, config1); + if (ret) + return -EIO; + + chip->config1 = config1; + + return len; +} + +static IIO_DEVICE_ATTR(select_ex_temp, S_IRUGO | S_IWUSR, + adt7316_show_select_ex_temp, + adt7316_store_select_ex_temp, + 0); + +static ssize_t adt7316_show_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + if (chip->config2 & ADT7316_AD_SINGLE_CH_MODE) + return sprintf(buf, "single_channel\n"); + else + return sprintf(buf, "round_robin\n"); +} + +static ssize_t adt7316_store_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 config2; + int ret; + + config2 = chip->config2 & (~ADT7316_AD_SINGLE_CH_MODE); + if (!memcmp(buf, "single_channel", 14)) + config2 |= ADT7316_AD_SINGLE_CH_MODE; + + ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG2, config2); + if (ret) + return -EIO; + + chip->config2 = config2; + + return len; +} + +static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, + adt7316_show_mode, + adt7316_store_mode, + 0); + +static ssize_t adt7316_show_all_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "single_channel\nround_robin\n"); +} + +static IIO_DEVICE_ATTR(all_modes, S_IRUGO, adt7316_show_all_modes, NULL, 0); + +static ssize_t adt7316_show_ad_channel(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + if (!(chip->config2 & ADT7316_AD_SINGLE_CH_MODE)) + return -EPERM; + + switch (chip->config2 & ADT7516_AD_SINGLE_CH_MASK) { + case ADT7316_AD_SINGLE_CH_VDD: + return sprintf(buf, "0 - VDD\n"); + case ADT7316_AD_SINGLE_CH_IN: + return sprintf(buf, "1 - Internal Temperature\n"); + case ADT7316_AD_SINGLE_CH_EX: + if (((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) && + (chip->config1 & ADT7516_SEL_AIN1_2_EX_TEMP_MASK) == 0) + return sprintf(buf, "2 - AIN1\n"); + else + return sprintf(buf, "2 - External Temperature\n"); + case ADT7516_AD_SINGLE_CH_AIN2: + if ((chip->config1 & ADT7516_SEL_AIN1_2_EX_TEMP_MASK) == 0) + return sprintf(buf, "3 - AIN2\n"); + else + return sprintf(buf, "N/A\n"); + case ADT7516_AD_SINGLE_CH_AIN3: + if (chip->config1 & ADT7516_SEL_AIN3) + return sprintf(buf, "4 - AIN3\n"); + else + return sprintf(buf, "N/A\n"); + case ADT7516_AD_SINGLE_CH_AIN4: + return sprintf(buf, "5 - AIN4\n"); + default: + return sprintf(buf, "N/A\n"); + }; +} + +static ssize_t adt7316_store_ad_channel(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 config2; + unsigned long data = 0; + int ret; + + if (!(chip->config2 & ADT7316_AD_SINGLE_CH_MODE)) + return -EPERM; + + ret = strict_strtoul(buf, 10, &data); + if (ret) + return -EINVAL; + + if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) { + if (data > 5) + return -EINVAL; + + config2 = chip->config2 & (~ADT7516_AD_SINGLE_CH_MASK); + } else { + if (data > 2) + return -EINVAL; + + config2 = chip->config2 & (~ADT7316_AD_SINGLE_CH_MASK); + } + + + config2 |= data; + + ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG2, config2); + if (ret) + return -EIO; + + chip->config2 = config2; + + return len; +} + +static IIO_DEVICE_ATTR(ad_channel, S_IRUGO | S_IWUSR, + adt7316_show_ad_channel, + adt7316_store_ad_channel, + 0); + +static ssize_t adt7316_show_all_ad_channels(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + if (!(chip->config2 & ADT7316_AD_SINGLE_CH_MODE)) + return -EPERM; + + if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) + return sprintf(buf, "0 - VDD\n1 - Internal Temperature\n" + "2 - External Temperature or AIN2\n" + "3 - AIN2\n4 - AIN3\n5 - AIN4\n"); + else + return sprintf(buf, "0 - VDD\n1 - Internal Temperature\n" + "2 - External Temperature\n"); +} + +static IIO_DEVICE_ATTR(all_ad_channels, S_IRUGO, + adt7316_show_all_ad_channels, NULL, 0); + +static ssize_t adt7316_show_disable_averaging(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", + !!(chip->config2 & ADT7316_DISABLE_AVERAGING)); +} + +static ssize_t adt7316_store_disable_averaging(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 config2; + int ret; + + config2 = chip->config2 & (~ADT7316_DISABLE_AVERAGING); + if (!memcmp(buf, "1", 1)) + config2 |= ADT7316_DISABLE_AVERAGING; + + ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG2, config2); + if (ret) + return -EIO; + + chip->config2 = config2; + + return len; +} + +static IIO_DEVICE_ATTR(disable_averaging, S_IRUGO | S_IWUSR, + adt7316_show_disable_averaging, + adt7316_store_disable_averaging, + 0); + +static ssize_t adt7316_show_enable_smbus_timeout(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", + !!(chip->config2 & ADT7316_EN_SMBUS_TIMEOUT)); +} + +static ssize_t adt7316_store_enable_smbus_timeout(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 config2; + int ret; + + config2 = chip->config2 & (~ADT7316_EN_SMBUS_TIMEOUT); + if (!memcmp(buf, "1", 1)) + config2 |= ADT7316_EN_SMBUS_TIMEOUT; + + ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG2, config2); + if (ret) + return -EIO; + + chip->config2 = config2; + + return len; +} + +static IIO_DEVICE_ATTR(enable_smbus_timeout, S_IRUGO | S_IWUSR, + adt7316_show_enable_smbus_timeout, + adt7316_store_enable_smbus_timeout, + 0); + + +static ssize_t adt7316_store_reset(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 config2; + int ret; + + config2 = chip->config2 | ADT7316_RESET; + + ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG2, config2); + if (ret) + return -EIO; + + return len; +} + +static IIO_DEVICE_ATTR(reset, S_IWUSR, + NULL, + adt7316_store_reset, + 0); + +static ssize_t adt7316_show_powerdown(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_PD)); +} + +static ssize_t adt7316_store_powerdown(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 config1; + int ret; + + config1 = chip->config1 & (~ADT7316_PD); + if (!memcmp(buf, "1", 1)) + config1 |= ADT7316_PD; + + ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG1, config1); + if (ret) + return -EIO; + + chip->config1 = config1; + + return len; +} + +static IIO_DEVICE_ATTR(powerdown, S_IRUGO | S_IWUSR, + adt7316_show_powerdown, + adt7316_store_powerdown, + 0); + +static ssize_t adt7316_show_fast_ad_clock(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", !!(chip->config3 & ADT7316_ADCLK_22_5)); +} + +static ssize_t adt7316_store_fast_ad_clock(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 config3; + int ret; + + config3 = chip->config3 & (~ADT7316_ADCLK_22_5); + if (!memcmp(buf, "1", 1)) + config3 |= ADT7316_ADCLK_22_5; + + ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, config3); + if (ret) + return -EIO; + + chip->config3 = config3; + + return len; +} + +static IIO_DEVICE_ATTR(fast_ad_clock, S_IRUGO | S_IWUSR, + adt7316_show_fast_ad_clock, + adt7316_store_fast_ad_clock, + 0); + +static ssize_t adt7316_show_da_high_resolution(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + if (chip->config3 & ADT7316_DA_HIGH_RESOLUTION) { + if (chip->id == ID_ADT7316 || chip->id == ID_ADT7516) + return sprintf(buf, "1 (12 bits)\n"); + else if (chip->id == ID_ADT7317 || chip->id == ID_ADT7517) + return sprintf(buf, "1 (10 bits)\n"); + } + + return sprintf(buf, "0 (8 bits)\n"); +} + +static ssize_t adt7316_store_da_high_resolution(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 config3; + int ret; + + chip->dac_bits = 8; + + if (!memcmp(buf, "1", 1)) { + config3 = chip->config3 | ADT7316_DA_HIGH_RESOLUTION; + if (chip->id == ID_ADT7316 || chip->id == ID_ADT7516) + chip->dac_bits = 12; + else if (chip->id == ID_ADT7317 || chip->id == ID_ADT7517) + chip->dac_bits = 10; + } else + config3 = chip->config3 & (~ADT7316_DA_HIGH_RESOLUTION); + + ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, config3); + if (ret) + return -EIO; + + chip->config3 = config3; + + return len; +} + +static IIO_DEVICE_ATTR(da_high_resolution, S_IRUGO | S_IWUSR, + adt7316_show_da_high_resolution, + adt7316_store_da_high_resolution, + 0); + +static ssize_t adt7316_show_AIN_internal_Vref(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX) + return -EPERM; + + return sprintf(buf, "%d\n", + !!(chip->config3 & ADT7516_AIN_IN_VREF)); +} + +static ssize_t adt7316_store_AIN_internal_Vref(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 config3; + int ret; + + if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX) + return -EPERM; + + if (memcmp(buf, "1", 1)) + config3 = chip->config3 & (~ADT7516_AIN_IN_VREF); + else + config3 = chip->config3 | ADT7516_AIN_IN_VREF; + + ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, config3); + if (ret) + return -EIO; + + chip->config3 = config3; + + return len; +} + +static IIO_DEVICE_ATTR(AIN_internal_Vref, S_IRUGO | S_IWUSR, + adt7316_show_AIN_internal_Vref, + adt7316_store_AIN_internal_Vref, + 0); + + +static ssize_t adt7316_show_enable_prop_DACA(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", + !!(chip->config3 & ADT7316_EN_IN_TEMP_PROP_DACA)); +} + +static ssize_t adt7316_store_enable_prop_DACA(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 config3; + int ret; + + config3 = chip->config3 & (~ADT7316_EN_IN_TEMP_PROP_DACA); + if (!memcmp(buf, "1", 1)) + config3 |= ADT7316_EN_IN_TEMP_PROP_DACA; + + ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, config3); + if (ret) + return -EIO; + + chip->config3 = config3; + + return len; +} + +static IIO_DEVICE_ATTR(enable_proportion_DACA, S_IRUGO | S_IWUSR, + adt7316_show_enable_prop_DACA, + adt7316_store_enable_prop_DACA, + 0); + +static ssize_t adt7316_show_enable_prop_DACB(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", + !!(chip->config3 & ADT7316_EN_EX_TEMP_PROP_DACB)); +} + +static ssize_t adt7316_store_enable_prop_DACB(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 config3; + int ret; + + config3 = chip->config3 & (~ADT7316_EN_EX_TEMP_PROP_DACB); + if (!memcmp(buf, "1", 1)) + config3 |= ADT7316_EN_EX_TEMP_PROP_DACB; + + ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, config3); + if (ret) + return -EIO; + + chip->config3 = config3; + + return len; +} + +static IIO_DEVICE_ATTR(enable_proportion_DACB, S_IRUGO | S_IWUSR, + adt7316_show_enable_prop_DACB, + adt7316_store_enable_prop_DACB, + 0); + +static ssize_t adt7316_show_DAC_2Vref_ch_mask(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "0x%x\n", + chip->dac_config & ADT7316_DA_2VREF_CH_MASK); +} + +static ssize_t adt7316_store_DAC_2Vref_ch_mask(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 dac_config; + unsigned long data = 0; + int ret; + + ret = strict_strtoul(buf, 16, &data); + if (ret || data > ADT7316_DA_2VREF_CH_MASK) + return -EINVAL; + + dac_config = chip->dac_config & (~ADT7316_DA_2VREF_CH_MASK); + dac_config |= data; + + ret = chip->bus.write(chip->bus.client, ADT7316_DAC_CONFIG, dac_config); + if (ret) + return -EIO; + + chip->dac_config = dac_config; + + return len; +} + +static IIO_DEVICE_ATTR(DAC_2Vref_channels_mask, S_IRUGO | S_IWUSR, + adt7316_show_DAC_2Vref_ch_mask, + adt7316_store_DAC_2Vref_ch_mask, + 0); + +static ssize_t adt7316_show_DAC_update_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA)) + return sprintf(buf, "manual\n"); + else { + switch (chip->dac_config & ADT7316_DA_EN_MODE_MASK) { + case ADT7316_DA_EN_MODE_SINGLE: + return sprintf(buf, "0 - auto at any MSB DAC writing\n"); + case ADT7316_DA_EN_MODE_AB_CD: + return sprintf(buf, "1 - auto at MSB DAC AB and CD writing\n"); + case ADT7316_DA_EN_MODE_ABCD: + return sprintf(buf, "2 - auto at MSB DAC ABCD writing\n"); + default: /* ADT7316_DA_EN_MODE_LDAC */ + return sprintf(buf, "3 - manual\n"); + }; + } +} + +static ssize_t adt7316_store_DAC_update_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 dac_config; + unsigned long data; + int ret; + + if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA)) + return -EPERM; + + ret = strict_strtoul(buf, 10, &data); + if (ret || data > ADT7316_DA_EN_MODE_MASK) + return -EINVAL; + + dac_config = chip->dac_config & (~ADT7316_DA_EN_MODE_MASK); + dac_config |= data; + + ret = chip->bus.write(chip->bus.client, ADT7316_DAC_CONFIG, dac_config); + if (ret) + return -EIO; + + chip->dac_config = dac_config; + + return len; +} + +static IIO_DEVICE_ATTR(DAC_update_mode, S_IRUGO | S_IWUSR, + adt7316_show_DAC_update_mode, + adt7316_store_DAC_update_mode, + 0); + +static ssize_t adt7316_show_all_DAC_update_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA) + return sprintf(buf, "0 - auto at any MSB DAC writing\n" + "1 - auto at MSB DAC AB and CD writing\n" + "2 - auto at MSB DAC ABCD writing\n" + "3 - manual\n"); + else + return sprintf(buf, "manual\n"); +} + +static IIO_DEVICE_ATTR(all_DAC_update_modes, S_IRUGO, + adt7316_show_all_DAC_update_modes, NULL, 0); + + +static ssize_t adt7316_store_update_DAC(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 ldac_config; + unsigned long data; + int ret; + + if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA) { + if ((chip->dac_config & ADT7316_DA_EN_MODE_MASK) != + ADT7316_DA_EN_MODE_LDAC) + return -EPERM; + + ret = strict_strtoul(buf, 16, &data); + if (ret || data > ADT7316_LDAC_EN_DA_MASK) + return -EINVAL; + + ldac_config = chip->ldac_config & (~ADT7316_LDAC_EN_DA_MASK); + ldac_config |= data; + + ret = chip->bus.write(chip->bus.client, ADT7316_LDAC_CONFIG, + ldac_config); + if (ret) + return -EIO; + } else { + gpio_set_value(chip->ldac_pin, 0); + gpio_set_value(chip->ldac_pin, 1); + } + + return len; +} + +static IIO_DEVICE_ATTR(update_DAC, S_IRUGO | S_IWUSR, + NULL, + adt7316_store_update_DAC, + 0); + +static ssize_t adt7316_show_DA_AB_Vref_bypass(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) + return -EPERM; + + return sprintf(buf, "%d\n", + !!(chip->dac_config & ADT7316_VREF_BYPASS_DAC_AB)); +} + +static ssize_t adt7316_store_DA_AB_Vref_bypass(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 dac_config; + int ret; + + if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) + return -EPERM; + + dac_config = chip->dac_config & (~ADT7316_VREF_BYPASS_DAC_AB); + if (!memcmp(buf, "1", 1)) + dac_config |= ADT7316_VREF_BYPASS_DAC_AB; + + ret = chip->bus.write(chip->bus.client, ADT7316_DAC_CONFIG, dac_config); + if (ret) + return -EIO; + + chip->dac_config = dac_config; + + return len; +} + +static IIO_DEVICE_ATTR(DA_AB_Vref_bypass, S_IRUGO | S_IWUSR, + adt7316_show_DA_AB_Vref_bypass, + adt7316_store_DA_AB_Vref_bypass, + 0); + +static ssize_t adt7316_show_DA_CD_Vref_bypass(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) + return -EPERM; + + return sprintf(buf, "%d\n", + !!(chip->dac_config & ADT7316_VREF_BYPASS_DAC_CD)); +} + +static ssize_t adt7316_store_DA_CD_Vref_bypass(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 dac_config; + int ret; + + if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) + return -EPERM; + + dac_config = chip->dac_config & (~ADT7316_VREF_BYPASS_DAC_CD); + if (!memcmp(buf, "1", 1)) + dac_config |= ADT7316_VREF_BYPASS_DAC_CD; + + ret = chip->bus.write(chip->bus.client, ADT7316_DAC_CONFIG, dac_config); + if (ret) + return -EIO; + + chip->dac_config = dac_config; + + return len; +} + +static IIO_DEVICE_ATTR(DA_CD_Vref_bypass, S_IRUGO | S_IWUSR, + adt7316_show_DA_CD_Vref_bypass, + adt7316_store_DA_CD_Vref_bypass, + 0); + +static ssize_t adt7316_show_DAC_internal_Vref(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) + return sprintf(buf, "0x%x\n", + (chip->dac_config & ADT7516_DAC_IN_VREF_MASK) >> + ADT7516_DAC_IN_VREF_OFFSET); + else + return sprintf(buf, "%d\n", + !!(chip->dac_config & ADT7316_DAC_IN_VREF)); +} + +static ssize_t adt7316_store_DAC_internal_Vref(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 ldac_config; + unsigned long data; + int ret; + + if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) { + ret = strict_strtoul(buf, 16, &data); + if (ret || data > 3) + return -EINVAL; + + ldac_config = chip->ldac_config & (~ADT7516_DAC_IN_VREF_MASK); + if (data & 0x1) + ldac_config |= ADT7516_DAC_AB_IN_VREF; + else if (data & 0x2) + ldac_config |= ADT7516_DAC_CD_IN_VREF; + } else { + ret = strict_strtoul(buf, 16, &data); + if (ret) + return -EINVAL; + + ldac_config = chip->ldac_config & (~ADT7316_DAC_IN_VREF); + if (data) + ldac_config = chip->ldac_config | ADT7316_DAC_IN_VREF; + } + + ret = chip->bus.write(chip->bus.client, ADT7316_LDAC_CONFIG, ldac_config); + if (ret) + return -EIO; + + chip->ldac_config = ldac_config; + + return len; +} + +static IIO_DEVICE_ATTR(DAC_internal_Vref, S_IRUGO | S_IWUSR, + adt7316_show_DAC_internal_Vref, + adt7316_store_DAC_internal_Vref, + 0); + +static ssize_t adt7316_show_ad(struct adt7316_chip_info *chip, + int channel, char *buf) +{ + u16 data; + u8 msb, lsb; + char sign = ' '; + int ret; + + if ((chip->config2 & ADT7316_AD_SINGLE_CH_MODE) && + channel != (chip->config2 & ADT7516_AD_SINGLE_CH_MASK)) + return -EPERM; + + switch (channel) { + case ADT7316_AD_SINGLE_CH_IN: + ret = chip->bus.read(chip->bus.client, + ADT7316_LSB_IN_TEMP_VDD, &lsb); + if (ret) + return -EIO; + + ret = chip->bus.read(chip->bus.client, + ADT7316_AD_MSB_DATA_BASE + channel, &msb); + if (ret) + return -EIO; + + data = msb << ADT7316_T_VALUE_FLOAT_OFFSET; + data |= lsb & ADT7316_LSB_IN_TEMP_MASK; + break; + case ADT7316_AD_SINGLE_CH_VDD: + ret = chip->bus.read(chip->bus.client, + ADT7316_LSB_IN_TEMP_VDD, &lsb); + if (ret) + return -EIO; + + ret = chip->bus.read(chip->bus.client, + + ADT7316_AD_MSB_DATA_BASE + channel, &msb); + if (ret) + return -EIO; + + data = msb << ADT7316_T_VALUE_FLOAT_OFFSET; + data |= (lsb & ADT7316_LSB_VDD_MASK) >> ADT7316_LSB_VDD_OFFSET; + return sprintf(buf, "%d\n", data); + default: /* ex_temp and ain */ + ret = chip->bus.read(chip->bus.client, + ADT7316_LSB_EX_TEMP_AIN, &lsb); + if (ret) + return -EIO; + + ret = chip->bus.read(chip->bus.client, + ADT7316_AD_MSB_DATA_BASE + channel, &msb); + if (ret) + return -EIO; + + data = msb << ADT7316_T_VALUE_FLOAT_OFFSET; + data |= lsb & (ADT7316_LSB_EX_TEMP_MASK << + (ADT7516_LSB_AIN_SHIFT * (channel - + (ADT7316_MSB_EX_TEMP - ADT7316_AD_MSB_DATA_BASE)))); + + if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) + return sprintf(buf, "%d\n", data); + else + break; + }; + + if (data & ADT7316_T_VALUE_SIGN) { + /* convert supplement to positive value */ + data = (ADT7316_T_VALUE_SIGN << 1) - data; + sign = '-'; + } + + return sprintf(buf, "%c%d.%.2d\n", sign, + (data >> ADT7316_T_VALUE_FLOAT_OFFSET), + (data & ADT7316_T_VALUE_FLOAT_MASK) * 25); +} + +static ssize_t adt7316_show_VDD(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_VDD, buf); +} +static IIO_DEVICE_ATTR(VDD, S_IRUGO, adt7316_show_VDD, NULL, 0); + +static ssize_t adt7316_show_in_temp(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_IN, buf); +} + +static IIO_DEVICE_ATTR(in_temp, S_IRUGO, adt7316_show_in_temp, NULL, 0); + +static ssize_t adt7316_show_ex_temp_AIN1(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_show_ad(chip, ADT7316_AD_SINGLE_CH_EX, buf); +} + +static IIO_DEVICE_ATTR(ex_temp_AIN1, S_IRUGO, adt7316_show_ex_temp_AIN1, NULL, 0); +static IIO_DEVICE_ATTR(ex_temp, S_IRUGO, adt7316_show_ex_temp_AIN1, NULL, 0); + +static ssize_t adt7316_show_AIN2(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN2, buf); +} +static IIO_DEVICE_ATTR(AIN2, S_IRUGO, adt7316_show_AIN2, NULL, 0); + +static ssize_t adt7316_show_AIN3(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN3, buf); +} +static IIO_DEVICE_ATTR(AIN3, S_IRUGO, adt7316_show_AIN3, NULL, 0); + +static ssize_t adt7316_show_AIN4(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_show_ad(chip, ADT7516_AD_SINGLE_CH_AIN4, buf); +} +static IIO_DEVICE_ATTR(AIN4, S_IRUGO, adt7316_show_AIN4, NULL, 0); + +static ssize_t adt7316_show_temp_offset(struct adt7316_chip_info *chip, + int offset_addr, char *buf) +{ + int data; + u8 val; + int ret; + + ret = chip->bus.read(chip->bus.client, offset_addr, &val); + if (ret) + return -EIO; + + data = (int)val; + if (val & 0x80) + data -= 256; + + return sprintf(buf, "%d\n", data); +} + +static ssize_t adt7316_store_temp_offset(struct adt7316_chip_info *chip, + int offset_addr, const char *buf, size_t len) +{ + long data; + u8 val; + int ret; + + ret = strict_strtol(buf, 10, &data); + if (ret || data > 127 || data < -128) + return -EINVAL; + + if (data < 0) + data += 256; + + val = (u8)data; + + ret = chip->bus.write(chip->bus.client, offset_addr, val); + if (ret) + return -EIO; + + return len; +} + +static ssize_t adt7316_show_in_temp_offset(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_show_temp_offset(chip, ADT7316_IN_TEMP_OFFSET, buf); +} + +static ssize_t adt7316_store_in_temp_offset(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_store_temp_offset(chip, ADT7316_IN_TEMP_OFFSET, buf, len); +} + +static IIO_DEVICE_ATTR(in_temp_offset, S_IRUGO | S_IWUSR, + adt7316_show_in_temp_offset, + adt7316_store_in_temp_offset, 0); + +static ssize_t adt7316_show_ex_temp_offset(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_show_temp_offset(chip, ADT7316_EX_TEMP_OFFSET, buf); +} + +static ssize_t adt7316_store_ex_temp_offset(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_store_temp_offset(chip, ADT7316_EX_TEMP_OFFSET, buf, len); +} + +static IIO_DEVICE_ATTR(ex_temp_offset, S_IRUGO | S_IWUSR, + adt7316_show_ex_temp_offset, + adt7316_store_ex_temp_offset, 0); + +static ssize_t adt7316_show_in_analog_temp_offset(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_show_temp_offset(chip, + ADT7316_IN_ANALOG_TEMP_OFFSET, buf); +} + +static ssize_t adt7316_store_in_analog_temp_offset(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_store_temp_offset(chip, + ADT7316_IN_ANALOG_TEMP_OFFSET, buf, len); +} + +static IIO_DEVICE_ATTR(in_analog_temp_offset, S_IRUGO | S_IWUSR, + adt7316_show_in_analog_temp_offset, + adt7316_store_in_analog_temp_offset, 0); + +static ssize_t adt7316_show_ex_analog_temp_offset(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_show_temp_offset(chip, + ADT7316_EX_ANALOG_TEMP_OFFSET, buf); +} + +static ssize_t adt7316_store_ex_analog_temp_offset(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_store_temp_offset(chip, + ADT7316_EX_ANALOG_TEMP_OFFSET, buf, len); +} + +static IIO_DEVICE_ATTR(ex_analog_temp_offset, S_IRUGO | S_IWUSR, + adt7316_show_ex_analog_temp_offset, + adt7316_store_ex_analog_temp_offset, 0); + +static ssize_t adt7316_show_DAC(struct adt7316_chip_info *chip, + int channel, char *buf) +{ + u16 data; + u8 msb, lsb, offset; + int ret; + + if (channel >= ADT7316_DA_MSB_DATA_REGS || + (channel == 0 && + (chip->config3 & ADT7316_EN_IN_TEMP_PROP_DACA)) || + (channel == 1 && + (chip->config3 & ADT7316_EN_EX_TEMP_PROP_DACB))) + return -EPERM; + + offset = chip->dac_bits - 8; + + if (chip->dac_bits > 8) { + ret = chip->bus.read(chip->bus.client, + ADT7316_DA_DATA_BASE + channel * 2, &lsb); + if (ret) + return -EIO; + } + + ret = chip->bus.read(chip->bus.client, + ADT7316_DA_DATA_BASE + 1 + channel * 2, &msb); + if (ret) + return -EIO; + + data = (msb << offset) + (lsb & ((1 << offset) - 1)); + + return sprintf(buf, "%d\n", data); +} + +static ssize_t adt7316_store_DAC(struct adt7316_chip_info *chip, + int channel, const char *buf, size_t len) +{ + u8 msb, lsb, offset; + unsigned long data; + int ret; + + if (channel >= ADT7316_DA_MSB_DATA_REGS || + (channel == 0 && + (chip->config3 & ADT7316_EN_IN_TEMP_PROP_DACA)) || + (channel == 1 && + (chip->config3 & ADT7316_EN_EX_TEMP_PROP_DACB))) + return -EPERM; + + offset = chip->dac_bits - 8; + + ret = strict_strtoul(buf, 10, &data); + if (ret || data >= (1 << chip->dac_bits)) + return -EINVAL; + + if (chip->dac_bits > 8) { + lsb = data & (1 << offset); + ret = chip->bus.write(chip->bus.client, + ADT7316_DA_DATA_BASE + channel * 2, lsb); + if (ret) + return -EIO; + } + + msb = data >> offset; + ret = chip->bus.write(chip->bus.client, + ADT7316_DA_DATA_BASE + 1 + channel * 2, msb); + if (ret) + return -EIO; + + return len; +} + +static ssize_t adt7316_show_DAC_A(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_show_DAC(chip, 0, buf); +} + +static ssize_t adt7316_store_DAC_A(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_store_DAC(chip, 0, buf, len); +} + +static IIO_DEVICE_ATTR(DAC_A, S_IRUGO | S_IWUSR, adt7316_show_DAC_A, + adt7316_store_DAC_A, 0); + +static ssize_t adt7316_show_DAC_B(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_show_DAC(chip, 1, buf); +} + +static ssize_t adt7316_store_DAC_B(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_store_DAC(chip, 1, buf, len); +} + +static IIO_DEVICE_ATTR(DAC_B, S_IRUGO | S_IWUSR, adt7316_show_DAC_B, + adt7316_store_DAC_B, 0); + +static ssize_t adt7316_show_DAC_C(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_show_DAC(chip, 2, buf); +} + +static ssize_t adt7316_store_DAC_C(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_store_DAC(chip, 2, buf, len); +} + +static IIO_DEVICE_ATTR(DAC_C, S_IRUGO | S_IWUSR, adt7316_show_DAC_C, + adt7316_store_DAC_C, 0); + +static ssize_t adt7316_show_DAC_D(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_show_DAC(chip, 3, buf); +} + +static ssize_t adt7316_store_DAC_D(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return adt7316_store_DAC(chip, 3, buf, len); +} + +static IIO_DEVICE_ATTR(DAC_D, S_IRUGO | S_IWUSR, adt7316_show_DAC_D, + adt7316_store_DAC_D, 0); + +static ssize_t adt7316_show_device_id(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 id; + int ret; + + ret = chip->bus.read(chip->bus.client, ADT7316_DEVICE_ID, &id); + if (ret) + return -EIO; + + return sprintf(buf, "%d\n", id); +} + +static IIO_DEVICE_ATTR(device_id, S_IRUGO, adt7316_show_device_id, NULL, 0); + +static ssize_t adt7316_show_manufactorer_id(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 id; + int ret; + + ret = chip->bus.read(chip->bus.client, ADT7316_MANUFACTURE_ID, &id); + if (ret) + return -EIO; + + return sprintf(buf, "%d\n", id); +} + +static IIO_DEVICE_ATTR(manufactorer_id, S_IRUGO, + adt7316_show_manufactorer_id, NULL, 0); + +static ssize_t adt7316_show_device_rev(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 rev; + int ret; + + ret = chip->bus.read(chip->bus.client, ADT7316_DEVICE_REV, &rev); + if (ret) + return -EIO; + + return sprintf(buf, "%d\n", rev); +} + +static IIO_DEVICE_ATTR(device_rev, S_IRUGO, adt7316_show_device_rev, NULL, 0); + +static ssize_t adt7316_show_bus_type(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 stat; + int ret; + + ret = chip->bus.read(chip->bus.client, ADT7316_SPI_LOCK_STAT, &stat); + if (ret) + return -EIO; + + if (stat) + return sprintf(buf, "spi\n"); + else + return sprintf(buf, "i2c\n"); +} + +static IIO_DEVICE_ATTR(bus_type, S_IRUGO, adt7316_show_bus_type, NULL, 0); + +static ssize_t adt7316_show_name(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%s\n", chip->name); +} + +static IIO_DEVICE_ATTR(name, S_IRUGO, adt7316_show_name, NULL, 0); + +static struct attribute *adt7316_attributes[] = { + &iio_dev_attr_all_modes.dev_attr.attr, + &iio_dev_attr_mode.dev_attr.attr, + &iio_dev_attr_reset.dev_attr.attr, + &iio_dev_attr_enabled.dev_attr.attr, + &iio_dev_attr_ad_channel.dev_attr.attr, + &iio_dev_attr_all_ad_channels.dev_attr.attr, + &iio_dev_attr_disable_averaging.dev_attr.attr, + &iio_dev_attr_enable_smbus_timeout.dev_attr.attr, + &iio_dev_attr_powerdown.dev_attr.attr, + &iio_dev_attr_fast_ad_clock.dev_attr.attr, + &iio_dev_attr_da_high_resolution.dev_attr.attr, + &iio_dev_attr_enable_proportion_DACA.dev_attr.attr, + &iio_dev_attr_enable_proportion_DACB.dev_attr.attr, + &iio_dev_attr_DAC_2Vref_channels_mask.dev_attr.attr, + &iio_dev_attr_DAC_update_mode.dev_attr.attr, + &iio_dev_attr_all_DAC_update_modes.dev_attr.attr, + &iio_dev_attr_update_DAC.dev_attr.attr, + &iio_dev_attr_DA_AB_Vref_bypass.dev_attr.attr, + &iio_dev_attr_DA_CD_Vref_bypass.dev_attr.attr, + &iio_dev_attr_DAC_internal_Vref.dev_attr.attr, + &iio_dev_attr_VDD.dev_attr.attr, + &iio_dev_attr_in_temp.dev_attr.attr, + &iio_dev_attr_ex_temp.dev_attr.attr, + &iio_dev_attr_in_temp_offset.dev_attr.attr, + &iio_dev_attr_ex_temp_offset.dev_attr.attr, + &iio_dev_attr_in_analog_temp_offset.dev_attr.attr, + &iio_dev_attr_ex_analog_temp_offset.dev_attr.attr, + &iio_dev_attr_DAC_A.dev_attr.attr, + &iio_dev_attr_DAC_B.dev_attr.attr, + &iio_dev_attr_DAC_C.dev_attr.attr, + &iio_dev_attr_DAC_D.dev_attr.attr, + &iio_dev_attr_device_id.dev_attr.attr, + &iio_dev_attr_manufactorer_id.dev_attr.attr, + &iio_dev_attr_device_rev.dev_attr.attr, + &iio_dev_attr_bus_type.dev_attr.attr, + &iio_dev_attr_name.dev_attr.attr, + NULL, +}; + +static const struct attribute_group adt7316_attribute_group = { + .attrs = adt7316_attributes, +}; + +static struct attribute *adt7516_attributes[] = { + &iio_dev_attr_all_modes.dev_attr.attr, + &iio_dev_attr_mode.dev_attr.attr, + &iio_dev_attr_select_ex_temp.dev_attr.attr, + &iio_dev_attr_reset.dev_attr.attr, + &iio_dev_attr_enabled.dev_attr.attr, + &iio_dev_attr_ad_channel.dev_attr.attr, + &iio_dev_attr_all_ad_channels.dev_attr.attr, + &iio_dev_attr_disable_averaging.dev_attr.attr, + &iio_dev_attr_enable_smbus_timeout.dev_attr.attr, + &iio_dev_attr_powerdown.dev_attr.attr, + &iio_dev_attr_fast_ad_clock.dev_attr.attr, + &iio_dev_attr_AIN_internal_Vref.dev_attr.attr, + &iio_dev_attr_da_high_resolution.dev_attr.attr, + &iio_dev_attr_enable_proportion_DACA.dev_attr.attr, + &iio_dev_attr_enable_proportion_DACB.dev_attr.attr, + &iio_dev_attr_DAC_2Vref_channels_mask.dev_attr.attr, + &iio_dev_attr_DAC_update_mode.dev_attr.attr, + &iio_dev_attr_all_DAC_update_modes.dev_attr.attr, + &iio_dev_attr_update_DAC.dev_attr.attr, + &iio_dev_attr_DA_AB_Vref_bypass.dev_attr.attr, + &iio_dev_attr_DA_CD_Vref_bypass.dev_attr.attr, + &iio_dev_attr_DAC_internal_Vref.dev_attr.attr, + &iio_dev_attr_VDD.dev_attr.attr, + &iio_dev_attr_in_temp.dev_attr.attr, + &iio_dev_attr_ex_temp_AIN1.dev_attr.attr, + &iio_dev_attr_AIN2.dev_attr.attr, + &iio_dev_attr_AIN3.dev_attr.attr, + &iio_dev_attr_AIN4.dev_attr.attr, + &iio_dev_attr_in_temp_offset.dev_attr.attr, + &iio_dev_attr_ex_temp_offset.dev_attr.attr, + &iio_dev_attr_in_analog_temp_offset.dev_attr.attr, + &iio_dev_attr_ex_analog_temp_offset.dev_attr.attr, + &iio_dev_attr_DAC_A.dev_attr.attr, + &iio_dev_attr_DAC_B.dev_attr.attr, + &iio_dev_attr_DAC_C.dev_attr.attr, + &iio_dev_attr_DAC_D.dev_attr.attr, + &iio_dev_attr_device_id.dev_attr.attr, + &iio_dev_attr_manufactorer_id.dev_attr.attr, + &iio_dev_attr_device_rev.dev_attr.attr, + &iio_dev_attr_bus_type.dev_attr.attr, + &iio_dev_attr_name.dev_attr.attr, + NULL, +}; + +static const struct attribute_group adt7516_attribute_group = { + .attrs = adt7516_attributes, +}; + + +/* + * temperature bound events + */ + +#define IIO_EVENT_CODE_ADT7316_IN_TEMP_HIGH IIO_BUFFER_EVENT_CODE(0) +#define IIO_EVENT_CODE_ADT7316_IN_TEMP_LOW IIO_BUFFER_EVENT_CODE(1) +#define IIO_EVENT_CODE_ADT7316_EX_TEMP_HIGH IIO_BUFFER_EVENT_CODE(2) +#define IIO_EVENT_CODE_ADT7316_EX_TEMP_LOW IIO_BUFFER_EVENT_CODE(3) +#define IIO_EVENT_CODE_ADT7316_EX_TEMP_FAULT IIO_BUFFER_EVENT_CODE(4) +#define IIO_EVENT_CODE_ADT7516_AIN1 IIO_BUFFER_EVENT_CODE(5) +#define IIO_EVENT_CODE_ADT7516_AIN2 IIO_BUFFER_EVENT_CODE(6) +#define IIO_EVENT_CODE_ADT7516_AIN3 IIO_BUFFER_EVENT_CODE(7) +#define IIO_EVENT_CODE_ADT7516_AIN4 IIO_BUFFER_EVENT_CODE(8) +#define IIO_EVENT_CODE_ADT7316_VDD IIO_BUFFER_EVENT_CODE(9) + +static void adt7316_interrupt_bh(struct work_struct *work_s) +{ + struct adt7316_chip_info *chip = + container_of(work_s, struct adt7316_chip_info, thresh_work); + u8 stat1, stat2; + int i, ret, count; + + ret = chip->bus.read(chip->bus.client, ADT7316_INT_STAT1, &stat1); + if (!ret) { + if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) + count = 8; + else + count = 5; + + for (i = 0; i < count; i++) { + if (stat1 & (1 << i)) + iio_push_event(chip->indio_dev, 0, + IIO_EVENT_CODE_ADT7316_IN_TEMP_HIGH + i, + chip->last_timestamp); + } + } + + ret = chip->bus.read(chip->bus.client, ADT7316_INT_STAT2, &stat2); + if (!ret) { + if (stat2 & ADT7316_INT_MASK2_VDD) + iio_push_event(chip->indio_dev, 0, + IIO_EVENT_CODE_ADT7316_VDD, + chip->last_timestamp); + } + + enable_irq(chip->bus.irq); +} + +static int adt7316_interrupt(struct iio_dev *dev_info, + int index, + s64 timestamp, + int no_test) +{ + struct adt7316_chip_info *chip = dev_info->dev_data; + + chip->last_timestamp = timestamp; + schedule_work(&chip->thresh_work); + + return 0; +} + +IIO_EVENT_SH(adt7316, &adt7316_interrupt); + +/* + * Show mask of enabled interrupts in Hex. + */ +static ssize_t adt7316_show_int_mask(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "0x%x\n", chip->int_mask); +} + +/* + * Set 1 to the mask in Hex to enabled interrupts. + */ +static ssize_t adt7316_set_int_mask(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + unsigned long data; + int ret; + u8 mask; + + ret = strict_strtoul(buf, 16, &data); + if (ret || data >= ADT7316_VDD_INT_MASK + 1) + return -EINVAL; + + if (data & ADT7316_VDD_INT_MASK) + mask = 0; /* enable vdd int */ + else + mask = ADT7316_INT_MASK2_VDD; /* disable vdd int */ + + ret = chip->bus.write(chip->bus.client, ADT7316_INT_MASK2, mask); + if (!ret) { + chip->int_mask &= ~ADT7316_VDD_INT_MASK; + chip->int_mask |= data & ADT7316_VDD_INT_MASK; + } + + if (data & ADT7316_TEMP_AIN_INT_MASK) { + if ((chip->id & ID_FAMILY_MASK) == ID_ADT73XX) + /* mask in reg is opposite, set 1 to disable */ + mask = (~data) & ADT7316_TEMP_INT_MASK; + else + /* mask in reg is opposite, set 1 to disable */ + mask = (~data) & ADT7316_TEMP_AIN_INT_MASK; + } + ret = chip->bus.write(chip->bus.client, ADT7316_INT_MASK1, mask); + + chip->int_mask = mask; + + return len; +} +static inline ssize_t adt7316_show_ad_bound(struct device *dev, + struct device_attribute *attr, + u8 bound_reg, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 val; + int data; + int ret; + + if ((chip->id & ID_FAMILY_MASK) == ID_ADT73XX && + bound_reg > ADT7316_EX_TEMP_LOW) + return -EPERM; + + ret = chip->bus.read(chip->bus.client, bound_reg, &val); + if (ret) + return -EIO; + + data = (int)val; + + if (!((chip->id & ID_FAMILY_MASK) == ID_ADT75XX && + (chip->config1 & ADT7516_SEL_AIN1_2_EX_TEMP_MASK) == 0)) { + if (data & 0x80) + data -= 256; + } + + return sprintf(buf, "%d\n", data); +} + +static inline ssize_t adt7316_set_ad_bound(struct device *dev, + struct device_attribute *attr, + u8 bound_reg, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + long data; + u8 val; + int ret; + + if ((chip->id & ID_FAMILY_MASK) == ID_ADT73XX && + bound_reg > ADT7316_EX_TEMP_LOW) + return -EPERM; + + ret = strict_strtol(buf, 10, &data); + if (ret) + return -EINVAL; + + if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX && + (chip->config1 & ADT7516_SEL_AIN1_2_EX_TEMP_MASK) == 0) { + if (data > 255 || data < 0) + return -EINVAL; + } else { + if (data > 127 || data < -128) + return -EINVAL; + + if (data < 0) + data += 256; + } + + val = (u8)data; + + ret = chip->bus.write(chip->bus.client, bound_reg, val); + if (ret) + return -EIO; + + return len; +} + +static ssize_t adt7316_show_in_temp_high(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return adt7316_show_ad_bound(dev, attr, + ADT7316_IN_TEMP_HIGH, buf); +} + +static inline ssize_t adt7316_set_in_temp_high(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return adt7316_set_ad_bound(dev, attr, + ADT7316_IN_TEMP_HIGH, buf, len); +} + +static ssize_t adt7316_show_in_temp_low(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return adt7316_show_ad_bound(dev, attr, + ADT7316_IN_TEMP_LOW, buf); +} + +static inline ssize_t adt7316_set_in_temp_low(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return adt7316_set_ad_bound(dev, attr, + ADT7316_IN_TEMP_LOW, buf, len); +} + +static ssize_t adt7316_show_ex_temp_ain1_high(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return adt7316_show_ad_bound(dev, attr, + ADT7316_EX_TEMP_HIGH, buf); +} + +static inline ssize_t adt7316_set_ex_temp_ain1_high(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return adt7316_set_ad_bound(dev, attr, + ADT7316_EX_TEMP_HIGH, buf, len); +} + +static ssize_t adt7316_show_ex_temp_ain1_low(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return adt7316_show_ad_bound(dev, attr, + ADT7316_EX_TEMP_LOW, buf); +} + +static inline ssize_t adt7316_set_ex_temp_ain1_low(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return adt7316_set_ad_bound(dev, attr, + ADT7316_EX_TEMP_LOW, buf, len); +} + +static ssize_t adt7316_show_ain2_high(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return adt7316_show_ad_bound(dev, attr, + ADT7516_AIN2_HIGH, buf); +} + +static inline ssize_t adt7316_set_ain2_high(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return adt7316_set_ad_bound(dev, attr, + ADT7516_AIN2_HIGH, buf, len); +} + +static ssize_t adt7316_show_ain2_low(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return adt7316_show_ad_bound(dev, attr, + ADT7516_AIN2_LOW, buf); +} + +static inline ssize_t adt7316_set_ain2_low(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return adt7316_set_ad_bound(dev, attr, + ADT7516_AIN2_LOW, buf, len); +} + +static ssize_t adt7316_show_ain3_high(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return adt7316_show_ad_bound(dev, attr, + ADT7516_AIN3_HIGH, buf); +} + +static inline ssize_t adt7316_set_ain3_high(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return adt7316_set_ad_bound(dev, attr, + ADT7516_AIN3_HIGH, buf, len); +} + +static ssize_t adt7316_show_ain3_low(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return adt7316_show_ad_bound(dev, attr, + ADT7516_AIN3_LOW, buf); +} + +static inline ssize_t adt7316_set_ain3_low(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return adt7316_set_ad_bound(dev, attr, + ADT7516_AIN3_LOW, buf, len); +} + +static ssize_t adt7316_show_ain4_high(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return adt7316_show_ad_bound(dev, attr, + ADT7516_AIN4_HIGH, buf); +} + +static inline ssize_t adt7316_set_ain4_high(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return adt7316_set_ad_bound(dev, attr, + ADT7516_AIN4_HIGH, buf, len); +} + +static ssize_t adt7316_show_ain4_low(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return adt7316_show_ad_bound(dev, attr, + ADT7516_AIN4_LOW, buf); +} + +static inline ssize_t adt7316_set_ain4_low(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + return adt7316_set_ad_bound(dev, attr, + ADT7516_AIN4_LOW, buf, len); +} + +static ssize_t adt7316_show_int_enabled(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_INT_EN)); +} + +static ssize_t adt7316_set_int_enabled(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + u8 config1; + int ret; + + config1 = chip->config1 & (~ADT7316_INT_EN); + if (!memcmp(buf, "1", 1)) + config1 |= ADT7316_INT_EN; + + ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG1, config1); + if (ret) + return -EIO; + + chip->config1 = config1; + + return len; +} + + +IIO_EVENT_ATTR_SH(int_mask, iio_event_adt7316, + adt7316_show_int_mask, adt7316_set_int_mask, 0); +IIO_EVENT_ATTR_SH(in_temp_high, iio_event_adt7316, + adt7316_show_in_temp_high, adt7316_set_in_temp_high, 0); +IIO_EVENT_ATTR_SH(in_temp_low, iio_event_adt7316, + adt7316_show_in_temp_low, adt7316_set_in_temp_low, 0); +IIO_EVENT_ATTR_SH(ex_temp_high, iio_event_adt7316, + adt7316_show_ex_temp_ain1_high, + adt7316_set_ex_temp_ain1_high, 0); +IIO_EVENT_ATTR_SH(ex_temp_low, iio_event_adt7316, + adt7316_show_ex_temp_ain1_low, + adt7316_set_ex_temp_ain1_low, 0); +IIO_EVENT_ATTR_SH(ex_temp_ain1_high, iio_event_adt7316, + adt7316_show_ex_temp_ain1_high, + adt7316_set_ex_temp_ain1_high, 0); +IIO_EVENT_ATTR_SH(ex_temp_ain1_low, iio_event_adt7316, + adt7316_show_ex_temp_ain1_low, + adt7316_set_ex_temp_ain1_low, 0); +IIO_EVENT_ATTR_SH(ain2_high, iio_event_adt7316, + adt7316_show_ain2_high, adt7316_set_ain2_high, 0); +IIO_EVENT_ATTR_SH(ain2_low, iio_event_adt7316, + adt7316_show_ain2_low, adt7316_set_ain2_low, 0); +IIO_EVENT_ATTR_SH(ain3_high, iio_event_adt7316, + adt7316_show_ain3_high, adt7316_set_ain3_high, 0); +IIO_EVENT_ATTR_SH(ain3_low, iio_event_adt7316, + adt7316_show_ain3_low, adt7316_set_ain3_low, 0); +IIO_EVENT_ATTR_SH(ain4_high, iio_event_adt7316, + adt7316_show_ain4_high, adt7316_set_ain4_high, 0); +IIO_EVENT_ATTR_SH(ain4_low, iio_event_adt7316, + adt7316_show_ain4_low, adt7316_set_ain4_low, 0); +IIO_EVENT_ATTR_SH(int_enabled, iio_event_adt7316, + adt7316_show_int_enabled, adt7316_set_int_enabled, 0); + +static struct attribute *adt7316_event_attributes[] = { + &iio_event_attr_int_mask.dev_attr.attr, + &iio_event_attr_in_temp_high.dev_attr.attr, + &iio_event_attr_in_temp_low.dev_attr.attr, + &iio_event_attr_ex_temp_high.dev_attr.attr, + &iio_event_attr_ex_temp_low.dev_attr.attr, + &iio_event_attr_int_enabled.dev_attr.attr, + NULL, +}; + +static struct attribute_group adt7316_event_attribute_group = { + .attrs = adt7316_event_attributes, +}; + +static struct attribute *adt7516_event_attributes[] = { + &iio_event_attr_int_mask.dev_attr.attr, + &iio_event_attr_in_temp_high.dev_attr.attr, + &iio_event_attr_in_temp_low.dev_attr.attr, + &iio_event_attr_ex_temp_ain1_high.dev_attr.attr, + &iio_event_attr_ex_temp_ain1_low.dev_attr.attr, + &iio_event_attr_ain2_high.dev_attr.attr, + &iio_event_attr_ain2_low.dev_attr.attr, + &iio_event_attr_ain3_high.dev_attr.attr, + &iio_event_attr_ain3_low.dev_attr.attr, + &iio_event_attr_ain4_high.dev_attr.attr, + &iio_event_attr_ain4_low.dev_attr.attr, + &iio_event_attr_int_enabled.dev_attr.attr, + NULL, +}; + +static struct attribute_group adt7516_event_attribute_group = { + .attrs = adt7516_event_attributes, +}; + +#ifdef CONFIG_PM +int adt7316_disable(struct device *dev) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return _adt7316_store_enabled(chip, 0); +} +EXPORT_SYMBOL(adt7316_disable); + +int adt7316_enable(struct device *dev) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + + return _adt7316_store_enabled(chip, 1); +} +EXPORT_SYMBOL(adt7316_enable); +#endif + +/* + * device probe and remove + */ +int __devinit adt7316_probe(struct device *dev, struct adt7316_bus *bus, + const char *name) +{ + struct adt7316_chip_info *chip; + unsigned short *adt7316_platform_data = dev->platform_data; + int ret = 0; + + chip = kzalloc(sizeof(struct adt7316_chip_info), GFP_KERNEL); + + if (chip == NULL) + return -ENOMEM; + + /* this is only used for device removal purposes */ + dev_set_drvdata(dev, chip); + + chip->bus = *bus; + chip->name = name; + + if (name[4] == '3') + chip->id = ID_ADT7316 + (name[6] - '6'); + else if (name[4] == '5') + chip->id = ID_ADT7516 + (name[6] - '6'); + else + return -ENODEV; + + chip->ldac_pin = adt7316_platform_data[1]; + if (chip->ldac_pin) { + chip->config3 |= ADT7316_DA_EN_VIA_DAC_LDCA; + if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) + chip->config1 |= ADT7516_SEL_AIN3; + } + chip->int_mask = ADT7316_TEMP_INT_MASK | ADT7316_VDD_INT_MASK; + if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) + chip->int_mask |= ADT7516_AIN_INT_MASK; + + chip->indio_dev = iio_allocate_device(); + if (chip->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_chip; + } + + chip->indio_dev->dev.parent = dev; + if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) { + chip->indio_dev->attrs = &adt7516_attribute_group; + chip->indio_dev->event_attrs = &adt7516_event_attribute_group; + } else { + chip->indio_dev->attrs = &adt7316_attribute_group; + chip->indio_dev->event_attrs = &adt7316_event_attribute_group; + } + chip->indio_dev->dev_data = (void *)chip; + chip->indio_dev->driver_module = THIS_MODULE; + chip->indio_dev->num_interrupt_lines = 1; + chip->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(chip->indio_dev); + if (ret) + goto error_free_dev; + + if (chip->bus.irq > 0) { + if (adt7316_platform_data[0]) + chip->bus.irq_flags = adt7316_platform_data[0]; + + ret = iio_register_interrupt_line(chip->bus.irq, + chip->indio_dev, + 0, + chip->bus.irq_flags, + chip->name); + if (ret) + goto error_unreg_dev; + + /* + * The event handler list element refer to iio_event_adt7316. + * All event attributes bind to the same event handler. + * So, only register event handler once. + */ + iio_add_event_to_list(&iio_event_adt7316, + &chip->indio_dev->interrupts[0]->ev_list); + + INIT_WORK(&chip->thresh_work, adt7316_interrupt_bh); + + if (chip->bus.irq_flags & IRQF_TRIGGER_HIGH) + chip->config1 |= ADT7316_INT_POLARITY; + } + + ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG1, chip->config1); + if (ret) { + ret = -EIO; + goto error_unreg_irq; + } + + ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, chip->config3); + if (ret) { + ret = -EIO; + goto error_unreg_irq; + } + + dev_info(dev, "%s temperature sensor, ADC and DAC registered.\n", + chip->name); + + return 0; + +error_unreg_irq: + iio_unregister_interrupt_line(chip->indio_dev, 0); +error_unreg_dev: + iio_device_unregister(chip->indio_dev); +error_free_dev: + iio_free_device(chip->indio_dev); +error_free_chip: + kfree(chip); + + return ret; +} +EXPORT_SYMBOL(adt7316_probe); + +int __devexit adt7316_remove(struct device *dev) +{ + + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adt7316_chip_info *chip = dev_info->dev_data; + struct iio_dev *indio_dev = chip->indio_dev; + + dev_set_drvdata(dev, NULL); + if (chip->bus.irq) + iio_unregister_interrupt_line(indio_dev, 0); + iio_device_unregister(indio_dev); + iio_free_device(chip->indio_dev); + kfree(chip); + + return 0; +} +EXPORT_SYMBOL(adt7316_remove); + +MODULE_AUTHOR("Sonic Zhang "); +MODULE_DESCRIPTION("Analog Devices ADT7316/7/8 and ADT7516/7/9 digital" + " temperature sensor, ADC and DAC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/addac/adt7316.h b/trunk/drivers/staging/iio/addac/adt7316.h new file mode 100644 index 000000000000..d34bd679bb4e --- /dev/null +++ b/trunk/drivers/staging/iio/addac/adt7316.h @@ -0,0 +1,33 @@ +/* + * ADT7316 digital temperature sensor driver supporting ADT7316/7/8 ADT7516/7/9 + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef _ADT7316_H_ +#define _ADT7316_H_ + +#include + +#define ADT7316_REG_MAX_ADDR 0x3F + +struct adt7316_bus { + void *client; + int irq; + int irq_flags; + int (*read) (void *client, u8 reg, u8 *data); + int (*write) (void *client, u8 reg, u8 val); + int (*multi_read) (void *client, u8 first_reg, u8 count, u8 *data); + int (*multi_write) (void *client, u8 first_reg, u8 count, u8 *data); +}; + +#ifdef CONFIG_PM +int adt7316_disable(struct device *dev); +int adt7316_enable(struct device *dev); +#endif +int adt7316_probe(struct device *dev, struct adt7316_bus *bus, const char *name); +int adt7316_remove(struct device *dev); + +#endif diff --git a/trunk/drivers/staging/iio/dac/Kconfig b/trunk/drivers/staging/iio/dac/Kconfig new file mode 100644 index 000000000000..583df785fd25 --- /dev/null +++ b/trunk/drivers/staging/iio/dac/Kconfig @@ -0,0 +1,11 @@ +# +# DAC drivers +# +comment "Digital to analog convertors" + +config AD5624R_SPI + tristate "Analog Devices AD5624/44/64R DAC spi driver" + depends on SPI + help + Say yes here to build support for Analog Devices AD5624R, AD5644R and + AD5664R convertors (DAC). This driver uses the common SPI interface. diff --git a/trunk/drivers/staging/iio/dac/Makefile b/trunk/drivers/staging/iio/dac/Makefile new file mode 100644 index 000000000000..7ddf05d5f1b4 --- /dev/null +++ b/trunk/drivers/staging/iio/dac/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for industrial I/O DAC drivers +# + +obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o diff --git a/trunk/drivers/staging/iio/dac/ad5624r.h b/trunk/drivers/staging/iio/dac/ad5624r.h new file mode 100644 index 000000000000..ce518be652b7 --- /dev/null +++ b/trunk/drivers/staging/iio/dac/ad5624r.h @@ -0,0 +1,21 @@ +#ifndef SPI_AD5624R_H_ +#define SPI_AD5624R_H_ + +#define AD5624R_DAC_CHANNELS 4 + +#define AD5624R_ADDR_DAC0 0x0 +#define AD5624R_ADDR_DAC1 0x1 +#define AD5624R_ADDR_DAC2 0x2 +#define AD5624R_ADDR_DAC3 0x3 +#define AD5624R_ADDR_ALL_DAC 0x7 + +#define AD5624R_CMD_WRITE_INPUT_N 0x0 +#define AD5624R_CMD_UPDATE_DAC_N 0x1 +#define AD5624R_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2 +#define AD5624R_CMD_WRITE_INPUT_N_UPDATE_N 0x3 +#define AD5624R_CMD_POWERDOWN_DAC 0x4 +#define AD5624R_CMD_RESET 0x5 +#define AD5624R_CMD_LDAC_SETUP 0x6 +#define AD5624R_CMD_INTERNAL_REFER_SETUP 0x7 + +#endif diff --git a/trunk/drivers/staging/iio/dac/ad5624r_spi.c b/trunk/drivers/staging/iio/dac/ad5624r_spi.c new file mode 100644 index 000000000000..705ff505bf25 --- /dev/null +++ b/trunk/drivers/staging/iio/dac/ad5624r_spi.c @@ -0,0 +1,313 @@ +/* + * AD5624R, AD5644R, AD5664R Digital to analog convertors spi driver + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "dac.h" +#include "ad5624r.h" + +/** + * struct ad5624r_state - device related storage + * @indio_dev: associated industrial IO device + * @us: spi device + **/ +struct ad5624r_state { + struct iio_dev *indio_dev; + struct spi_device *us; + int data_len; + int ldac_mode; + int dac_power_mode[AD5624R_DAC_CHANNELS]; + int internal_ref; +}; + +static int ad5624r_spi_write(struct spi_device *spi, u8 cmd, u8 addr, u16 val, u8 len) +{ + struct spi_transfer t; + struct spi_message m; + u32 data; + u8 msg[3]; + + /* + * The input shift register is 24 bits wide. The first two bits are don't care bits. + * The next three are the command bits, C2 to C0, followed by the 3-bit DAC address, + * A2 to A0, and then the 16-, 14-, 12-bit data-word. The data-word comprises the 16-, + * 14-, 12-bit input code followed by 0, 2, or 4 don't care bits, for the AD5664R, + * AD5644R, and AD5624R, respectively. + */ + data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << (16 - len)); + msg[0] = data >> 16; + msg[1] = data >> 8; + msg[2] = data; + + spi_message_init(&m); + memset(&t, 0, (sizeof t)); + t.tx_buf = &msg[0]; + t.len = 3; + + spi_message_add_tail(&t, &m); + spi_sync(spi, &m); + + return len; +} + +static ssize_t ad5624r_write_dac(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + long readin; + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad5624r_state *st = indio_dev->dev_data; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = strict_strtol(buf, 10, &readin); + if (ret) + return ret; + + ad5624r_spi_write(st->us, AD5624R_CMD_WRITE_INPUT_N_UPDATE_N, + this_attr->address, readin, st->data_len); + return ret ? ret : len; +} + +static ssize_t ad5624r_read_ldac_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad5624r_state *st = indio_dev->dev_data; + + return sprintf(buf, "%x\n", st->ldac_mode); +} + +static ssize_t ad5624r_write_ldac_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + long readin; + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad5624r_state *st = indio_dev->dev_data; + + ret = strict_strtol(buf, 16, &readin); + if (ret) + return ret; + + ad5624r_spi_write(st->us, AD5624R_CMD_LDAC_SETUP, 0, readin & 0xF, 16); + st->ldac_mode = readin & 0xF; + + return ret ? ret : len; +} + +static ssize_t ad5624r_read_dac_power_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad5624r_state *st = indio_dev->dev_data; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + return sprintf(buf, "%d\n", st->dac_power_mode[this_attr->address]); +} + +static ssize_t ad5624r_write_dac_power_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + long readin; + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad5624r_state *st = indio_dev->dev_data; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = strict_strtol(buf, 10, &readin); + if (ret) + return ret; + + ad5624r_spi_write(st->us, AD5624R_CMD_POWERDOWN_DAC, 0, + ((readin & 0x3) << 4) | (1 << this_attr->address), 16); + + st->dac_power_mode[this_attr->address] = readin & 0x3; + + return ret ? ret : len; +} + +static ssize_t ad5624r_read_internal_ref_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad5624r_state *st = indio_dev->dev_data; + + return sprintf(buf, "%d\n", st->internal_ref); +} + +static ssize_t ad5624r_write_internal_ref_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + long readin; + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad5624r_state *st = indio_dev->dev_data; + + ret = strict_strtol(buf, 10, &readin); + if (ret) + return ret; + + ad5624r_spi_write(st->us, AD5624R_CMD_INTERNAL_REFER_SETUP, 0, !!readin, 16); + + st->internal_ref = !!readin; + + return ret ? ret : len; +} + +static IIO_DEV_ATTR_DAC(0, ad5624r_write_dac, AD5624R_ADDR_DAC0); +static IIO_DEV_ATTR_DAC(1, ad5624r_write_dac, AD5624R_ADDR_DAC1); +static IIO_DEV_ATTR_DAC(2, ad5624r_write_dac, AD5624R_ADDR_DAC2); +static IIO_DEV_ATTR_DAC(3, ad5624r_write_dac, AD5624R_ADDR_DAC3); + +static IIO_DEVICE_ATTR(ldac_mode, S_IRUGO | S_IWUSR, ad5624r_read_ldac_mode, + ad5624r_write_ldac_mode, 0); +static IIO_DEVICE_ATTR(internal_ref, S_IRUGO | S_IWUSR, ad5624r_read_internal_ref_mode, + ad5624r_write_internal_ref_mode, 0); + +#define IIO_DEV_ATTR_DAC_POWER_MODE(_num, _show, _store, _addr) \ + IIO_DEVICE_ATTR(dac_power_mode_##_num, S_IRUGO | S_IWUSR, _show, _store, _addr) + +static IIO_DEV_ATTR_DAC_POWER_MODE(0, ad5624r_read_dac_power_mode, ad5624r_write_dac_power_mode, 0); +static IIO_DEV_ATTR_DAC_POWER_MODE(1, ad5624r_read_dac_power_mode, ad5624r_write_dac_power_mode, 1); +static IIO_DEV_ATTR_DAC_POWER_MODE(2, ad5624r_read_dac_power_mode, ad5624r_write_dac_power_mode, 2); +static IIO_DEV_ATTR_DAC_POWER_MODE(3, ad5624r_read_dac_power_mode, ad5624r_write_dac_power_mode, 3); + +static struct attribute *ad5624r_attributes[] = { + &iio_dev_attr_dac_0.dev_attr.attr, + &iio_dev_attr_dac_1.dev_attr.attr, + &iio_dev_attr_dac_2.dev_attr.attr, + &iio_dev_attr_dac_3.dev_attr.attr, + &iio_dev_attr_dac_power_mode_0.dev_attr.attr, + &iio_dev_attr_dac_power_mode_1.dev_attr.attr, + &iio_dev_attr_dac_power_mode_2.dev_attr.attr, + &iio_dev_attr_dac_power_mode_3.dev_attr.attr, + &iio_dev_attr_ldac_mode.dev_attr.attr, + &iio_dev_attr_internal_ref.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad5624r_attribute_group = { + .attrs = ad5624r_attributes, +}; + +static int __devinit ad5624r_probe(struct spi_device *spi) +{ + + struct ad5624r_state *st; + int ret = 0; + char *chip_name = spi->dev.platform_data; + + if (!chip_name) + return -ENODEV; + + st = kzalloc(sizeof(*st), GFP_KERNEL); + if (st == NULL) { + ret = -ENOMEM; + goto error_ret; + } + spi_set_drvdata(spi, st); + + if (strcmp(chip_name, "ad5624r") == 0) + st->data_len = 12; + else if (strcmp(chip_name, "ad5644r") == 0) + st->data_len = 14; + else if (strcmp(chip_name, "ad5664r") == 0) + st->data_len = 16; + else { + dev_err(&spi->dev, "not supported chip type\n"); + ret = -EINVAL; + goto error_ret; + } + + st->us = spi; + st->indio_dev = iio_allocate_device(); + if (st->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->indio_dev->dev.parent = &spi->dev; + st->indio_dev->num_interrupt_lines = 0; + st->indio_dev->event_attrs = NULL; + + st->indio_dev->attrs = &ad5624r_attribute_group; + st->indio_dev->dev_data = (void *)(st); + st->indio_dev->driver_module = THIS_MODULE; + st->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(st->indio_dev); + if (ret) + goto error_free_dev; + + spi->mode = SPI_MODE_0; + spi_setup(spi); + + return 0; + +error_free_dev: + iio_free_device(st->indio_dev); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +static int __devexit ad5624r_remove(struct spi_device *spi) +{ + struct ad5624r_state *st = spi_get_drvdata(spi); + + iio_device_unregister(st->indio_dev); + kfree(st); + + return 0; +} + +static struct spi_driver ad5624r_driver = { + .driver = { + .name = "ad5624r", + .owner = THIS_MODULE, + }, + .probe = ad5624r_probe, + .remove = __devexit_p(ad5624r_remove), +}; + +static __init int ad5624r_spi_init(void) +{ + return spi_register_driver(&ad5624r_driver); +} +module_init(ad5624r_spi_init); + +static __exit void ad5624r_spi_exit(void) +{ + spi_unregister_driver(&ad5624r_driver); +} +module_exit(ad5624r_spi_exit); + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices AD5624/44/64R DAC spi driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/dac/dac.h b/trunk/drivers/staging/iio/dac/dac.h new file mode 100644 index 000000000000..55005eec1214 --- /dev/null +++ b/trunk/drivers/staging/iio/dac/dac.h @@ -0,0 +1,6 @@ +/* + * dac.h - sysfs attributes associated with DACs + */ + +#define IIO_DEV_ATTR_DAC(_num, _store, _addr) \ + IIO_DEVICE_ATTR(dac_##_num, S_IWUSR, NULL, _store, _addr) diff --git a/trunk/drivers/staging/iio/dds/Kconfig b/trunk/drivers/staging/iio/dds/Kconfig new file mode 100644 index 000000000000..d045ed69ad38 --- /dev/null +++ b/trunk/drivers/staging/iio/dds/Kconfig @@ -0,0 +1,46 @@ +# +# Direct Digital Synthesis drivers +# +comment "Direct Digital Synthesis" + +config AD5930 + tristate "Analog Devices ad5930/5932 driver" + depends on SPI + help + Say yes here to build support for Analog Devices DDS chip + ad5930/ad5932, provides direct access via sysfs. + +config AD9832 + tristate "Analog Devices ad9832/3/4/5 driver" + depends on SPI + help + Say yes here to build support for Analog Devices DDS chip + ad9832/3/4/5, provides direct access via sysfs. + +config AD9850 + tristate "Analog Devices ad9850/1 driver" + depends on SPI + help + Say yes here to build support for Analog Devices DDS chip + ad9850/1, provides direct access via sysfs. + +config AD9852 + tristate "Analog Devices ad9852/4 driver" + depends on SPI + help + Say yes here to build support for Analog Devices DDS chip + ad9852/4, provides direct access via sysfs. + +config AD9910 + tristate "Analog Devices ad9910 driver" + depends on SPI + help + Say yes here to build support for Analog Devices DDS chip + ad9910, provides direct access via sysfs. + +config AD9951 + tristate "Analog Devices ad9951 driver" + depends on SPI + help + Say yes here to build support for Analog Devices DDS chip + ad9951, provides direct access via sysfs. diff --git a/trunk/drivers/staging/iio/dds/Makefile b/trunk/drivers/staging/iio/dds/Makefile new file mode 100644 index 000000000000..6f274acb0fcf --- /dev/null +++ b/trunk/drivers/staging/iio/dds/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for Direct Digital Synthesis drivers +# + +obj-$(CONFIG_AD5930) += ad5930.o +obj-$(CONFIG_AD9832) += ad9832.o +obj-$(CONFIG_AD9850) += ad9850.o +obj-$(CONFIG_AD9852) += ad9852.o +obj-$(CONFIG_AD9910) += ad9910.o +obj-$(CONFIG_AD9951) += ad9951.o diff --git a/trunk/drivers/staging/iio/dds/ad5930.c b/trunk/drivers/staging/iio/dds/ad5930.c new file mode 100644 index 000000000000..f80039c5d539 --- /dev/null +++ b/trunk/drivers/staging/iio/dds/ad5930.c @@ -0,0 +1,170 @@ +/* + * Driver for ADI Direct Digital Synthesis ad5930 + * + * Copyright (c) 2010-2010 Analog Devices Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +#define DRV_NAME "ad5930" + +#define value_mask (u16)0xf000 +#define addr_shift 12 + +/* Register format: 4 bits addr + 12 bits value */ +struct ad5903_config { + u16 control; + u16 incnum; + u16 frqdelt[2]; + u16 incitvl; + u16 buritvl; + u16 strtfrq[2]; +}; + +struct ad5930_state { + struct mutex lock; + struct iio_dev *idev; + struct spi_device *sdev; +}; + +static ssize_t ad5930_set_parameter(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct spi_message msg; + struct spi_transfer xfer; + int ret; + struct ad5903_config *config = (struct ad5903_config *)buf; + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad5930_state *st = idev->dev_data; + + config->control = (config->control & ~value_mask); + config->incnum = (config->control & ~value_mask) | (1 << addr_shift); + config->frqdelt[0] = (config->control & ~value_mask) | (2 << addr_shift); + config->frqdelt[1] = (config->control & ~value_mask) | 3 << addr_shift; + config->incitvl = (config->control & ~value_mask) | 4 << addr_shift; + config->buritvl = (config->control & ~value_mask) | 8 << addr_shift; + config->strtfrq[0] = (config->control & ~value_mask) | 0xc << addr_shift; + config->strtfrq[1] = (config->control & ~value_mask) | 0xd << addr_shift; + + xfer.len = len; + xfer.tx_buf = config; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; +error_ret: + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad5930_set_parameter, 0); + +static struct attribute *ad5930_attributes[] = { + &iio_dev_attr_dds.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad5930_attribute_group = { + .name = DRV_NAME, + .attrs = ad5930_attributes, +}; + +static int __devinit ad5930_probe(struct spi_device *spi) +{ + struct ad5930_state *st; + int ret = 0; + + st = kzalloc(sizeof(*st), GFP_KERNEL); + if (st == NULL) { + ret = -ENOMEM; + goto error_ret; + } + spi_set_drvdata(spi, st); + + mutex_init(&st->lock); + st->sdev = spi; + + st->idev = iio_allocate_device(); + if (st->idev == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->idev->dev.parent = &spi->dev; + st->idev->num_interrupt_lines = 0; + st->idev->event_attrs = NULL; + + st->idev->attrs = &ad5930_attribute_group; + st->idev->dev_data = (void *)(st); + st->idev->driver_module = THIS_MODULE; + st->idev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(st->idev); + if (ret) + goto error_free_dev; + spi->max_speed_hz = 2000000; + spi->mode = SPI_MODE_3; + spi->bits_per_word = 16; + spi_setup(spi); + + return 0; + +error_free_dev: + iio_free_device(st->idev); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +static int __devexit ad5930_remove(struct spi_device *spi) +{ + struct ad5930_state *st = spi_get_drvdata(spi); + + iio_device_unregister(st->idev); + kfree(st); + + return 0; +} + +static struct spi_driver ad5930_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = ad5930_probe, + .remove = __devexit_p(ad5930_remove), +}; + +static __init int ad5930_spi_init(void) +{ + return spi_register_driver(&ad5930_driver); +} +module_init(ad5930_spi_init); + +static __exit void ad5930_spi_exit(void) +{ + spi_unregister_driver(&ad5930_driver); +} +module_exit(ad5930_spi_exit); + +MODULE_AUTHOR("Cliff Cai"); +MODULE_DESCRIPTION("Analog Devices ad5930 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/dds/ad9832.c b/trunk/drivers/staging/iio/dds/ad9832.c new file mode 100644 index 000000000000..a4bb0482ed5b --- /dev/null +++ b/trunk/drivers/staging/iio/dds/ad9832.c @@ -0,0 +1,266 @@ +/* + * Driver for ADI Direct Digital Synthesis ad9832 + * + * Copyright (c) 2010 Analog Devices Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +#define DRV_NAME "ad9832" + +#define value_mask (u16)0xf000 +#define cmd_shift 12 +#define add_shift 8 +#define AD9832_SYNC (1 << 13) +#define AD9832_SELSRC (1 << 12) +#define AD9832_SLEEP (1 << 13) +#define AD9832_RESET (1 << 12) +#define AD9832_CLR (1 << 11) + +#define ADD_FREQ0LL 0x0 +#define ADD_FREQ0HL 0x1 +#define ADD_FREQ0LM 0x2 +#define ADD_FREQ0HM 0x3 +#define ADD_FREQ1LL 0x4 +#define ADD_FREQ1HL 0x5 +#define ADD_FREQ1LM 0x6 +#define ADD_FREQ1HM 0x7 +#define ADD_PHASE0L 0x8 +#define ADD_PHASE0H 0x9 +#define ADD_PHASE1L 0xa +#define ADD_PHASE1H 0xb +#define ADD_PHASE2L 0xc +#define ADD_PHASE2H 0xd +#define ADD_PHASE3L 0xe +#define ADD_PHASE3H 0xf + +#define CMD_PHA8BITSW 0x1 +#define CMD_PHA16BITSW 0x0 +#define CMD_FRE8BITSW 0x3 +#define CMD_FRE16BITSW 0x2 +#define CMD_SELBITSCTL 0x6 + +struct ad9832_setting { + u16 freq0[4]; + u16 freq1[4]; + u16 phase0[2]; + u16 phase1[2]; + u16 phase2[2]; + u16 phase3[2]; +}; + +struct ad9832_state { + struct mutex lock; + struct iio_dev *idev; + struct spi_device *sdev; +}; + +static ssize_t ad9832_set_parameter(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct spi_message msg; + struct spi_transfer xfer; + int ret; + struct ad9832_setting config; + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad9832_state *st = idev->dev_data; + + config.freq0[0] = (CMD_FRE8BITSW << add_shift | ADD_FREQ0LL << add_shift | buf[0]); + config.freq0[1] = (CMD_FRE16BITSW << add_shift | ADD_FREQ0HL << add_shift | buf[1]); + config.freq0[2] = (CMD_FRE8BITSW << add_shift | ADD_FREQ0LM << add_shift | buf[2]); + config.freq0[3] = (CMD_FRE16BITSW << add_shift | ADD_FREQ0HM << add_shift | buf[3]); + config.freq1[0] = (CMD_FRE8BITSW << add_shift | ADD_FREQ1LL << add_shift | buf[4]); + config.freq1[1] = (CMD_FRE16BITSW << add_shift | ADD_FREQ1HL << add_shift | buf[5]); + config.freq1[2] = (CMD_FRE8BITSW << add_shift | ADD_FREQ1LM << add_shift | buf[6]); + config.freq1[3] = (CMD_FRE16BITSW << add_shift | ADD_FREQ1HM << add_shift | buf[7]); + + config.phase0[0] = (CMD_PHA8BITSW << add_shift | ADD_PHASE0L << add_shift | buf[9]); + config.phase0[1] = (CMD_PHA16BITSW << add_shift | ADD_PHASE0H << add_shift | buf[10]); + config.phase1[0] = (CMD_PHA8BITSW << add_shift | ADD_PHASE1L << add_shift | buf[11]); + config.phase1[1] = (CMD_PHA16BITSW << add_shift | ADD_PHASE1H << add_shift | buf[12]); + config.phase2[0] = (CMD_PHA8BITSW << add_shift | ADD_PHASE2L << add_shift | buf[13]); + config.phase2[1] = (CMD_PHA16BITSW << add_shift | ADD_PHASE2H << add_shift | buf[14]); + config.phase3[0] = (CMD_PHA8BITSW << add_shift | ADD_PHASE3L << add_shift | buf[15]); + config.phase3[1] = (CMD_PHA16BITSW << add_shift | ADD_PHASE3H << add_shift | buf[16]); + + xfer.len = 2 * len; + xfer.tx_buf = &config; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; +error_ret: + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9832_set_parameter, 0); + +static struct attribute *ad9832_attributes[] = { + &iio_dev_attr_dds.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad9832_attribute_group = { + .name = DRV_NAME, + .attrs = ad9832_attributes, +}; + +static void ad9832_init(struct ad9832_state *st) +{ + struct spi_message msg; + struct spi_transfer xfer; + int ret; + u16 config = 0; + + config = 0x3 << 14 | AD9832_SLEEP | AD9832_RESET | AD9832_CLR; + + mutex_lock(&st->lock); + + xfer.len = 2; + xfer.tx_buf = &config; + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + config = 0x2 << 14 | AD9832_SYNC | AD9832_SELSRC; + xfer.len = 2; + xfer.tx_buf = &config; + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + config = CMD_SELBITSCTL << cmd_shift; + xfer.len = 2; + xfer.tx_buf = &config; + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + config = 0x3 << 14; + + mutex_lock(&st->lock); + + xfer.len = 2; + xfer.tx_buf = &config; + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; +error_ret: + mutex_unlock(&st->lock); + + + +} + +static int __devinit ad9832_probe(struct spi_device *spi) +{ + struct ad9832_state *st; + int ret = 0; + + st = kzalloc(sizeof(*st), GFP_KERNEL); + if (st == NULL) { + ret = -ENOMEM; + goto error_ret; + } + spi_set_drvdata(spi, st); + + mutex_init(&st->lock); + st->sdev = spi; + + st->idev = iio_allocate_device(); + if (st->idev == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->idev->dev.parent = &spi->dev; + st->idev->num_interrupt_lines = 0; + st->idev->event_attrs = NULL; + + st->idev->attrs = &ad9832_attribute_group; + st->idev->dev_data = (void *)(st); + st->idev->driver_module = THIS_MODULE; + st->idev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(st->idev); + if (ret) + goto error_free_dev; + spi->max_speed_hz = 2000000; + spi->mode = SPI_MODE_3; + spi->bits_per_word = 16; + spi_setup(spi); + ad9832_init(st); + return 0; + +error_free_dev: + iio_free_device(st->idev); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +static int __devexit ad9832_remove(struct spi_device *spi) +{ + struct ad9832_state *st = spi_get_drvdata(spi); + + iio_device_unregister(st->idev); + kfree(st); + + return 0; +} + +static struct spi_driver ad9832_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = ad9832_probe, + .remove = __devexit_p(ad9832_remove), +}; + +static __init int ad9832_spi_init(void) +{ + return spi_register_driver(&ad9832_driver); +} +module_init(ad9832_spi_init); + +static __exit void ad9832_spi_exit(void) +{ + spi_unregister_driver(&ad9832_driver); +} +module_exit(ad9832_spi_exit); + +MODULE_AUTHOR("Cliff Cai"); +MODULE_DESCRIPTION("Analog Devices ad9832 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/dds/ad9850.c b/trunk/drivers/staging/iio/dds/ad9850.c new file mode 100644 index 000000000000..b259bfeaf5aa --- /dev/null +++ b/trunk/drivers/staging/iio/dds/ad9850.c @@ -0,0 +1,156 @@ +/* + * Driver for ADI Direct Digital Synthesis ad9850 + * + * Copyright (c) 2010-2010 Analog Devices Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +#define DRV_NAME "ad9850" + +#define value_mask (u16)0xf000 +#define addr_shift 12 + +/* Register format: 4 bits addr + 12 bits value */ +struct ad9850_config { + u8 control[5]; +}; + +struct ad9850_state { + struct mutex lock; + struct iio_dev *idev; + struct spi_device *sdev; +}; + +static ssize_t ad9850_set_parameter(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct spi_message msg; + struct spi_transfer xfer; + int ret; + struct ad9850_config *config = (struct ad9850_config *)buf; + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad9850_state *st = idev->dev_data; + + xfer.len = len; + xfer.tx_buf = config; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; +error_ret: + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9850_set_parameter, 0); + +static struct attribute *ad9850_attributes[] = { + &iio_dev_attr_dds.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad9850_attribute_group = { + .name = DRV_NAME, + .attrs = ad9850_attributes, +}; + +static int __devinit ad9850_probe(struct spi_device *spi) +{ + struct ad9850_state *st; + int ret = 0; + + st = kzalloc(sizeof(*st), GFP_KERNEL); + if (st == NULL) { + ret = -ENOMEM; + goto error_ret; + } + spi_set_drvdata(spi, st); + + mutex_init(&st->lock); + st->sdev = spi; + + st->idev = iio_allocate_device(); + if (st->idev == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->idev->dev.parent = &spi->dev; + st->idev->num_interrupt_lines = 0; + st->idev->event_attrs = NULL; + + st->idev->attrs = &ad9850_attribute_group; + st->idev->dev_data = (void *)(st); + st->idev->driver_module = THIS_MODULE; + st->idev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(st->idev); + if (ret) + goto error_free_dev; + spi->max_speed_hz = 2000000; + spi->mode = SPI_MODE_3; + spi->bits_per_word = 16; + spi_setup(spi); + + return 0; + +error_free_dev: + iio_free_device(st->idev); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +static int __devexit ad9850_remove(struct spi_device *spi) +{ + struct ad9850_state *st = spi_get_drvdata(spi); + + iio_device_unregister(st->idev); + kfree(st); + + return 0; +} + +static struct spi_driver ad9850_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = ad9850_probe, + .remove = __devexit_p(ad9850_remove), +}; + +static __init int ad9850_spi_init(void) +{ + return spi_register_driver(&ad9850_driver); +} +module_init(ad9850_spi_init); + +static __exit void ad9850_spi_exit(void) +{ + spi_unregister_driver(&ad9850_driver); +} +module_exit(ad9850_spi_exit); + +MODULE_AUTHOR("Cliff Cai"); +MODULE_DESCRIPTION("Analog Devices ad9850 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/dds/ad9852.c b/trunk/drivers/staging/iio/dds/ad9852.c new file mode 100644 index 000000000000..0a41d25583af --- /dev/null +++ b/trunk/drivers/staging/iio/dds/ad9852.c @@ -0,0 +1,314 @@ +/* + * Driver for ADI Direct Digital Synthesis ad9852 + * + * Copyright (c) 2010 Analog Devices Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +#define DRV_NAME "ad9852" + +#define addr_phaad1 0x0 +#define addr_phaad2 0x1 +#define addr_fretu1 0x2 +#define addr_fretu2 0x3 +#define addr_delfre 0x4 +#define addr_updclk 0x5 +#define addr_ramclk 0x6 +#define addr_contrl 0x7 +#define addr_optskm 0x8 +#define addr_optskr 0xa +#define addr_dacctl 0xb + +#define COMPPD (1 << 4) +#define REFMULT2 (1 << 2) +#define BYPPLL (1 << 5) +#define PLLRANG (1 << 6) +#define IEUPCLK (1) +#define OSKEN (1 << 5) + +#define read_bit (1 << 7) + +/* Register format: 1 byte addr + value */ +struct ad9852_config { + u8 phajst0[3]; + u8 phajst1[3]; + u8 fretun1[6]; + u8 fretun2[6]; + u8 dltafre[6]; + u8 updtclk[5]; + u8 ramprat[4]; + u8 control[5]; + u8 outpskm[3]; + u8 outpskr[2]; + u8 daccntl[3]; +}; + +struct ad9852_state { + struct mutex lock; + struct iio_dev *idev; + struct spi_device *sdev; +}; + +static ssize_t ad9852_set_parameter(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct spi_message msg; + struct spi_transfer xfer; + int ret; + struct ad9852_config *config = (struct ad9852_config *)buf; + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad9852_state *st = idev->dev_data; + + xfer.len = 3; + xfer.tx_buf = &config->phajst0[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 3; + xfer.tx_buf = &config->phajst1[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 6; + xfer.tx_buf = &config->fretun1[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 6; + xfer.tx_buf = &config->fretun2[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 6; + xfer.tx_buf = &config->dltafre[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 5; + xfer.tx_buf = &config->updtclk[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 4; + xfer.tx_buf = &config->ramprat[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 5; + xfer.tx_buf = &config->control[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 3; + xfer.tx_buf = &config->outpskm[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 2; + xfer.tx_buf = &config->outpskr[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + xfer.len = 3; + xfer.tx_buf = &config->daccntl[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; +error_ret: + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9852_set_parameter, 0); + +static void ad9852_init(struct ad9852_state *st) +{ + struct spi_message msg; + struct spi_transfer xfer; + int ret; + u8 config[5]; + + config[0] = addr_contrl; + config[1] = COMPPD; + config[2] = REFMULT2 | BYPPLL | PLLRANG; + config[3] = IEUPCLK; + config[4] = OSKEN; + + mutex_lock(&st->lock); + + xfer.len = 5; + xfer.tx_buf = &config; + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + +error_ret: + mutex_unlock(&st->lock); + + + +} + +static struct attribute *ad9852_attributes[] = { + &iio_dev_attr_dds.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad9852_attribute_group = { + .name = DRV_NAME, + .attrs = ad9852_attributes, +}; + +static int __devinit ad9852_probe(struct spi_device *spi) +{ + struct ad9852_state *st; + int ret = 0; + + st = kzalloc(sizeof(*st), GFP_KERNEL); + if (st == NULL) { + ret = -ENOMEM; + goto error_ret; + } + spi_set_drvdata(spi, st); + + mutex_init(&st->lock); + st->sdev = spi; + + st->idev = iio_allocate_device(); + if (st->idev == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->idev->dev.parent = &spi->dev; + st->idev->num_interrupt_lines = 0; + st->idev->event_attrs = NULL; + + st->idev->attrs = &ad9852_attribute_group; + st->idev->dev_data = (void *)(st); + st->idev->driver_module = THIS_MODULE; + st->idev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(st->idev); + if (ret) + goto error_free_dev; + spi->max_speed_hz = 2000000; + spi->mode = SPI_MODE_3; + spi->bits_per_word = 8; + spi_setup(spi); + ad9852_init(st); + return 0; + +error_free_dev: + iio_free_device(st->idev); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +static int __devexit ad9852_remove(struct spi_device *spi) +{ + struct ad9852_state *st = spi_get_drvdata(spi); + + iio_device_unregister(st->idev); + kfree(st); + + return 0; +} + +static struct spi_driver ad9852_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = ad9852_probe, + .remove = __devexit_p(ad9852_remove), +}; + +static __init int ad9852_spi_init(void) +{ + return spi_register_driver(&ad9852_driver); +} +module_init(ad9852_spi_init); + +static __exit void ad9852_spi_exit(void) +{ + spi_unregister_driver(&ad9852_driver); +} +module_exit(ad9852_spi_exit); + +MODULE_AUTHOR("Cliff Cai"); +MODULE_DESCRIPTION("Analog Devices ad9852 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/dds/ad9910.c b/trunk/drivers/staging/iio/dds/ad9910.c new file mode 100644 index 000000000000..c59b40794768 --- /dev/null +++ b/trunk/drivers/staging/iio/dds/ad9910.c @@ -0,0 +1,454 @@ +/* + * Driver for ADI Direct Digital Synthesis ad9910 + * + * Copyright (c) 2010 Analog Devices Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +#define DRV_NAME "ad9910" + +#define CFR1 0x0 +#define CFR2 0x1 +#define CFR3 0x2 + +#define AUXDAC 0x3 +#define IOUPD 0x4 +#define FTW 0x7 +#define POW 0x8 +#define ASF 0x9 +#define MULTC 0x0A +#define DIG_RAMPL 0x0B +#define DIG_RAMPS 0x0C +#define DIG_RAMPR 0x0D +#define SIN_TONEP0 0x0E +#define SIN_TONEP1 0x0F +#define SIN_TONEP2 0x10 +#define SIN_TONEP3 0x11 +#define SIN_TONEP4 0x12 +#define SIN_TONEP5 0x13 +#define SIN_TONEP6 0x14 +#define SIN_TONEP7 0x15 + +#define RAM_ENABLE (1 << 7) + +#define MANUAL_OSK (1 << 7) +#define INVSIC (1 << 6) +#define DDS_SINEOP (1) + +#define AUTO_OSK (1) +#define OSKEN (1 << 1) +#define LOAD_ARR (1 << 2) +#define CLR_PHA (1 << 3) +#define CLR_DIG (1 << 4) +#define ACLR_PHA (1 << 5) +#define ACLR_DIG (1 << 6) +#define LOAD_LRR (1 << 7) + +#define LSB_FST (1) +#define SDIO_IPT (1 << 1) +#define EXT_PWD (1 << 3) +#define ADAC_PWD (1 << 4) +#define REFCLK_PWD (1 << 5) +#define DAC_PWD (1 << 6) +#define DIG_PWD (1 << 7) + +#define ENA_AMP (1) +#define READ_FTW (1) +#define DIGR_LOW (1 << 1) +#define DIGR_HIGH (1 << 2) +#define DIGR_ENA (1 << 3) +#define SYNCCLK_ENA (1 << 6) +#define ITER_IOUPD (1 << 7) + +#define TX_ENA (1 << 1) +#define PDCLK_INV (1 << 2) +#define PDCLK_ENB (1 << 3) + +#define PARA_ENA (1 << 4) +#define SYNC_DIS (1 << 5) +#define DATA_ASS (1 << 6) +#define MATCH_ENA (1 << 7) + +#define PLL_ENA (1) +#define PFD_RST (1 << 2) +#define REFCLK_RST (1 << 6) +#define REFCLK_BYP (1 << 7) + +/* Register format: 1 byte addr + value */ +struct ad9910_config { + u8 auxdac[5]; + u8 ioupd[5]; + u8 ftw[5]; + u8 pow[3]; + u8 asf[5]; + u8 multc[5]; + u8 dig_rampl[9]; + u8 dig_ramps[9]; + u8 dig_rampr[5]; + u8 sin_tonep0[9]; + u8 sin_tonep1[9]; + u8 sin_tonep2[9]; + u8 sin_tonep3[9]; + u8 sin_tonep4[9]; + u8 sin_tonep5[9]; + u8 sin_tonep6[9]; + u8 sin_tonep7[9]; +}; + +struct ad9910_state { + struct mutex lock; + struct iio_dev *idev; + struct spi_device *sdev; +}; + +static ssize_t ad9910_set_parameter(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct spi_message msg; + struct spi_transfer xfer; + int ret; + struct ad9910_config *config = (struct ad9910_config *)buf; + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad9910_state *st = idev->dev_data; + + xfer.len = 5; + xfer.tx_buf = &config->auxdac[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 5; + xfer.tx_buf = &config->ioupd[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 5; + xfer.tx_buf = &config->ftw[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 3; + xfer.tx_buf = &config->pow[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 5; + xfer.tx_buf = &config->asf[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 5; + xfer.tx_buf = &config->multc[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 9; + xfer.tx_buf = &config->dig_rampl[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 9; + xfer.tx_buf = &config->dig_ramps[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 5; + xfer.tx_buf = &config->dig_rampr[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 9; + xfer.tx_buf = &config->sin_tonep0[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + xfer.len = 9; + xfer.tx_buf = &config->sin_tonep1[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + xfer.len = 9; + xfer.tx_buf = &config->sin_tonep2[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + xfer.len = 9; + xfer.tx_buf = &config->sin_tonep3[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + xfer.len = 9; + xfer.tx_buf = &config->sin_tonep4[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + xfer.len = 9; + xfer.tx_buf = &config->sin_tonep5[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + xfer.len = 9; + xfer.tx_buf = &config->sin_tonep6[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + xfer.len = 9; + xfer.tx_buf = &config->sin_tonep7[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; +error_ret: + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9910_set_parameter, 0); + +static void ad9910_init(struct ad9910_state *st) +{ + struct spi_message msg; + struct spi_transfer xfer; + int ret; + u8 cfr[5]; + + cfr[0] = CFR1; + cfr[1] = 0; + cfr[2] = MANUAL_OSK | INVSIC | DDS_SINEOP; + cfr[3] = AUTO_OSK | OSKEN | ACLR_PHA | ACLR_DIG | LOAD_LRR; + cfr[4] = 0; + + mutex_lock(&st->lock); + + xfer.len = 5; + xfer.tx_buf = 𝔠 + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + cfr[0] = CFR2; + cfr[1] = ENA_AMP; + cfr[2] = READ_FTW | DIGR_ENA | ITER_IOUPD; + cfr[3] = TX_ENA | PDCLK_INV | PDCLK_ENB; + cfr[4] = PARA_ENA; + + mutex_lock(&st->lock); + + xfer.len = 5; + xfer.tx_buf = 𝔠 + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + cfr[0] = CFR3; + cfr[1] = PLL_ENA; + cfr[2] = 0; + cfr[3] = REFCLK_RST | REFCLK_BYP; + cfr[4] = 0; + + mutex_lock(&st->lock); + + xfer.len = 5; + xfer.tx_buf = 𝔠 + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + +error_ret: + mutex_unlock(&st->lock); + + + +} + +static struct attribute *ad9910_attributes[] = { + &iio_dev_attr_dds.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad9910_attribute_group = { + .name = DRV_NAME, + .attrs = ad9910_attributes, +}; + +static int __devinit ad9910_probe(struct spi_device *spi) +{ + struct ad9910_state *st; + int ret = 0; + + st = kzalloc(sizeof(*st), GFP_KERNEL); + if (st == NULL) { + ret = -ENOMEM; + goto error_ret; + } + spi_set_drvdata(spi, st); + + mutex_init(&st->lock); + st->sdev = spi; + + st->idev = iio_allocate_device(); + if (st->idev == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->idev->dev.parent = &spi->dev; + st->idev->num_interrupt_lines = 0; + st->idev->event_attrs = NULL; + + st->idev->attrs = &ad9910_attribute_group; + st->idev->dev_data = (void *)(st); + st->idev->driver_module = THIS_MODULE; + st->idev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(st->idev); + if (ret) + goto error_free_dev; + spi->max_speed_hz = 2000000; + spi->mode = SPI_MODE_3; + spi->bits_per_word = 8; + spi_setup(spi); + ad9910_init(st); + return 0; + +error_free_dev: + iio_free_device(st->idev); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +static int __devexit ad9910_remove(struct spi_device *spi) +{ + struct ad9910_state *st = spi_get_drvdata(spi); + + iio_device_unregister(st->idev); + kfree(st); + + return 0; +} + +static struct spi_driver ad9910_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = ad9910_probe, + .remove = __devexit_p(ad9910_remove), +}; + +static __init int ad9910_spi_init(void) +{ + return spi_register_driver(&ad9910_driver); +} +module_init(ad9910_spi_init); + +static __exit void ad9910_spi_exit(void) +{ + spi_unregister_driver(&ad9910_driver); +} +module_exit(ad9910_spi_exit); + +MODULE_AUTHOR("Cliff Cai"); +MODULE_DESCRIPTION("Analog Devices ad9910 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/dds/ad9951.c b/trunk/drivers/staging/iio/dds/ad9951.c new file mode 100644 index 000000000000..bc3befff167a --- /dev/null +++ b/trunk/drivers/staging/iio/dds/ad9951.c @@ -0,0 +1,254 @@ +/* + * Driver for ADI Direct Digital Synthesis ad9951 + * + * Copyright (c) 2010 Analog Devices Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +#define DRV_NAME "ad9951" + +#define CFR1 0x0 +#define CFR2 0x1 + +#define AUTO_OSK (1) +#define OSKEN (1 << 1) +#define LOAD_ARR (1 << 2) + +#define AUTO_SYNC (1 << 7) + +#define LSB_FST (1) +#define SDIO_IPT (1 << 1) +#define CLR_PHA (1 << 2) +#define SINE_OPT (1 << 4) +#define ACLR_PHA (1 << 5) + +#define VCO_RANGE (1 << 2) + +#define CRS_OPT (1 << 1) +#define HMANU_SYNC (1 << 2) +#define HSPD_SYNC (1 << 3) + +/* Register format: 1 byte addr + value */ +struct ad9951_config { + u8 asf[3]; + u8 arr[2]; + u8 ftw0[5]; + u8 ftw1[3]; +}; + +struct ad9951_state { + struct mutex lock; + struct iio_dev *idev; + struct spi_device *sdev; +}; + +static ssize_t ad9951_set_parameter(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct spi_message msg; + struct spi_transfer xfer; + int ret; + struct ad9951_config *config = (struct ad9951_config *)buf; + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad9951_state *st = idev->dev_data; + + xfer.len = 3; + xfer.tx_buf = &config->asf[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 2; + xfer.tx_buf = &config->arr[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 5; + xfer.tx_buf = &config->ftw0[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + xfer.len = 3; + xfer.tx_buf = &config->ftw1[0]; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; +error_ret: + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9951_set_parameter, 0); + +static void ad9951_init(struct ad9951_state *st) +{ + struct spi_message msg; + struct spi_transfer xfer; + int ret; + u8 cfr[5]; + + cfr[0] = CFR1; + cfr[1] = 0; + cfr[2] = LSB_FST | CLR_PHA | SINE_OPT | ACLR_PHA; + cfr[3] = AUTO_OSK | OSKEN | LOAD_ARR; + cfr[4] = 0; + + mutex_lock(&st->lock); + + xfer.len = 5; + xfer.tx_buf = 𝔠 + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + + cfr[0] = CFR2; + cfr[1] = VCO_RANGE; + cfr[2] = HSPD_SYNC; + cfr[3] = 0; + + mutex_lock(&st->lock); + + xfer.len = 4; + xfer.tx_buf = 𝔠 + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + +error_ret: + mutex_unlock(&st->lock); + + + +} + +static struct attribute *ad9951_attributes[] = { + &iio_dev_attr_dds.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad9951_attribute_group = { + .name = DRV_NAME, + .attrs = ad9951_attributes, +}; + +static int __devinit ad9951_probe(struct spi_device *spi) +{ + struct ad9951_state *st; + int ret = 0; + + st = kzalloc(sizeof(*st), GFP_KERNEL); + if (st == NULL) { + ret = -ENOMEM; + goto error_ret; + } + spi_set_drvdata(spi, st); + + mutex_init(&st->lock); + st->sdev = spi; + + st->idev = iio_allocate_device(); + if (st->idev == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->idev->dev.parent = &spi->dev; + st->idev->num_interrupt_lines = 0; + st->idev->event_attrs = NULL; + + st->idev->attrs = &ad9951_attribute_group; + st->idev->dev_data = (void *)(st); + st->idev->driver_module = THIS_MODULE; + st->idev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(st->idev); + if (ret) + goto error_free_dev; + spi->max_speed_hz = 2000000; + spi->mode = SPI_MODE_3; + spi->bits_per_word = 8; + spi_setup(spi); + ad9951_init(st); + return 0; + +error_free_dev: + iio_free_device(st->idev); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +static int __devexit ad9951_remove(struct spi_device *spi) +{ + struct ad9951_state *st = spi_get_drvdata(spi); + + iio_device_unregister(st->idev); + kfree(st); + + return 0; +} + +static struct spi_driver ad9951_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = ad9951_probe, + .remove = __devexit_p(ad9951_remove), +}; + +static __init int ad9951_spi_init(void) +{ + return spi_register_driver(&ad9951_driver); +} +module_init(ad9951_spi_init); + +static __exit void ad9951_spi_exit(void) +{ + spi_unregister_driver(&ad9951_driver); +} +module_exit(ad9951_spi_exit); + +MODULE_AUTHOR("Cliff Cai"); +MODULE_DESCRIPTION("Analog Devices ad9951 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/gyro/Kconfig b/trunk/drivers/staging/iio/gyro/Kconfig index c4043610c0df..236f15fdbfc9 100644 --- a/trunk/drivers/staging/iio/gyro/Kconfig +++ b/trunk/drivers/staging/iio/gyro/Kconfig @@ -3,11 +3,45 @@ # comment "Digital gyroscope sensors" +config ADIS16060 + tristate "Analog Devices ADIS16060 Yaw Rate Gyroscope with SPI driver" + depends on SPI + help + Say yes here to build support for Analog Devices adis16060 wide bandwidth + yaw rate gyroscope with SPI. + +config ADIS16080 + tristate "Analog Devices ADIS16080/100 Yaw Rate Gyroscope with SPI driver" + depends on SPI + help + Say yes here to build support for Analog Devices adis16080/100 Yaw Rate + Gyroscope with SPI. + +config ADIS16130 + tristate "Analog Devices ADIS16130 High Precision Angular Rate Sensor driver" + depends on SPI + help + Say yes here to build support for Analog Devices ADIS16130 High Precision + Angular Rate Sensor driver. + config ADIS16260 - tristate "Analog Devices ADIS16260/5 Digital Gyroscope Sensor SPI driver" + tristate "Analog Devices ADIS16260 ADIS16265 Digital Gyroscope Sensor SPI driver" depends on SPI select IIO_TRIGGER if IIO_RING_BUFFER select IIO_SW_RING if IIO_RING_BUFFER help - Say yes here to build support for Analog Devices adis16260/5 + Say yes here to build support for Analog Devices ADIS16260 ADIS16265 programmable digital gyroscope sensor. + + This driver can also be built as a module. If so, the module + will be called adis16260. + +config ADIS16251 + tristate "Analog Devices ADIS16251 Digital Gyroscope Sensor SPI driver" + depends on SPI + help + Say yes here to build support for Analog Devices adis16261 programmable + digital gyroscope sensor. + + This driver can also be built as a module. If so, the module + will be called adis16251. diff --git a/trunk/drivers/staging/iio/gyro/Makefile b/trunk/drivers/staging/iio/gyro/Makefile index b5f0dc01122c..2764c15025a5 100644 --- a/trunk/drivers/staging/iio/gyro/Makefile +++ b/trunk/drivers/staging/iio/gyro/Makefile @@ -2,6 +2,18 @@ # Makefile for digital gyroscope sensor drivers # +adis16060-y := adis16060_core.o +obj-$(CONFIG_ADIS16060) += adis16060.o + +adis16080-y := adis16080_core.o +obj-$(CONFIG_ADIS16080) += adis16080.o + +adis16130-y := adis16130_core.o +obj-$(CONFIG_ADIS16130) += adis16130.o + adis16260-y := adis16260_core.o adis16260-$(CONFIG_IIO_RING_BUFFER) += adis16260_ring.o adis16260_trigger.o obj-$(CONFIG_ADIS16260) += adis16260.o + +adis16251-y := adis16251_core.o +obj-$(CONFIG_ADIS16251) += adis16251.o diff --git a/trunk/drivers/staging/iio/gyro/adis16060.h b/trunk/drivers/staging/iio/gyro/adis16060.h new file mode 100644 index 000000000000..5c00e5385ee0 --- /dev/null +++ b/trunk/drivers/staging/iio/gyro/adis16060.h @@ -0,0 +1,101 @@ +#ifndef SPI_ADIS16060_H_ +#define SPI_ADIS16060_H_ + +#define ADIS16060_GYRO 0x20 /* Measure Angular Rate (Gyro) */ +#define ADIS16060_SUPPLY_OUT 0x10 /* Measure Temperature */ +#define ADIS16060_AIN2 0x80 /* Measure AIN2 */ +#define ADIS16060_AIN1 0x40 /* Measure AIN1 */ +#define ADIS16060_TEMP_OUT 0x22 /* Set Positive Self-Test and Output for Angular Rate */ +#define ADIS16060_ANGL_OUT 0x21 /* Set Negative Self-Test and Output for Angular Rate */ + +#define ADIS16060_MAX_TX 3 +#define ADIS16060_MAX_RX 3 + +/** + * struct adis16060_state - device instance specific data + * @us_w: actual spi_device to write data + * @work_trigger_to_ring: bh for triggered event handling + * @inter: used to check if new interrupt has been triggered + * @last_timestamp: passing timestamp from th to bh of interrupt handler + * @indio_dev: industrial I/O device structure + * @trig: data ready trigger registered with iio + * @tx: transmit buffer + * @rx: recieve buffer + * @buf_lock: mutex to protect tx and rx + **/ +struct adis16060_state { + struct spi_device *us_w; + struct spi_device *us_r; + struct work_struct work_trigger_to_ring; + s64 last_timestamp; + struct iio_dev *indio_dev; + struct iio_trigger *trig; + u8 *tx; + u8 *rx; + struct mutex buf_lock; +}; + +#if defined(CONFIG_IIO_RING_BUFFER) && defined(THIS_HAS_RING_BUFFER_SUPPORT) +/* At the moment triggers are only used for ring buffer + * filling. This may change! + */ + +enum adis16060_scan { + ADIS16060_SCAN_GYRO, + ADIS16060_SCAN_TEMP, + ADIS16060_SCAN_ADC_1, + ADIS16060_SCAN_ADC_2, +}; + +void adis16060_remove_trigger(struct iio_dev *indio_dev); +int adis16060_probe_trigger(struct iio_dev *indio_dev); + +ssize_t adis16060_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf); + + +int adis16060_configure_ring(struct iio_dev *indio_dev); +void adis16060_unconfigure_ring(struct iio_dev *indio_dev); + +int adis16060_initialize_ring(struct iio_ring_buffer *ring); +void adis16060_uninitialize_ring(struct iio_ring_buffer *ring); +#else /* CONFIG_IIO_RING_BUFFER */ + +static inline void adis16060_remove_trigger(struct iio_dev *indio_dev) +{ +} + +static inline int adis16060_probe_trigger(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline ssize_t +adis16060_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return 0; +} + +static int adis16060_configure_ring(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline void adis16060_unconfigure_ring(struct iio_dev *indio_dev) +{ +} + +static inline int adis16060_initialize_ring(struct iio_ring_buffer *ring) +{ + return 0; +} + +static inline void adis16060_uninitialize_ring(struct iio_ring_buffer *ring) +{ +} + +#endif /* CONFIG_IIO_RING_BUFFER */ +#endif /* SPI_ADIS16060_H_ */ diff --git a/trunk/drivers/staging/iio/gyro/adis16060_core.c b/trunk/drivers/staging/iio/gyro/adis16060_core.c new file mode 100644 index 000000000000..fc48aca04bd3 --- /dev/null +++ b/trunk/drivers/staging/iio/gyro/adis16060_core.c @@ -0,0 +1,319 @@ +/* + * ADIS16060 Wide Bandwidth Yaw Rate Gyroscope with SPI driver + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "gyro.h" +#include "../adc/adc.h" + +#include "adis16060.h" + +#define DRIVER_NAME "adis16060" + +struct adis16060_state *adis16060_st; + +int adis16060_spi_write(struct device *dev, + u8 val) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16060_state *st = iio_dev_get_devdata(indio_dev); + + mutex_lock(&st->buf_lock); + st->tx[0] = 0; + st->tx[1] = 0; + st->tx[2] = val; /* The last 8 bits clocked in are latched */ + + ret = spi_write(st->us_w, st->tx, 3); + mutex_unlock(&st->buf_lock); + + return ret; +} + +int adis16060_spi_read(struct device *dev, + u16 *val) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16060_state *st = iio_dev_get_devdata(indio_dev); + + mutex_lock(&st->buf_lock); + + ret = spi_read(st->us_r, st->rx, 3); + + /* The internal successive approximation ADC begins the conversion process + * on the falling edge of MSEL1 and starts to place data MSB first on the + * DOUT line at the 6th falling edge of SCLK + */ + if (ret == 0) + *val = ((st->rx[0] & 0x3) << 12) | (st->rx[1] << 4) | ((st->rx[2] >> 4) & 0xF); + mutex_unlock(&st->buf_lock); + + return ret; +} + +static ssize_t adis16060_read(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + u16 val; + ssize_t ret; + + /* Take the iio_dev status lock */ + mutex_lock(&indio_dev->mlock); + ret = adis16060_spi_read(dev, &val); + mutex_unlock(&indio_dev->mlock); + + if (ret == 0) + return sprintf(buf, "%d\n", val); + else + return ret; +} + +static ssize_t adis16060_write(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + int ret; + long val; + + ret = strict_strtol(buf, 16, &val); + if (ret) + goto error_ret; + ret = adis16060_spi_write(dev, val); + +error_ret: + return ret ? ret : len; +} + +#define IIO_DEV_ATTR_IN(_show) \ + IIO_DEVICE_ATTR(in, S_IRUGO, _show, NULL, 0) + +#define IIO_DEV_ATTR_OUT(_store) \ + IIO_DEVICE_ATTR(out, S_IRUGO, NULL, _store, 0) + +static IIO_DEV_ATTR_IN(adis16060_read); +static IIO_DEV_ATTR_OUT(adis16060_write); + +static IIO_CONST_ATTR(name, "adis16060"); + +static struct attribute *adis16060_event_attributes[] = { + NULL +}; + +static struct attribute_group adis16060_event_attribute_group = { + .attrs = adis16060_event_attributes, +}; + +static struct attribute *adis16060_attributes[] = { + &iio_dev_attr_in.dev_attr.attr, + &iio_dev_attr_out.dev_attr.attr, + &iio_const_attr_name.dev_attr.attr, + NULL +}; + +static const struct attribute_group adis16060_attribute_group = { + .attrs = adis16060_attributes, +}; + +static int __devinit adis16060_r_probe(struct spi_device *spi) +{ + int ret, regdone = 0; + struct adis16060_state *st = kzalloc(sizeof *st, GFP_KERNEL); + if (!st) { + ret = -ENOMEM; + goto error_ret; + } + /* this is only used for removal purposes */ + spi_set_drvdata(spi, st); + + /* Allocate the comms buffers */ + st->rx = kzalloc(sizeof(*st->rx)*ADIS16060_MAX_RX, GFP_KERNEL); + if (st->rx == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->tx = kzalloc(sizeof(*st->tx)*ADIS16060_MAX_TX, GFP_KERNEL); + if (st->tx == NULL) { + ret = -ENOMEM; + goto error_free_rx; + } + st->us_r = spi; + mutex_init(&st->buf_lock); + /* setup the industrialio driver allocated elements */ + st->indio_dev = iio_allocate_device(); + if (st->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_tx; + } + + st->indio_dev->dev.parent = &spi->dev; + st->indio_dev->num_interrupt_lines = 1; + st->indio_dev->event_attrs = &adis16060_event_attribute_group; + st->indio_dev->attrs = &adis16060_attribute_group; + st->indio_dev->dev_data = (void *)(st); + st->indio_dev->driver_module = THIS_MODULE; + st->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = adis16060_configure_ring(st->indio_dev); + if (ret) + goto error_free_dev; + + ret = iio_device_register(st->indio_dev); + if (ret) + goto error_unreg_ring_funcs; + regdone = 1; + + ret = adis16060_initialize_ring(st->indio_dev->ring); + if (ret) { + printk(KERN_ERR "failed to initialize the ring\n"); + goto error_unreg_ring_funcs; + } + + if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) { + ret = iio_register_interrupt_line(spi->irq, + st->indio_dev, + 0, + IRQF_TRIGGER_RISING, + "adis16060"); + if (ret) + goto error_uninitialize_ring; + + ret = adis16060_probe_trigger(st->indio_dev); + if (ret) + goto error_unregister_line; + } + + adis16060_st = st; + return 0; + +error_unregister_line: + if (st->indio_dev->modes & INDIO_RING_TRIGGERED) + iio_unregister_interrupt_line(st->indio_dev, 0); +error_uninitialize_ring: + adis16060_uninitialize_ring(st->indio_dev->ring); +error_unreg_ring_funcs: + adis16060_unconfigure_ring(st->indio_dev); +error_free_dev: + if (regdone) + iio_device_unregister(st->indio_dev); + else + iio_free_device(st->indio_dev); +error_free_tx: + kfree(st->tx); +error_free_rx: + kfree(st->rx); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +/* fixme, confirm ordering in this function */ +static int adis16060_r_remove(struct spi_device *spi) +{ + struct adis16060_state *st = spi_get_drvdata(spi); + struct iio_dev *indio_dev = st->indio_dev; + + flush_scheduled_work(); + + adis16060_remove_trigger(indio_dev); + if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) + iio_unregister_interrupt_line(indio_dev, 0); + + adis16060_uninitialize_ring(indio_dev->ring); + adis16060_unconfigure_ring(indio_dev); + iio_device_unregister(indio_dev); + kfree(st->tx); + kfree(st->rx); + kfree(st); + + return 0; +} + +static int __devinit adis16060_w_probe(struct spi_device *spi) +{ + int ret; + struct adis16060_state *st = adis16060_st; + if (!st) { + ret = -ENODEV; + goto error_ret; + } + spi_set_drvdata(spi, st); + st->us_w = spi; + return 0; + +error_ret: + return ret; +} + +static int adis16060_w_remove(struct spi_device *spi) +{ + return 0; +} + +static struct spi_driver adis16060_r_driver = { + .driver = { + .name = "adis16060_r", + .owner = THIS_MODULE, + }, + .probe = adis16060_r_probe, + .remove = __devexit_p(adis16060_r_remove), +}; + +static struct spi_driver adis16060_w_driver = { + .driver = { + .name = "adis16060_w", + .owner = THIS_MODULE, + }, + .probe = adis16060_w_probe, + .remove = __devexit_p(adis16060_w_remove), +}; + +static __init int adis16060_init(void) +{ + int ret; + + ret = spi_register_driver(&adis16060_r_driver); + if (ret < 0) + return ret; + + ret = spi_register_driver(&adis16060_w_driver); + if (ret < 0) { + spi_unregister_driver(&adis16060_r_driver); + return ret; + } + + return 0; +} +module_init(adis16060_init); + +static __exit void adis16060_exit(void) +{ + spi_unregister_driver(&adis16060_w_driver); + spi_unregister_driver(&adis16060_r_driver); +} +module_exit(adis16060_exit); + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices ADIS16060 Yaw Rate Gyroscope with SPI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/gyro/adis16080.h b/trunk/drivers/staging/iio/gyro/adis16080.h new file mode 100644 index 000000000000..3fcbe67f7c31 --- /dev/null +++ b/trunk/drivers/staging/iio/gyro/adis16080.h @@ -0,0 +1,102 @@ +#ifndef SPI_ADIS16080_H_ +#define SPI_ADIS16080_H_ + +#define ADIS16080_DIN_CODE 4 /* Output data format setting. 0: Twos complement. 1: Offset binary. */ +#define ADIS16080_DIN_GYRO (0 << 10) /* Gyroscope output */ +#define ADIS16080_DIN_TEMP (1 << 10) /* Temperature output */ +#define ADIS16080_DIN_AIN1 (2 << 10) +#define ADIS16080_DIN_AIN2 (3 << 10) +#define ADIS16080_DIN_WRITE (1 << 15) /* 1: Write contents on DIN to control register. + * 0: No changes to control register. + */ + +#define ADIS16080_MAX_TX 2 +#define ADIS16080_MAX_RX 2 + +/** + * struct adis16080_state - device instance specific data + * @us: actual spi_device to write data + * @work_trigger_to_ring: bh for triggered event handling + * @inter: used to check if new interrupt has been triggered + * @last_timestamp: passing timestamp from th to bh of interrupt handler + * @indio_dev: industrial I/O device structure + * @trig: data ready trigger registered with iio + * @tx: transmit buffer + * @rx: recieve buffer + * @buf_lock: mutex to protect tx and rx + **/ +struct adis16080_state { + struct spi_device *us; + struct work_struct work_trigger_to_ring; + s64 last_timestamp; + struct iio_dev *indio_dev; + struct iio_trigger *trig; + u8 *tx; + u8 *rx; + struct mutex buf_lock; +}; + +#if defined(CONFIG_IIO_RING_BUFFER) && defined(THIS_HAS_RING_BUFFER_SUPPORT) +/* At the moment triggers are only used for ring buffer + * filling. This may change! + */ + +enum adis16080_scan { + ADIS16080_SCAN_GYRO, + ADIS16080_SCAN_TEMP, + ADIS16080_SCAN_ADC_1, + ADIS16080_SCAN_ADC_2, +}; + +void adis16080_remove_trigger(struct iio_dev *indio_dev); +int adis16080_probe_trigger(struct iio_dev *indio_dev); + +ssize_t adis16080_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf); + + +int adis16080_configure_ring(struct iio_dev *indio_dev); +void adis16080_unconfigure_ring(struct iio_dev *indio_dev); + +int adis16080_initialize_ring(struct iio_ring_buffer *ring); +void adis16080_uninitialize_ring(struct iio_ring_buffer *ring); +#else /* CONFIG_IIO_RING_BUFFER */ + +static inline void adis16080_remove_trigger(struct iio_dev *indio_dev) +{ +} + +static inline int adis16080_probe_trigger(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline ssize_t +adis16080_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return 0; +} + +static int adis16080_configure_ring(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline void adis16080_unconfigure_ring(struct iio_dev *indio_dev) +{ +} + +static inline int adis16080_initialize_ring(struct iio_ring_buffer *ring) +{ + return 0; +} + +static inline void adis16080_uninitialize_ring(struct iio_ring_buffer *ring) +{ +} + +#endif /* CONFIG_IIO_RING_BUFFER */ +#endif /* SPI_ADIS16080_H_ */ diff --git a/trunk/drivers/staging/iio/gyro/adis16080_core.c b/trunk/drivers/staging/iio/gyro/adis16080_core.c new file mode 100644 index 000000000000..0efb768db7d3 --- /dev/null +++ b/trunk/drivers/staging/iio/gyro/adis16080_core.c @@ -0,0 +1,271 @@ +/* + * ADIS16080/100 Yaw Rate Gyroscope with SPI driver + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "gyro.h" +#include "../adc/adc.h" + +#include "adis16080.h" + +#define DRIVER_NAME "adis16080" + +struct adis16080_state *adis16080_st; + +int adis16080_spi_write(struct device *dev, + u16 val) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16080_state *st = iio_dev_get_devdata(indio_dev); + + mutex_lock(&st->buf_lock); + st->tx[0] = val >> 8; + st->tx[1] = val; + + ret = spi_write(st->us, st->tx, 2); + mutex_unlock(&st->buf_lock); + + return ret; +} + +int adis16080_spi_read(struct device *dev, + u16 *val) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16080_state *st = iio_dev_get_devdata(indio_dev); + + mutex_lock(&st->buf_lock); + + ret = spi_read(st->us, st->rx, 2); + + if (ret == 0) + *val = ((st->rx[0] & 0xF) << 8) | st->rx[1]; + mutex_unlock(&st->buf_lock); + + return ret; +} + +static ssize_t adis16080_read(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + u16 val; + ssize_t ret; + + /* Take the iio_dev status lock */ + mutex_lock(&indio_dev->mlock); + ret = adis16080_spi_read(dev, &val); + mutex_unlock(&indio_dev->mlock); + + if (ret == 0) + return sprintf(buf, "%d\n", val); + else + return ret; +} + +static ssize_t adis16080_write(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + int ret; + long val; + + ret = strict_strtol(buf, 16, &val); + if (ret) + goto error_ret; + ret = adis16080_spi_write(dev, val); + +error_ret: + return ret ? ret : len; +} + +#define IIO_DEV_ATTR_IN(_show) \ + IIO_DEVICE_ATTR(in, S_IRUGO, _show, NULL, 0) + +#define IIO_DEV_ATTR_OUT(_store) \ + IIO_DEVICE_ATTR(out, S_IRUGO, NULL, _store, 0) + +static IIO_DEV_ATTR_IN(adis16080_read); +static IIO_DEV_ATTR_OUT(adis16080_write); + +static IIO_CONST_ATTR(name, "adis16080"); + +static struct attribute *adis16080_event_attributes[] = { + NULL +}; + +static struct attribute_group adis16080_event_attribute_group = { + .attrs = adis16080_event_attributes, +}; + +static struct attribute *adis16080_attributes[] = { + &iio_dev_attr_in.dev_attr.attr, + &iio_dev_attr_out.dev_attr.attr, + &iio_const_attr_name.dev_attr.attr, + NULL +}; + +static const struct attribute_group adis16080_attribute_group = { + .attrs = adis16080_attributes, +}; + +static int __devinit adis16080_probe(struct spi_device *spi) +{ + int ret, regdone = 0; + struct adis16080_state *st = kzalloc(sizeof *st, GFP_KERNEL); + if (!st) { + ret = -ENOMEM; + goto error_ret; + } + /* this is only used for removal purposes */ + spi_set_drvdata(spi, st); + + /* Allocate the comms buffers */ + st->rx = kzalloc(sizeof(*st->rx)*ADIS16080_MAX_RX, GFP_KERNEL); + if (st->rx == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->tx = kzalloc(sizeof(*st->tx)*ADIS16080_MAX_TX, GFP_KERNEL); + if (st->tx == NULL) { + ret = -ENOMEM; + goto error_free_rx; + } + st->us = spi; + mutex_init(&st->buf_lock); + /* setup the industrialio driver allocated elements */ + st->indio_dev = iio_allocate_device(); + if (st->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_tx; + } + + st->indio_dev->dev.parent = &spi->dev; + st->indio_dev->num_interrupt_lines = 1; + st->indio_dev->event_attrs = &adis16080_event_attribute_group; + st->indio_dev->attrs = &adis16080_attribute_group; + st->indio_dev->dev_data = (void *)(st); + st->indio_dev->driver_module = THIS_MODULE; + st->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = adis16080_configure_ring(st->indio_dev); + if (ret) + goto error_free_dev; + + ret = iio_device_register(st->indio_dev); + if (ret) + goto error_unreg_ring_funcs; + regdone = 1; + + ret = adis16080_initialize_ring(st->indio_dev->ring); + if (ret) { + printk(KERN_ERR "failed to initialize the ring\n"); + goto error_unreg_ring_funcs; + } + + if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) { + ret = iio_register_interrupt_line(spi->irq, + st->indio_dev, + 0, + IRQF_TRIGGER_RISING, + "adis16080"); + if (ret) + goto error_uninitialize_ring; + + ret = adis16080_probe_trigger(st->indio_dev); + if (ret) + goto error_unregister_line; + } + + adis16080_st = st; + return 0; + +error_unregister_line: + if (st->indio_dev->modes & INDIO_RING_TRIGGERED) + iio_unregister_interrupt_line(st->indio_dev, 0); +error_uninitialize_ring: + adis16080_uninitialize_ring(st->indio_dev->ring); +error_unreg_ring_funcs: + adis16080_unconfigure_ring(st->indio_dev); +error_free_dev: + if (regdone) + iio_device_unregister(st->indio_dev); + else + iio_free_device(st->indio_dev); +error_free_tx: + kfree(st->tx); +error_free_rx: + kfree(st->rx); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +/* fixme, confirm ordering in this function */ +static int adis16080_remove(struct spi_device *spi) +{ + struct adis16080_state *st = spi_get_drvdata(spi); + struct iio_dev *indio_dev = st->indio_dev; + + flush_scheduled_work(); + + adis16080_remove_trigger(indio_dev); + if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) + iio_unregister_interrupt_line(indio_dev, 0); + + adis16080_uninitialize_ring(indio_dev->ring); + adis16080_unconfigure_ring(indio_dev); + iio_device_unregister(indio_dev); + kfree(st->tx); + kfree(st->rx); + kfree(st); + + return 0; +} + +static struct spi_driver adis16080_driver = { + .driver = { + .name = "adis16080", + .owner = THIS_MODULE, + }, + .probe = adis16080_probe, + .remove = __devexit_p(adis16080_remove), +}; + +static __init int adis16080_init(void) +{ + return spi_register_driver(&adis16080_driver); +} +module_init(adis16080_init); + +static __exit void adis16080_exit(void) +{ + spi_unregister_driver(&adis16080_driver); +} +module_exit(adis16080_exit); + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices ADIS16080/100 Yaw Rate Gyroscope with SPI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/gyro/adis16130.h b/trunk/drivers/staging/iio/gyro/adis16130.h new file mode 100644 index 000000000000..ab80ef6a8961 --- /dev/null +++ b/trunk/drivers/staging/iio/gyro/adis16130.h @@ -0,0 +1,108 @@ +#ifndef SPI_ADIS16130_H_ +#define SPI_ADIS16130_H_ + +#define ADIS16130_CON 0x0 +#define ADIS16130_CON_RD (1 << 6) +#define ADIS16130_IOP 0x1 +#define ADIS16130_IOP_ALL_RDY (1 << 3) /* 1 = data-ready signal low when unread data on all channels; */ +#define ADIS16130_IOP_SYNC (1 << 0) /* 1 = synchronization enabled */ +#define ADIS16130_RATEDATA 0x8 /* Gyroscope output, rate of rotation */ +#define ADIS16130_TEMPDATA 0xA /* Temperature output */ +#define ADIS16130_RATECS 0x28 /* Gyroscope channel setup */ +#define ADIS16130_RATECS_EN (1 << 3) /* 1 = channel enable; */ +#define ADIS16130_TEMPCS 0x2A /* Temperature channel setup */ +#define ADIS16130_TEMPCS_EN (1 << 3) +#define ADIS16130_RATECONV 0x30 +#define ADIS16130_TEMPCONV 0x32 +#define ADIS16130_MODE 0x38 +#define ADIS16130_MODE_24BIT (1 << 1) /* 1 = 24-bit resolution; */ + +#define ADIS16130_MAX_TX 4 +#define ADIS16130_MAX_RX 4 + +/** + * struct adis16130_state - device instance specific data + * @us: actual spi_device to write data + * @work_trigger_to_ring: bh for triggered event handling + * @inter: used to check if new interrupt has been triggered + * @last_timestamp: passing timestamp from th to bh of interrupt handler + * @indio_dev: industrial I/O device structure + * @trig: data ready trigger registered with iio + * @tx: transmit buffer + * @rx: recieve buffer + * @buf_lock: mutex to protect tx and rx + **/ +struct adis16130_state { + struct spi_device *us; + struct work_struct work_trigger_to_ring; + s64 last_timestamp; + struct iio_dev *indio_dev; + struct iio_trigger *trig; + u8 *tx; + u8 *rx; + u32 mode; /* 1: 24bits mode 0:16bits mode */ + struct mutex buf_lock; +}; + +#if defined(CONFIG_IIO_RING_BUFFER) && defined(THIS_HAS_RING_BUFFER_SUPPORT) +/* At the moment triggers are only used for ring buffer + * filling. This may change! + */ + +enum adis16130_scan { + ADIS16130_SCAN_GYRO, + ADIS16130_SCAN_TEMP, +}; + +void adis16130_remove_trigger(struct iio_dev *indio_dev); +int adis16130_probe_trigger(struct iio_dev *indio_dev); + +ssize_t adis16130_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf); + + +int adis16130_configure_ring(struct iio_dev *indio_dev); +void adis16130_unconfigure_ring(struct iio_dev *indio_dev); + +int adis16130_initialize_ring(struct iio_ring_buffer *ring); +void adis16130_uninitialize_ring(struct iio_ring_buffer *ring); +#else /* CONFIG_IIO_RING_BUFFER */ + +static inline void adis16130_remove_trigger(struct iio_dev *indio_dev) +{ +} + +static inline int adis16130_probe_trigger(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline ssize_t +adis16130_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return 0; +} + +static int adis16130_configure_ring(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline void adis16130_unconfigure_ring(struct iio_dev *indio_dev) +{ +} + +static inline int adis16130_initialize_ring(struct iio_ring_buffer *ring) +{ + return 0; +} + +static inline void adis16130_uninitialize_ring(struct iio_ring_buffer *ring) +{ +} + +#endif /* CONFIG_IIO_RING_BUFFER */ +#endif /* SPI_ADIS16130_H_ */ diff --git a/trunk/drivers/staging/iio/gyro/adis16130_core.c b/trunk/drivers/staging/iio/gyro/adis16130_core.c new file mode 100644 index 000000000000..49ffc7b26e8a --- /dev/null +++ b/trunk/drivers/staging/iio/gyro/adis16130_core.c @@ -0,0 +1,313 @@ +/* + * ADIS16130 Digital Output, High Precision Angular Rate Sensor driver + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "gyro.h" +#include "../adc/adc.h" + +#include "adis16130.h" + +#define DRIVER_NAME "adis16130" + +struct adis16130_state *adis16130_st; + +int adis16130_spi_write(struct device *dev, u8 reg_addr, + u8 val) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16130_state *st = iio_dev_get_devdata(indio_dev); + + mutex_lock(&st->buf_lock); + st->tx[0] = reg_addr; + st->tx[1] = val; + + ret = spi_write(st->us, st->tx, 2); + mutex_unlock(&st->buf_lock); + + return ret; +} + +int adis16130_spi_read(struct device *dev, u8 reg_addr, + u32 *val) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16130_state *st = iio_dev_get_devdata(indio_dev); + + mutex_lock(&st->buf_lock); + + st->tx[0] = ADIS16130_CON_RD | reg_addr; + if (st->mode) + ret = spi_read(st->us, st->rx, 4); + else + ret = spi_read(st->us, st->rx, 3); + + if (ret == 0) { + if (st->mode) + *val = (st->rx[1] << 16) | (st->rx[2] << 8) | st->rx[3]; + else + *val = (st->rx[1] << 8) | st->rx[2]; + } + + mutex_unlock(&st->buf_lock); + + return ret; +} + +static ssize_t adis16130_gyro_read(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + u32 val; + ssize_t ret; + + /* Take the iio_dev status lock */ + mutex_lock(&indio_dev->mlock); + ret = adis16130_spi_read(dev, ADIS16130_RATEDATA, &val); + mutex_unlock(&indio_dev->mlock); + + if (ret == 0) + return sprintf(buf, "%d\n", val); + else + return ret; +} + +static ssize_t adis16130_temp_read(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + u32 val; + ssize_t ret; + + /* Take the iio_dev status lock */ + mutex_lock(&indio_dev->mlock); + ret = adis16130_spi_read(dev, ADIS16130_TEMPDATA, &val); + mutex_unlock(&indio_dev->mlock); + + if (ret == 0) + return sprintf(buf, "%d\n", val); + else + return ret; +} + +static ssize_t adis16130_bitsmode_read(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16130_state *st = iio_dev_get_devdata(indio_dev); + + return sprintf(buf, "%d\n", st->mode); +} + +static ssize_t adis16130_bitsmode_write(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + int ret; + long val; + + ret = strict_strtol(buf, 16, &val); + if (ret) + goto error_ret; + ret = adis16130_spi_write(dev, ADIS16130_MODE, !!val); + +error_ret: + return ret ? ret : len; +} + +static IIO_DEV_ATTR_TEMP_RAW(adis16130_temp_read); + +static IIO_CONST_ATTR(name, "adis16130"); + +static IIO_DEV_ATTR_GYRO(adis16130_gyro_read, + ADIS16130_RATEDATA); + +#define IIO_DEV_ATTR_BITS_MODE(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(bits_mode, _mode, _show, _store, _addr) + +static IIO_DEV_ATTR_BITS_MODE(S_IWUSR | S_IRUGO, adis16130_bitsmode_read, adis16130_bitsmode_write, + ADIS16130_MODE); + +static struct attribute *adis16130_event_attributes[] = { + NULL +}; + +static struct attribute_group adis16130_event_attribute_group = { + .attrs = adis16130_event_attributes, +}; + +static struct attribute *adis16130_attributes[] = { + &iio_dev_attr_temp_raw.dev_attr.attr, + &iio_const_attr_name.dev_attr.attr, + &iio_dev_attr_gyro_raw.dev_attr.attr, + &iio_dev_attr_bits_mode.dev_attr.attr, + NULL +}; + +static const struct attribute_group adis16130_attribute_group = { + .attrs = adis16130_attributes, +}; + +static int __devinit adis16130_probe(struct spi_device *spi) +{ + int ret, regdone = 0; + struct adis16130_state *st = kzalloc(sizeof *st, GFP_KERNEL); + if (!st) { + ret = -ENOMEM; + goto error_ret; + } + /* this is only used for removal purposes */ + spi_set_drvdata(spi, st); + + /* Allocate the comms buffers */ + st->rx = kzalloc(sizeof(*st->rx)*ADIS16130_MAX_RX, GFP_KERNEL); + if (st->rx == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->tx = kzalloc(sizeof(*st->tx)*ADIS16130_MAX_TX, GFP_KERNEL); + if (st->tx == NULL) { + ret = -ENOMEM; + goto error_free_rx; + } + st->us = spi; + mutex_init(&st->buf_lock); + /* setup the industrialio driver allocated elements */ + st->indio_dev = iio_allocate_device(); + if (st->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_tx; + } + + st->indio_dev->dev.parent = &spi->dev; + st->indio_dev->num_interrupt_lines = 1; + st->indio_dev->event_attrs = &adis16130_event_attribute_group; + st->indio_dev->attrs = &adis16130_attribute_group; + st->indio_dev->dev_data = (void *)(st); + st->indio_dev->driver_module = THIS_MODULE; + st->indio_dev->modes = INDIO_DIRECT_MODE; + st->mode = 1; + + ret = adis16130_configure_ring(st->indio_dev); + if (ret) + goto error_free_dev; + + ret = iio_device_register(st->indio_dev); + if (ret) + goto error_unreg_ring_funcs; + regdone = 1; + + ret = adis16130_initialize_ring(st->indio_dev->ring); + if (ret) { + printk(KERN_ERR "failed to initialize the ring\n"); + goto error_unreg_ring_funcs; + } + + if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) { + ret = iio_register_interrupt_line(spi->irq, + st->indio_dev, + 0, + IRQF_TRIGGER_RISING, + "adis16130"); + if (ret) + goto error_uninitialize_ring; + + ret = adis16130_probe_trigger(st->indio_dev); + if (ret) + goto error_unregister_line; + } + + adis16130_st = st; + return 0; + +error_unregister_line: + if (st->indio_dev->modes & INDIO_RING_TRIGGERED) + iio_unregister_interrupt_line(st->indio_dev, 0); +error_uninitialize_ring: + adis16130_uninitialize_ring(st->indio_dev->ring); +error_unreg_ring_funcs: + adis16130_unconfigure_ring(st->indio_dev); +error_free_dev: + if (regdone) + iio_device_unregister(st->indio_dev); + else + iio_free_device(st->indio_dev); +error_free_tx: + kfree(st->tx); +error_free_rx: + kfree(st->rx); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +/* fixme, confirm ordering in this function */ +static int adis16130_remove(struct spi_device *spi) +{ + struct adis16130_state *st = spi_get_drvdata(spi); + struct iio_dev *indio_dev = st->indio_dev; + + flush_scheduled_work(); + + adis16130_remove_trigger(indio_dev); + if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) + iio_unregister_interrupt_line(indio_dev, 0); + + adis16130_uninitialize_ring(indio_dev->ring); + adis16130_unconfigure_ring(indio_dev); + iio_device_unregister(indio_dev); + kfree(st->tx); + kfree(st->rx); + kfree(st); + + return 0; +} + +static struct spi_driver adis16130_driver = { + .driver = { + .name = "adis16130", + .owner = THIS_MODULE, + }, + .probe = adis16130_probe, + .remove = __devexit_p(adis16130_remove), +}; + +static __init int adis16130_init(void) +{ + return spi_register_driver(&adis16130_driver); +} +module_init(adis16130_init); + +static __exit void adis16130_exit(void) +{ + spi_unregister_driver(&adis16130_driver); +} +module_exit(adis16130_exit); + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices ADIS16130 High Precision Angular Rate Sensor driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/gyro/adis16251.h b/trunk/drivers/staging/iio/gyro/adis16251.h new file mode 100644 index 000000000000..999db4981413 --- /dev/null +++ b/trunk/drivers/staging/iio/gyro/adis16251.h @@ -0,0 +1,185 @@ +#ifndef SPI_ADIS16251_H_ +#define SPI_ADIS16251_H_ + +#define ADIS16251_STARTUP_DELAY 220 /* ms */ + +#define ADIS16251_READ_REG(a) a +#define ADIS16251_WRITE_REG(a) ((a) | 0x80) + +#define ADIS16251_ENDURANCE 0x00 /* Flash memory write count */ +#define ADIS16251_SUPPLY_OUT 0x02 /* Power supply measurement */ +#define ADIS16251_GYRO_OUT 0x04 /* X-axis gyroscope output */ +#define ADIS16251_AUX_ADC 0x0A /* analog input channel measurement */ +#define ADIS16251_TEMP_OUT 0x0C /* internal temperature measurement */ +#define ADIS16251_ANGL_OUT 0x0E /* angle displacement */ +#define ADIS16251_GYRO_OFF 0x14 /* Calibration, offset/bias adjustment */ +#define ADIS16251_GYRO_SCALE 0x16 /* Calibration, scale adjustment */ +#define ADIS16251_ALM_MAG1 0x20 /* Alarm 1 magnitude/polarity setting */ +#define ADIS16251_ALM_MAG2 0x22 /* Alarm 2 magnitude/polarity setting */ +#define ADIS16251_ALM_SMPL1 0x24 /* Alarm 1 dynamic rate of change setting */ +#define ADIS16251_ALM_SMPL2 0x26 /* Alarm 2 dynamic rate of change setting */ +#define ADIS16251_ALM_CTRL 0x28 /* Alarm control */ +#define ADIS16251_AUX_DAC 0x30 /* Auxiliary DAC data */ +#define ADIS16251_GPIO_CTRL 0x32 /* Control, digital I/O line */ +#define ADIS16251_MSC_CTRL 0x34 /* Control, data ready, self-test settings */ +#define ADIS16251_SMPL_PRD 0x36 /* Control, internal sample rate */ +#define ADIS16251_SENS_AVG 0x38 /* Control, dynamic range, filtering */ +#define ADIS16251_SLP_CNT 0x3A /* Control, sleep mode initiation */ +#define ADIS16251_DIAG_STAT 0x3C /* Diagnostic, error flags */ +#define ADIS16251_GLOB_CMD 0x3E /* Control, global commands */ + +#define ADIS16251_ERROR_ACTIVE (1<<14) +#define ADIS16251_NEW_DATA (1<<14) + +/* MSC_CTRL */ +#define ADIS16251_MSC_CTRL_INT_SELF_TEST (1<<10) /* Internal self-test enable */ +#define ADIS16251_MSC_CTRL_NEG_SELF_TEST (1<<9) +#define ADIS16251_MSC_CTRL_POS_SELF_TEST (1<<8) +#define ADIS16251_MSC_CTRL_DATA_RDY_EN (1<<2) +#define ADIS16251_MSC_CTRL_DATA_RDY_POL_HIGH (1<<1) +#define ADIS16251_MSC_CTRL_DATA_RDY_DIO2 (1<<0) + +/* SMPL_PRD */ +#define ADIS16251_SMPL_PRD_TIME_BASE (1<<7) /* Time base (tB): 0 = 1.953 ms, 1 = 60.54 ms */ +#define ADIS16251_SMPL_PRD_DIV_MASK 0x7F + +/* SLP_CNT */ +#define ADIS16251_SLP_CNT_POWER_OFF 0x80 + +/* DIAG_STAT */ +#define ADIS16251_DIAG_STAT_ALARM2 (1<<9) +#define ADIS16251_DIAG_STAT_ALARM1 (1<<8) +#define ADIS16251_DIAG_STAT_SELF_TEST (1<<5) +#define ADIS16251_DIAG_STAT_OVERFLOW (1<<4) +#define ADIS16251_DIAG_STAT_SPI_FAIL (1<<3) +#define ADIS16251_DIAG_STAT_FLASH_UPT (1<<2) +#define ADIS16251_DIAG_STAT_POWER_HIGH (1<<1) +#define ADIS16251_DIAG_STAT_POWER_LOW (1<<0) + +#define ADIS16251_DIAG_STAT_ERR_MASK (ADIS16261_DIAG_STAT_ALARM2 | \ + ADIS16261_DIAG_STAT_ALARM1 | \ + ADIS16261_DIAG_STAT_SELF_TEST | \ + ADIS16261_DIAG_STAT_OVERFLOW | \ + ADIS16261_DIAG_STAT_SPI_FAIL | \ + ADIS16261_DIAG_STAT_FLASH_UPT | \ + ADIS16261_DIAG_STAT_POWER_HIGH | \ + ADIS16261_DIAG_STAT_POWER_LOW) + +/* GLOB_CMD */ +#define ADIS16251_GLOB_CMD_SW_RESET (1<<7) +#define ADIS16251_GLOB_CMD_FLASH_UPD (1<<3) +#define ADIS16251_GLOB_CMD_DAC_LATCH (1<<2) +#define ADIS16251_GLOB_CMD_FAC_CALIB (1<<1) +#define ADIS16251_GLOB_CMD_AUTO_NULL (1<<0) + +#define ADIS16251_MAX_TX 24 +#define ADIS16251_MAX_RX 24 + +#define ADIS16251_SPI_SLOW (u32)(300 * 1000) +#define ADIS16251_SPI_BURST (u32)(1000 * 1000) +#define ADIS16251_SPI_FAST (u32)(2000 * 1000) + +/** + * struct adis16251_state - device instance specific data + * @us: actual spi_device + * @work_trigger_to_ring: bh for triggered event handling + * @inter: used to check if new interrupt has been triggered + * @last_timestamp: passing timestamp from th to bh of interrupt handler + * @indio_dev: industrial I/O device structure + * @trig: data ready trigger registered with iio + * @tx: transmit buffer + * @rx: recieve buffer + * @buf_lock: mutex to protect tx and rx + **/ +struct adis16251_state { + struct spi_device *us; + struct work_struct work_trigger_to_ring; + s64 last_timestamp; + struct iio_dev *indio_dev; + struct iio_trigger *trig; + u8 *tx; + u8 *rx; + struct mutex buf_lock; +}; + +int adis16251_spi_write_reg_8(struct device *dev, + u8 reg_address, + u8 val); + +int adis16251_spi_read_burst(struct device *dev, u8 *rx); + +int adis16251_spi_read_sequence(struct device *dev, + u8 *tx, u8 *rx, int num); + +int adis16251_set_irq(struct device *dev, bool enable); + +int adis16251_reset(struct device *dev); + +int adis16251_stop_device(struct device *dev); + +int adis16251_check_status(struct device *dev); + +#if defined(CONFIG_IIO_RING_BUFFER) && defined(THIS_HAS_RING_BUFFER_SUPPORT) +/* At the moment triggers are only used for ring buffer + * filling. This may change! + */ + +enum adis16251_scan { + ADIS16251_SCAN_SUPPLY, + ADIS16251_SCAN_GYRO, + ADIS16251_SCAN_TEMP, + ADIS16251_SCAN_ADC_0, +}; + +void adis16251_remove_trigger(struct iio_dev *indio_dev); +int adis16251_probe_trigger(struct iio_dev *indio_dev); + +ssize_t adis16251_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf); + + +int adis16251_configure_ring(struct iio_dev *indio_dev); +void adis16251_unconfigure_ring(struct iio_dev *indio_dev); + +int adis16251_initialize_ring(struct iio_ring_buffer *ring); +void adis16251_uninitialize_ring(struct iio_ring_buffer *ring); +#else /* CONFIG_IIO_RING_BUFFER */ + +static inline void adis16251_remove_trigger(struct iio_dev *indio_dev) +{ +} + +static inline int adis16251_probe_trigger(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline ssize_t +adis16251_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return 0; +} + +static int adis16251_configure_ring(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline void adis16251_unconfigure_ring(struct iio_dev *indio_dev) +{ +} + +static inline int adis16251_initialize_ring(struct iio_ring_buffer *ring) +{ + return 0; +} + +static inline void adis16251_uninitialize_ring(struct iio_ring_buffer *ring) +{ +} + +#endif /* CONFIG_IIO_RING_BUFFER */ +#endif /* SPI_ADIS16251_H_ */ diff --git a/trunk/drivers/staging/iio/gyro/adis16251_core.c b/trunk/drivers/staging/iio/gyro/adis16251_core.c new file mode 100644 index 000000000000..a0d400f7ee62 --- /dev/null +++ b/trunk/drivers/staging/iio/gyro/adis16251_core.c @@ -0,0 +1,777 @@ +/* + * ADIS16251 Programmable Digital Gyroscope Sensor Driver + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "gyro.h" +#include "../adc/adc.h" + +#include "adis16251.h" + +#define DRIVER_NAME "adis16251" + +/* At the moment the spi framework doesn't allow global setting of cs_change. + * It's in the likely to be added comment at the top of spi.h. + * This means that use cannot be made of spi_write etc. + */ + +/** + * adis16251_spi_write_reg_8() - write single byte to a register + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @reg_address: the address of the register to be written + * @val: the value to write + **/ +int adis16251_spi_write_reg_8(struct device *dev, + u8 reg_address, + u8 val) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16251_state *st = iio_dev_get_devdata(indio_dev); + + mutex_lock(&st->buf_lock); + st->tx[0] = ADIS16251_WRITE_REG(reg_address); + st->tx[1] = val; + + ret = spi_write(st->us, st->tx, 2); + mutex_unlock(&st->buf_lock); + + return ret; +} + +/** + * adis16251_spi_write_reg_16() - write 2 bytes to a pair of registers + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @reg_address: the address of the lower of the two registers. Second register + * is assumed to have address one greater. + * @val: value to be written + **/ +static int adis16251_spi_write_reg_16(struct device *dev, + u8 lower_reg_address, + u16 value) +{ + int ret; + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16251_state *st = iio_dev_get_devdata(indio_dev); + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + }, { + .tx_buf = st->tx + 2, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADIS16251_WRITE_REG(lower_reg_address); + st->tx[1] = value & 0xFF; + st->tx[2] = ADIS16251_WRITE_REG(lower_reg_address + 1); + st->tx[3] = (value >> 8) & 0xFF; + + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(st->us, &msg); + mutex_unlock(&st->buf_lock); + + return ret; +} + +/** + * adis16251_spi_read_reg_16() - read 2 bytes from a 16-bit register + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @reg_address: the address of the lower of the two registers. Second register + * is assumed to have address one greater. + * @val: somewhere to pass back the value read + **/ +static int adis16251_spi_read_reg_16(struct device *dev, + u8 lower_reg_address, + u16 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16251_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + }, { + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 2, + .cs_change = 1, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADIS16251_READ_REG(lower_reg_address); + st->tx[1] = 0; + st->tx[2] = 0; + st->tx[3] = 0; + + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", + lower_reg_address); + goto error_ret; + } + *val = (st->rx[0] << 8) | st->rx[1]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +/** + * adis16251_spi_read_burst() - read all data registers + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @rx: somewhere to pass back the value read (min size is 24 bytes) + **/ +int adis16251_spi_read_burst(struct device *dev, u8 *rx) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16251_state *st = iio_dev_get_devdata(indio_dev); + u32 old_speed_hz = st->us->max_speed_hz; + int ret; + + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 2, + .cs_change = 0, + }, { + .rx_buf = rx, + .bits_per_word = 8, + .len = 24, + .cs_change = 1, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADIS16251_READ_REG(ADIS16251_GLOB_CMD); + st->tx[1] = 0; + + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + + st->us->max_speed_hz = min(ADIS16251_SPI_BURST, old_speed_hz); + spi_setup(st->us); + + ret = spi_sync(st->us, &msg); + if (ret) + dev_err(&st->us->dev, "problem when burst reading"); + + st->us->max_speed_hz = old_speed_hz; + spi_setup(st->us); + mutex_unlock(&st->buf_lock); + return ret; +} + +/** + * adis16251_spi_read_sequence() - read a sequence of 16-bit registers + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @tx: register addresses in bytes 0,2,4,6... (min size is 2*num bytes) + * @rx: somewhere to pass back the value read (min size is 2*num bytes) + **/ +int adis16251_spi_read_sequence(struct device *dev, + u8 *tx, u8 *rx, int num) +{ + struct spi_message msg; + struct spi_transfer *xfers; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16251_state *st = iio_dev_get_devdata(indio_dev); + int ret, i; + + xfers = kzalloc(num + 1, GFP_KERNEL); + if (xfers == NULL) { + dev_err(&st->us->dev, "memory alloc failed"); + ret = -ENOMEM; + goto error_ret; + } + + /* tx: |add1|addr2|addr3|...|addrN |zero| + * rx: |zero|res1 |res2 |...|resN-1|resN| */ + spi_message_init(&msg); + for (i = 0; i < num + 1; i++) { + if (i > 0) + xfers[i].rx_buf = st->rx + 2*(i - 1); + if (i < num) + xfers[i].tx_buf = st->tx + 2*i; + xfers[i].bits_per_word = 8; + xfers[i].len = 2; + xfers[i].cs_change = 1; + spi_message_add_tail(&xfers[i], &msg); + } + + mutex_lock(&st->buf_lock); + + ret = spi_sync(st->us, &msg); + if (ret) + dev_err(&st->us->dev, "problem when reading sequence"); + + mutex_unlock(&st->buf_lock); + kfree(xfers); + +error_ret: + return ret; +} + +static ssize_t adis16251_spi_read_signed(struct device *dev, + struct device_attribute *attr, + char *buf, + unsigned bits) +{ + int ret; + s16 val = 0; + unsigned shift = 16 - bits; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = adis16251_spi_read_reg_16(dev, this_attr->address, (u16 *)&val); + if (ret) + return ret; + + if (val & ADIS16251_ERROR_ACTIVE) + adis16251_check_status(dev); + val = ((s16)(val << shift) >> shift); + return sprintf(buf, "%d\n", val); +} + +static ssize_t adis16251_read_12bit_unsigned(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u16 val = 0; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = adis16251_spi_read_reg_16(dev, this_attr->address, &val); + if (ret) + return ret; + + if (val & ADIS16251_ERROR_ACTIVE) + adis16251_check_status(dev); + + return sprintf(buf, "%u\n", val & 0x0FFF); +} + +static ssize_t adis16251_read_14bit_signed(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + ssize_t ret; + + /* Take the iio_dev status lock */ + mutex_lock(&indio_dev->mlock); + ret = adis16251_spi_read_signed(dev, attr, buf, 14); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static ssize_t adis16251_read_12bit_signed(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + ssize_t ret; + + /* Take the iio_dev status lock */ + mutex_lock(&indio_dev->mlock); + ret = adis16251_spi_read_signed(dev, attr, buf, 12); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static ssize_t adis16251_write_16bit(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + long val; + + ret = strict_strtol(buf, 10, &val); + if (ret) + goto error_ret; + ret = adis16251_spi_write_reg_16(dev, this_attr->address, val); + +error_ret: + return ret ? ret : len; +} + +static ssize_t adis16251_read_frequency(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret, len = 0; + u16 t; + int sps; + ret = adis16251_spi_read_reg_16(dev, + ADIS16251_SMPL_PRD, + &t); + if (ret) + return ret; + sps = (t & ADIS16251_SMPL_PRD_TIME_BASE) ? 8 : 256; + sps /= (t & ADIS16251_SMPL_PRD_DIV_MASK) + 1; + len = sprintf(buf, "%d SPS\n", sps); + return len; +} + +static ssize_t adis16251_write_frequency(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct adis16251_state *st = iio_dev_get_devdata(indio_dev); + long val; + int ret; + u8 t; + + ret = strict_strtol(buf, 10, &val); + if (ret) + return ret; + + mutex_lock(&indio_dev->mlock); + + t = (256 / val); + if (t > 0) + t--; + t &= ADIS16251_SMPL_PRD_DIV_MASK; + if ((t & ADIS16251_SMPL_PRD_DIV_MASK) >= 0x0A) + st->us->max_speed_hz = ADIS16251_SPI_SLOW; + else + st->us->max_speed_hz = ADIS16251_SPI_FAST; + + ret = adis16251_spi_write_reg_8(dev, + ADIS16251_SMPL_PRD, + t); + + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static ssize_t adis16251_write_reset(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + if (len < 1) + return -1; + switch (buf[0]) { + case '1': + case 'y': + case 'Y': + return adis16251_reset(dev); + } + return -1; +} + + + +int adis16251_set_irq(struct device *dev, bool enable) +{ + int ret; + u16 msc; + ret = adis16251_spi_read_reg_16(dev, ADIS16251_MSC_CTRL, &msc); + if (ret) + goto error_ret; + + msc |= ADIS16251_MSC_CTRL_DATA_RDY_POL_HIGH; + if (enable) + msc |= ADIS16251_MSC_CTRL_DATA_RDY_EN; + else + msc &= ~ADIS16251_MSC_CTRL_DATA_RDY_EN; + + ret = adis16251_spi_write_reg_16(dev, ADIS16251_MSC_CTRL, msc); + if (ret) + goto error_ret; + +error_ret: + return ret; +} + +int adis16251_reset(struct device *dev) +{ + int ret; + ret = adis16251_spi_write_reg_8(dev, + ADIS16251_GLOB_CMD, + ADIS16251_GLOB_CMD_SW_RESET); + if (ret) + dev_err(dev, "problem resetting device"); + + return ret; +} + +/* Power down the device */ +int adis16251_stop_device(struct device *dev) +{ + int ret; + u16 val = ADIS16251_SLP_CNT_POWER_OFF; + + ret = adis16251_spi_write_reg_16(dev, ADIS16251_SLP_CNT, val); + if (ret) + dev_err(dev, "problem with turning device off: SLP_CNT"); + + return ret; +} + +static int adis16251_self_test(struct device *dev) +{ + int ret; + + ret = adis16251_spi_write_reg_16(dev, + ADIS16251_MSC_CTRL, + ADIS16251_MSC_CTRL_INT_SELF_TEST); + if (ret) { + dev_err(dev, "problem starting self test"); + goto err_ret; + } + + adis16251_check_status(dev); + +err_ret: + return ret; +} + +int adis16251_check_status(struct device *dev) +{ + u16 status; + int ret; + + ret = adis16251_spi_read_reg_16(dev, ADIS16251_DIAG_STAT, &status); + + if (ret < 0) { + dev_err(dev, "Reading status failed\n"); + goto error_ret; + } + + if (!(status & ADIS16251_DIAG_STAT_ERR_MASK)) { + ret = 0; + goto error_ret; + } + + ret = -EFAULT; + + if (status & ADIS16251_DIAG_STAT_ALARM2) + dev_err(dev, "Alarm 2 active\n"); + if (status & ADIS16251_DIAG_STAT_ALARM1) + dev_err(dev, "Alarm 1 active\n"); + if (status & ADIS16251_DIAG_STAT_SELF_TEST) + dev_err(dev, "Self test error\n"); + if (status & ADIS16251_DIAG_STAT_OVERFLOW) + dev_err(dev, "Sensor overrange\n"); + if (status & ADIS16251_DIAG_STAT_SPI_FAIL) + dev_err(dev, "SPI failure\n"); + if (status & ADIS16251_DIAG_STAT_FLASH_UPT) + dev_err(dev, "Flash update failed\n"); + if (status & ADIS16251_DIAG_STAT_POWER_HIGH) + dev_err(dev, "Power supply above 5.25V\n"); + if (status & ADIS16251_DIAG_STAT_POWER_LOW) + dev_err(dev, "Power supply below 4.75V\n"); + +error_ret: + return ret; +} + +static int adis16251_initial_setup(struct adis16251_state *st) +{ + int ret; + u16 smp_prd; + struct device *dev = &st->indio_dev->dev; + + /* use low spi speed for init */ + st->us->max_speed_hz = ADIS16251_SPI_SLOW; + st->us->mode = SPI_MODE_3; + spi_setup(st->us); + + /* Disable IRQ */ + ret = adis16251_set_irq(dev, false); + if (ret) { + dev_err(dev, "disable irq failed"); + goto err_ret; + } + + /* Do self test */ + + /* Read status register to check the result */ + ret = adis16251_check_status(dev); + if (ret) { + adis16251_reset(dev); + dev_err(dev, "device not playing ball -> reset"); + msleep(ADIS16251_STARTUP_DELAY); + ret = adis16251_check_status(dev); + if (ret) { + dev_err(dev, "giving up"); + goto err_ret; + } + } + + printk(KERN_INFO DRIVER_NAME ": at CS%d (irq %d)\n", + st->us->chip_select, st->us->irq); + + /* use high spi speed if possible */ + ret = adis16251_spi_read_reg_16(dev, ADIS16251_SMPL_PRD, &smp_prd); + if (!ret && (smp_prd & ADIS16251_SMPL_PRD_DIV_MASK) < 0x0A) { + st->us->max_speed_hz = ADIS16251_SPI_SLOW; + spi_setup(st->us); + } + +err_ret: + return ret; +} + +static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16251_read_12bit_signed, + ADIS16251_SUPPLY_OUT); +static IIO_CONST_ATTR(in0_supply_scale, "0.0018315"); + +static IIO_DEV_ATTR_GYRO(adis16251_read_14bit_signed, + ADIS16251_GYRO_OUT); +static IIO_DEV_ATTR_GYRO_SCALE(S_IWUSR | S_IRUGO, + adis16251_read_12bit_signed, + adis16251_write_16bit, + ADIS16251_GYRO_SCALE); +static IIO_DEV_ATTR_GYRO_OFFSET(S_IWUSR | S_IRUGO, + adis16251_read_12bit_signed, + adis16251_write_16bit, + ADIS16251_GYRO_OFF); + +static IIO_DEV_ATTR_TEMP_RAW(adis16251_read_12bit_signed); +static IIO_CONST_ATTR(temp_offset, "25 K"); +static IIO_CONST_ATTR(temp_scale, "0.1453 K"); + +static IIO_DEV_ATTR_IN_NAMED_RAW(1, aux, adis16251_read_12bit_unsigned, + ADIS16251_AUX_ADC); +static IIO_CONST_ATTR(in1_aux_scale, "0.0006105"); + +static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, + adis16251_read_frequency, + adis16251_write_frequency); +static IIO_DEV_ATTR_ANGL(adis16251_read_14bit_signed, + ADIS16251_ANGL_OUT); + +static IIO_DEV_ATTR_RESET(adis16251_write_reset); + +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("0.129 ~ 256"); + +static IIO_CONST_ATTR(name, "adis16251"); + +static struct attribute *adis16251_event_attributes[] = { + NULL +}; + +static struct attribute_group adis16251_event_attribute_group = { + .attrs = adis16251_event_attributes, +}; + +static struct attribute *adis16251_attributes[] = { + &iio_dev_attr_in0_supply_raw.dev_attr.attr, + &iio_const_attr_in0_supply_scale.dev_attr.attr, + &iio_dev_attr_gyro_raw.dev_attr.attr, + &iio_dev_attr_gyro_scale.dev_attr.attr, + &iio_dev_attr_gyro_offset.dev_attr.attr, + &iio_dev_attr_angl_raw.dev_attr.attr, + &iio_dev_attr_temp_raw.dev_attr.attr, + &iio_const_attr_temp_offset.dev_attr.attr, + &iio_const_attr_temp_scale.dev_attr.attr, + &iio_dev_attr_in1_aux_raw.dev_attr.attr, + &iio_const_attr_in1_aux_scale.dev_attr.attr, + &iio_dev_attr_sampling_frequency.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + &iio_dev_attr_reset.dev_attr.attr, + &iio_const_attr_name.dev_attr.attr, + NULL +}; + +static const struct attribute_group adis16251_attribute_group = { + .attrs = adis16251_attributes, +}; + +static int __devinit adis16251_probe(struct spi_device *spi) +{ + int ret, regdone = 0; + struct adis16251_state *st = kzalloc(sizeof *st, GFP_KERNEL); + if (!st) { + ret = -ENOMEM; + goto error_ret; + } + /* this is only used for removal purposes */ + spi_set_drvdata(spi, st); + + /* Allocate the comms buffers */ + st->rx = kzalloc(sizeof(*st->rx)*ADIS16251_MAX_RX, GFP_KERNEL); + if (st->rx == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->tx = kzalloc(sizeof(*st->tx)*ADIS16251_MAX_TX, GFP_KERNEL); + if (st->tx == NULL) { + ret = -ENOMEM; + goto error_free_rx; + } + st->us = spi; + mutex_init(&st->buf_lock); + /* setup the industrialio driver allocated elements */ + st->indio_dev = iio_allocate_device(); + if (st->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_tx; + } + + st->indio_dev->dev.parent = &spi->dev; + st->indio_dev->num_interrupt_lines = 1; + st->indio_dev->event_attrs = &adis16251_event_attribute_group; + st->indio_dev->attrs = &adis16251_attribute_group; + st->indio_dev->dev_data = (void *)(st); + st->indio_dev->driver_module = THIS_MODULE; + st->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = adis16251_configure_ring(st->indio_dev); + if (ret) + goto error_free_dev; + + ret = iio_device_register(st->indio_dev); + if (ret) + goto error_unreg_ring_funcs; + regdone = 1; + + ret = adis16251_initialize_ring(st->indio_dev->ring); + if (ret) { + printk(KERN_ERR "failed to initialize the ring\n"); + goto error_unreg_ring_funcs; + } + + if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) { + ret = iio_register_interrupt_line(spi->irq, + st->indio_dev, + 0, + IRQF_TRIGGER_RISING, + "adis16251"); + if (ret) + goto error_uninitialize_ring; + + ret = adis16251_probe_trigger(st->indio_dev); + if (ret) + goto error_unregister_line; + } + + /* Get the device into a sane initial state */ + ret = adis16251_initial_setup(st); + if (ret) + goto error_remove_trigger; + return 0; + +error_remove_trigger: + if (st->indio_dev->modes & INDIO_RING_TRIGGERED) + adis16251_remove_trigger(st->indio_dev); +error_unregister_line: + if (st->indio_dev->modes & INDIO_RING_TRIGGERED) + iio_unregister_interrupt_line(st->indio_dev, 0); +error_uninitialize_ring: + adis16251_uninitialize_ring(st->indio_dev->ring); +error_unreg_ring_funcs: + adis16251_unconfigure_ring(st->indio_dev); +error_free_dev: + if (regdone) + iio_device_unregister(st->indio_dev); + else + iio_free_device(st->indio_dev); +error_free_tx: + kfree(st->tx); +error_free_rx: + kfree(st->rx); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +/* fixme, confirm ordering in this function */ +static int adis16251_remove(struct spi_device *spi) +{ + int ret; + struct adis16251_state *st = spi_get_drvdata(spi); + struct iio_dev *indio_dev = st->indio_dev; + + ret = adis16251_stop_device(&(indio_dev->dev)); + if (ret) + goto err_ret; + + flush_scheduled_work(); + + adis16251_remove_trigger(indio_dev); + if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) + iio_unregister_interrupt_line(indio_dev, 0); + + adis16251_uninitialize_ring(indio_dev->ring); + adis16251_unconfigure_ring(indio_dev); + iio_device_unregister(indio_dev); + kfree(st->tx); + kfree(st->rx); + kfree(st); + + return 0; + +err_ret: + return ret; +} + +static struct spi_driver adis16251_driver = { + .driver = { + .name = "adis16251", + .owner = THIS_MODULE, + }, + .probe = adis16251_probe, + .remove = __devexit_p(adis16251_remove), +}; + +static __init int adis16251_init(void) +{ + return spi_register_driver(&adis16251_driver); +} +module_init(adis16251_init); + +static __exit void adis16251_exit(void) +{ + spi_unregister_driver(&adis16251_driver); +} +module_exit(adis16251_exit); + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices ADIS16251 Digital Gyroscope Sensor SPI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/gyro/adis16260_core.c b/trunk/drivers/staging/iio/gyro/adis16260_core.c index 7d7716e5857c..8190c0fe0bea 100644 --- a/trunk/drivers/staging/iio/gyro/adis16260_core.c +++ b/trunk/drivers/staging/iio/gyro/adis16260_core.c @@ -1,5 +1,5 @@ /* - * ADIS16260 Programmable Digital Gyroscope Sensor Driver + * ADIS16260/ADIS16265 Programmable Digital Gyroscope Sensor Driver * * Copyright 2010 Analog Devices Inc. * diff --git a/trunk/drivers/staging/iio/imu/adis16350_core.c b/trunk/drivers/staging/iio/imu/adis16350_core.c index 97c1ec8594ce..cf7176bc766b 100644 --- a/trunk/drivers/staging/iio/imu/adis16350_core.c +++ b/trunk/drivers/staging/iio/imu/adis16350_core.c @@ -570,6 +570,7 @@ static struct attribute *adis16350_attributes[] = { &iio_dev_attr_temp_y_raw.dev_attr.attr, &iio_dev_attr_temp_z_raw.dev_attr.attr, &iio_const_attr_temp_scale.dev_attr.attr, + &iio_const_attr_temp_offset.dev_attr.attr, &iio_dev_attr_in1_raw.dev_attr.attr, &iio_const_attr_in1_scale.dev_attr.attr, &iio_dev_attr_sampling_frequency.dev_attr.attr, diff --git a/trunk/drivers/staging/iio/meter/Kconfig b/trunk/drivers/staging/iio/meter/Kconfig new file mode 100644 index 000000000000..12e36e460693 --- /dev/null +++ b/trunk/drivers/staging/iio/meter/Kconfig @@ -0,0 +1,61 @@ +# +# IIO meter drivers configuration +# +comment "Active energy metering IC" + +config ADE7753 + tristate "Analog Devices ADE7753/6 Single-Phase Multifunction Metering IC Driver" + depends on SPI + help + Say yes here to build support for Analog Devices ADE7753 Single-Phase Multifunction + Metering IC with di/dt Sensor Interface. + +config ADE7754 + tristate "Analog Devices ADE7754 Polyphase Multifunction Energy Metering IC Driver" + depends on SPI + help + Say yes here to build support for Analog Devices ADE7754 Polyphase + Multifunction Energy Metering IC Driver. + +config ADE7758 + tristate "Analog Devices ADE7758 Poly Phase Multifunction Energy Metering IC Driver" + depends on SPI + select IIO_TRIGGER if IIO_RING_BUFFER + select IIO_SW_RING if IIO_RING_BUFFER + help + Say yes here to build support for Analog Devices ADE7758 Polyphase + Multifunction Energy Metering IC with Per Phase Information Driver. + +config ADE7759 + tristate "Analog Devices ADE7759 Active Energy Metering IC Driver" + depends on SPI + help + Say yes here to build support for Analog Devices ADE7758 Active Energy + Metering IC with di/dt Sensor Interface. + +config ADE7854 + tristate "Analog Devices ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC Driver" + depends on SPI || I2C + help + Say yes here to build support for Analog Devices ADE7854/58/68/78 Polyphase + Multifunction Energy Metering IC Driver. + +config ADE7854_I2C + tristate "support I2C bus connection" + depends on ADE7854 && I2C + default y + help + Say Y here if you have ADE7854/58/68/78 hooked to an I2C bus. + + To compile this driver as a module, choose M here: the + module will be called ade7854-i2c. + +config ADE7854_SPI + tristate "support SPI bus connection" + depends on ADE7854 && SPI + default y + help + Say Y here if you have ADE7854/58/68/78 hooked to a SPI bus. + + To compile this driver as a module, choose M here: the + module will be called ade7854-spi. diff --git a/trunk/drivers/staging/iio/meter/Makefile b/trunk/drivers/staging/iio/meter/Makefile new file mode 100644 index 000000000000..0cc7d5140dfe --- /dev/null +++ b/trunk/drivers/staging/iio/meter/Makefile @@ -0,0 +1,15 @@ +# +# Makefile for metering ic drivers +# + +obj-$(CONFIG_ADE7753) += ade7753.o +obj-$(CONFIG_ADE7754) += ade7754.o + +ade7758-y := ade7758_core.o +ade7758-$(CONFIG_IIO_RING_BUFFER) += ade7758_ring.o ade7758_trigger.o +obj-$(CONFIG_ADE7758) += ade7758.o + +obj-$(CONFIG_ADE7759) += ade7759.o +obj-$(CONFIG_ADE7854) += ade7854.o +obj-$(CONFIG_ADE7854_I2C) += ade7854-i2c.o +obj-$(CONFIG_ADE7854_SPI) += ade7854-spi.o diff --git a/trunk/drivers/staging/iio/meter/ade7753.c b/trunk/drivers/staging/iio/meter/ade7753.c new file mode 100644 index 000000000000..e72afbd2b841 --- /dev/null +++ b/trunk/drivers/staging/iio/meter/ade7753.c @@ -0,0 +1,730 @@ +/* + * ADE7753 Single-Phase Multifunction Metering IC with di/dt Sensor Interface Driver + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "meter.h" +#include "ade7753.h" + +int ade7753_spi_write_reg_8(struct device *dev, + u8 reg_address, + u8 val) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7753_state *st = iio_dev_get_devdata(indio_dev); + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7753_WRITE_REG(reg_address); + st->tx[1] = val; + + ret = spi_write(st->us, st->tx, 2); + mutex_unlock(&st->buf_lock); + + return ret; +} + +static int ade7753_spi_write_reg_16(struct device *dev, + u8 reg_address, + u16 value) +{ + int ret; + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7753_state *st = iio_dev_get_devdata(indio_dev); + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 3, + } + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7753_WRITE_REG(reg_address); + st->tx[1] = (value >> 8) & 0xFF; + st->tx[2] = value & 0xFF; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->us, &msg); + mutex_unlock(&st->buf_lock); + + return ret; +} + +static int ade7753_spi_read_reg_8(struct device *dev, + u8 reg_address, + u8 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7753_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 2, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7753_READ_REG(reg_address); + st->tx[1] = 0; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X", + reg_address); + goto error_ret; + } + *val = st->rx[1]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static int ade7753_spi_read_reg_16(struct device *dev, + u8 reg_address, + u16 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7753_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 3, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7753_READ_REG(reg_address); + st->tx[1] = 0; + st->tx[2] = 0; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", + reg_address); + goto error_ret; + } + *val = (st->rx[1] << 8) | st->rx[2]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static int ade7753_spi_read_reg_24(struct device *dev, + u8 reg_address, + u32 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7753_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 4, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7753_READ_REG(reg_address); + st->tx[1] = 0; + st->tx[2] = 0; + st->tx[3] = 0; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X", + reg_address); + goto error_ret; + } + *val = (st->rx[1] << 16) | (st->rx[2] << 8) | st->rx[3]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static ssize_t ade7753_read_8bit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u8 val = 0; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = ade7753_spi_read_reg_8(dev, this_attr->address, &val); + if (ret) + return ret; + + return sprintf(buf, "%u\n", val); +} + +static ssize_t ade7753_read_16bit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u16 val = 0; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = ade7753_spi_read_reg_16(dev, this_attr->address, &val); + if (ret) + return ret; + + return sprintf(buf, "%u\n", val); +} + +static ssize_t ade7753_read_24bit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u32 val = 0; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = ade7753_spi_read_reg_24(dev, this_attr->address, &val); + if (ret) + return ret; + + return sprintf(buf, "%u\n", val & 0xFFFFFF); +} + +static ssize_t ade7753_write_8bit(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + long val; + + ret = strict_strtol(buf, 10, &val); + if (ret) + goto error_ret; + ret = ade7753_spi_write_reg_8(dev, this_attr->address, val); + +error_ret: + return ret ? ret : len; +} + +static ssize_t ade7753_write_16bit(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + long val; + + ret = strict_strtol(buf, 10, &val); + if (ret) + goto error_ret; + ret = ade7753_spi_write_reg_16(dev, this_attr->address, val); + +error_ret: + return ret ? ret : len; +} + +static int ade7753_reset(struct device *dev) +{ + int ret; + u16 val; + ade7753_spi_read_reg_16(dev, + ADE7753_MODE, + &val); + val |= 1 << 6; /* Software Chip Reset */ + ret = ade7753_spi_write_reg_16(dev, + ADE7753_MODE, + val); + + return ret; +} + +static ssize_t ade7753_write_reset(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + if (len < 1) + return -1; + switch (buf[0]) { + case '1': + case 'y': + case 'Y': + return ade7753_reset(dev); + } + return -1; +} + +static IIO_DEV_ATTR_AENERGY(ade7753_read_24bit, ADE7753_AENERGY); +static IIO_DEV_ATTR_LAENERGY(ade7753_read_24bit, ADE7753_LAENERGY); +static IIO_DEV_ATTR_VAENERGY(ade7753_read_24bit, ADE7753_VAENERGY); +static IIO_DEV_ATTR_LVAENERGY(ade7753_read_24bit, ADE7753_LVAENERGY); +static IIO_DEV_ATTR_CFDEN(S_IWUSR | S_IRUGO, + ade7753_read_16bit, + ade7753_write_16bit, + ADE7753_CFDEN); +static IIO_DEV_ATTR_CFNUM(S_IWUSR | S_IRUGO, + ade7753_read_8bit, + ade7753_write_8bit, + ADE7753_CFNUM); +static IIO_DEV_ATTR_CHKSUM(ade7753_read_8bit, ADE7753_CHKSUM); +static IIO_DEV_ATTR_PHCAL(S_IWUSR | S_IRUGO, + ade7753_read_16bit, + ade7753_write_16bit, + ADE7753_PHCAL); +static IIO_DEV_ATTR_APOS(S_IWUSR | S_IRUGO, + ade7753_read_16bit, + ade7753_write_16bit, + ADE7753_APOS); +static IIO_DEV_ATTR_SAGCYC(S_IWUSR | S_IRUGO, + ade7753_read_8bit, + ade7753_write_8bit, + ADE7753_SAGCYC); +static IIO_DEV_ATTR_SAGLVL(S_IWUSR | S_IRUGO, + ade7753_read_8bit, + ade7753_write_8bit, + ADE7753_SAGLVL); +static IIO_DEV_ATTR_LINECYC(S_IWUSR | S_IRUGO, + ade7753_read_8bit, + ade7753_write_8bit, + ADE7753_LINECYC); +static IIO_DEV_ATTR_WDIV(S_IWUSR | S_IRUGO, + ade7753_read_8bit, + ade7753_write_8bit, + ADE7753_WDIV); +static IIO_DEV_ATTR_IRMS(S_IWUSR | S_IRUGO, + ade7753_read_24bit, + NULL, + ADE7753_IRMS); +static IIO_DEV_ATTR_VRMS(S_IRUGO, + ade7753_read_24bit, + NULL, + ADE7753_VRMS); +static IIO_DEV_ATTR_IRMSOS(S_IWUSR | S_IRUGO, + ade7753_read_16bit, + ade7753_write_16bit, + ADE7753_IRMSOS); +static IIO_DEV_ATTR_VRMSOS(S_IWUSR | S_IRUGO, + ade7753_read_16bit, + ade7753_write_16bit, + ADE7753_VRMSOS); +static IIO_DEV_ATTR_WGAIN(S_IWUSR | S_IRUGO, + ade7753_read_16bit, + ade7753_write_16bit, + ADE7753_WGAIN); +static IIO_DEV_ATTR_VAGAIN(S_IWUSR | S_IRUGO, + ade7753_read_16bit, + ade7753_write_16bit, + ADE7753_VAGAIN); +static IIO_DEV_ATTR_PGA_GAIN(S_IWUSR | S_IRUGO, + ade7753_read_16bit, + ade7753_write_16bit, + ADE7753_GAIN); +static IIO_DEV_ATTR_IPKLVL(S_IWUSR | S_IRUGO, + ade7753_read_8bit, + ade7753_write_8bit, + ADE7753_IPKLVL); +static IIO_DEV_ATTR_VPKLVL(S_IWUSR | S_IRUGO, + ade7753_read_8bit, + ade7753_write_8bit, + ADE7753_VPKLVL); +static IIO_DEV_ATTR_IPEAK(S_IRUGO, + ade7753_read_24bit, + NULL, + ADE7753_IPEAK); +static IIO_DEV_ATTR_VPEAK(S_IRUGO, + ade7753_read_24bit, + NULL, + ADE7753_VPEAK); +static IIO_DEV_ATTR_VPERIOD(S_IRUGO, + ade7753_read_16bit, + NULL, + ADE7753_PERIOD); +static IIO_DEV_ATTR_CH_OFF(1, S_IWUSR | S_IRUGO, + ade7753_read_8bit, + ade7753_write_8bit, + ADE7753_CH1OS); +static IIO_DEV_ATTR_CH_OFF(2, S_IWUSR | S_IRUGO, + ade7753_read_8bit, + ade7753_write_8bit, + ADE7753_CH2OS); + +static int ade7753_set_irq(struct device *dev, bool enable) +{ + int ret; + u8 irqen; + ret = ade7753_spi_read_reg_8(dev, ADE7753_IRQEN, &irqen); + if (ret) + goto error_ret; + + if (enable) + irqen |= 1 << 3; /* Enables an interrupt when a data is + present in the waveform register */ + else + irqen &= ~(1 << 3); + + ret = ade7753_spi_write_reg_8(dev, ADE7753_IRQEN, irqen); + if (ret) + goto error_ret; + +error_ret: + return ret; +} + +/* Power down the device */ +int ade7753_stop_device(struct device *dev) +{ + int ret; + u16 val; + ade7753_spi_read_reg_16(dev, + ADE7753_MODE, + &val); + val |= 1 << 4; /* AD converters can be turned off */ + ret = ade7753_spi_write_reg_16(dev, + ADE7753_MODE, + val); + + return ret; +} + +static int ade7753_initial_setup(struct ade7753_state *st) +{ + int ret; + struct device *dev = &st->indio_dev->dev; + + /* use low spi speed for init */ + st->us->mode = SPI_MODE_3; + spi_setup(st->us); + + /* Disable IRQ */ + ret = ade7753_set_irq(dev, false); + if (ret) { + dev_err(dev, "disable irq failed"); + goto err_ret; + } + + ade7753_reset(dev); + msleep(ADE7753_STARTUP_DELAY); + +err_ret: + return ret; +} + +static ssize_t ade7753_read_frequency(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret, len = 0; + u8 t; + int sps; + ret = ade7753_spi_read_reg_8(dev, + ADE7753_MODE, + &t); + if (ret) + return ret; + + t = (t >> 11) & 0x3; + sps = 27900 / (1 + t); + + len = sprintf(buf, "%d SPS\n", sps); + return len; +} + +static ssize_t ade7753_write_frequency(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7753_state *st = iio_dev_get_devdata(indio_dev); + unsigned long val; + int ret; + u16 reg, t; + + ret = strict_strtol(buf, 10, &val); + if (ret) + return ret; + + mutex_lock(&indio_dev->mlock); + + t = (27900 / val); + if (t > 0) + t--; + + if (t > 1) + st->us->max_speed_hz = ADE7753_SPI_SLOW; + else + st->us->max_speed_hz = ADE7753_SPI_FAST; + + ret = ade7753_spi_read_reg_16(dev, + ADE7753_MODE, + ®); + if (ret) + goto out; + + reg &= ~(3 << 11); + reg |= t << 11; + + ret = ade7753_spi_write_reg_16(dev, + ADE7753_MODE, + reg); + +out: + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} +static IIO_DEV_ATTR_TEMP_RAW(ade7753_read_8bit); +static IIO_CONST_ATTR(temp_offset, "-25 C"); +static IIO_CONST_ATTR(temp_scale, "0.67 C"); + +static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, + ade7753_read_frequency, + ade7753_write_frequency); + +static IIO_DEV_ATTR_RESET(ade7753_write_reset); + +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("27900 14000 7000 3500"); + +static IIO_CONST_ATTR(name, "ade7753"); + +static struct attribute *ade7753_event_attributes[] = { + NULL +}; + +static struct attribute_group ade7753_event_attribute_group = { + .attrs = ade7753_event_attributes, +}; + +static struct attribute *ade7753_attributes[] = { + &iio_dev_attr_temp_raw.dev_attr.attr, + &iio_const_attr_temp_offset.dev_attr.attr, + &iio_const_attr_temp_scale.dev_attr.attr, + &iio_dev_attr_sampling_frequency.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + &iio_dev_attr_reset.dev_attr.attr, + &iio_const_attr_name.dev_attr.attr, + &iio_dev_attr_phcal.dev_attr.attr, + &iio_dev_attr_cfden.dev_attr.attr, + &iio_dev_attr_aenergy.dev_attr.attr, + &iio_dev_attr_laenergy.dev_attr.attr, + &iio_dev_attr_vaenergy.dev_attr.attr, + &iio_dev_attr_lvaenergy.dev_attr.attr, + &iio_dev_attr_cfnum.dev_attr.attr, + &iio_dev_attr_apos.dev_attr.attr, + &iio_dev_attr_sagcyc.dev_attr.attr, + &iio_dev_attr_saglvl.dev_attr.attr, + &iio_dev_attr_linecyc.dev_attr.attr, + &iio_dev_attr_chksum.dev_attr.attr, + &iio_dev_attr_pga_gain.dev_attr.attr, + &iio_dev_attr_wgain.dev_attr.attr, + &iio_dev_attr_choff_1.dev_attr.attr, + &iio_dev_attr_choff_2.dev_attr.attr, + &iio_dev_attr_wdiv.dev_attr.attr, + &iio_dev_attr_irms.dev_attr.attr, + &iio_dev_attr_vrms.dev_attr.attr, + &iio_dev_attr_irmsos.dev_attr.attr, + &iio_dev_attr_vrmsos.dev_attr.attr, + &iio_dev_attr_vagain.dev_attr.attr, + &iio_dev_attr_ipklvl.dev_attr.attr, + &iio_dev_attr_vpklvl.dev_attr.attr, + &iio_dev_attr_ipeak.dev_attr.attr, + &iio_dev_attr_vpeak.dev_attr.attr, + &iio_dev_attr_vperiod.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ade7753_attribute_group = { + .attrs = ade7753_attributes, +}; + +static int __devinit ade7753_probe(struct spi_device *spi) +{ + int ret, regdone = 0; + struct ade7753_state *st = kzalloc(sizeof *st, GFP_KERNEL); + if (!st) { + ret = -ENOMEM; + goto error_ret; + } + /* this is only used for removal purposes */ + spi_set_drvdata(spi, st); + + /* Allocate the comms buffers */ + st->rx = kzalloc(sizeof(*st->rx)*ADE7753_MAX_RX, GFP_KERNEL); + if (st->rx == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->tx = kzalloc(sizeof(*st->tx)*ADE7753_MAX_TX, GFP_KERNEL); + if (st->tx == NULL) { + ret = -ENOMEM; + goto error_free_rx; + } + st->us = spi; + mutex_init(&st->buf_lock); + /* setup the industrialio driver allocated elements */ + st->indio_dev = iio_allocate_device(); + if (st->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_tx; + } + + st->indio_dev->dev.parent = &spi->dev; + st->indio_dev->num_interrupt_lines = 1; + st->indio_dev->event_attrs = &ade7753_event_attribute_group; + st->indio_dev->attrs = &ade7753_attribute_group; + st->indio_dev->dev_data = (void *)(st); + st->indio_dev->driver_module = THIS_MODULE; + st->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = ade7753_configure_ring(st->indio_dev); + if (ret) + goto error_free_dev; + + ret = iio_device_register(st->indio_dev); + if (ret) + goto error_unreg_ring_funcs; + regdone = 1; + + ret = ade7753_initialize_ring(st->indio_dev->ring); + if (ret) { + printk(KERN_ERR "failed to initialize the ring\n"); + goto error_unreg_ring_funcs; + } + + if (spi->irq) { + ret = iio_register_interrupt_line(spi->irq, + st->indio_dev, + 0, + IRQF_TRIGGER_FALLING, + "ade7753"); + if (ret) + goto error_uninitialize_ring; + + ret = ade7753_probe_trigger(st->indio_dev); + if (ret) + goto error_unregister_line; + } + + /* Get the device into a sane initial state */ + ret = ade7753_initial_setup(st); + if (ret) + goto error_remove_trigger; + return 0; + +error_remove_trigger: + if (st->indio_dev->modes & INDIO_RING_TRIGGERED) + ade7753_remove_trigger(st->indio_dev); +error_unregister_line: + if (st->indio_dev->modes & INDIO_RING_TRIGGERED) + iio_unregister_interrupt_line(st->indio_dev, 0); +error_uninitialize_ring: + ade7753_uninitialize_ring(st->indio_dev->ring); +error_unreg_ring_funcs: + ade7753_unconfigure_ring(st->indio_dev); +error_free_dev: + if (regdone) + iio_device_unregister(st->indio_dev); + else + iio_free_device(st->indio_dev); +error_free_tx: + kfree(st->tx); +error_free_rx: + kfree(st->rx); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +/* fixme, confirm ordering in this function */ +static int ade7753_remove(struct spi_device *spi) +{ + int ret; + struct ade7753_state *st = spi_get_drvdata(spi); + struct iio_dev *indio_dev = st->indio_dev; + + ret = ade7753_stop_device(&(indio_dev->dev)); + if (ret) + goto err_ret; + + flush_scheduled_work(); + + ade7753_remove_trigger(indio_dev); + if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) + iio_unregister_interrupt_line(indio_dev, 0); + + ade7753_uninitialize_ring(indio_dev->ring); + ade7753_unconfigure_ring(indio_dev); + iio_device_unregister(indio_dev); + kfree(st->tx); + kfree(st->rx); + kfree(st); + + return 0; + +err_ret: + return ret; +} + +static struct spi_driver ade7753_driver = { + .driver = { + .name = "ade7753", + .owner = THIS_MODULE, + }, + .probe = ade7753_probe, + .remove = __devexit_p(ade7753_remove), +}; + +static __init int ade7753_init(void) +{ + return spi_register_driver(&ade7753_driver); +} +module_init(ade7753_init); + +static __exit void ade7753_exit(void) +{ + spi_unregister_driver(&ade7753_driver); +} +module_exit(ade7753_exit); + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices ADE7753/6 Single-Phase Multifunction Metering IC Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/meter/ade7753.h b/trunk/drivers/staging/iio/meter/ade7753.h new file mode 100644 index 000000000000..a3722b8c90fa --- /dev/null +++ b/trunk/drivers/staging/iio/meter/ade7753.h @@ -0,0 +1,140 @@ +#ifndef _ADE7753_H +#define _ADE7753_H + +#define ADE7753_WAVEFORM 0x01 +#define ADE7753_AENERGY 0x02 +#define ADE7753_RAENERGY 0x03 +#define ADE7753_LAENERGY 0x04 +#define ADE7753_VAENERGY 0x05 +#define ADE7753_RVAENERGY 0x06 +#define ADE7753_LVAENERGY 0x07 +#define ADE7753_LVARENERGY 0x08 +#define ADE7753_MODE 0x09 +#define ADE7753_IRQEN 0x0A +#define ADE7753_STATUS 0x0B +#define ADE7753_RSTSTATUS 0x0C +#define ADE7753_CH1OS 0x0D +#define ADE7753_CH2OS 0x0E +#define ADE7753_GAIN 0x0F +#define ADE7753_PHCAL 0x10 +#define ADE7753_APOS 0x11 +#define ADE7753_WGAIN 0x12 +#define ADE7753_WDIV 0x13 +#define ADE7753_CFNUM 0x14 +#define ADE7753_CFDEN 0x15 +#define ADE7753_IRMS 0x16 +#define ADE7753_VRMS 0x17 +#define ADE7753_IRMSOS 0x18 +#define ADE7753_VRMSOS 0x19 +#define ADE7753_VAGAIN 0x1A +#define ADE7753_VADIV 0x1B +#define ADE7753_LINECYC 0x1C +#define ADE7753_ZXTOUT 0x1D +#define ADE7753_SAGCYC 0x1E +#define ADE7753_SAGLVL 0x1F +#define ADE7753_IPKLVL 0x20 +#define ADE7753_VPKLVL 0x21 +#define ADE7753_IPEAK 0x22 +#define ADE7753_RSTIPEAK 0x23 +#define ADE7753_VPEAK 0x24 +#define ADE7753_RSTVPEAK 0x25 +#define ADE7753_TEMP 0x26 +#define ADE7753_PERIOD 0x27 +#define ADE7753_TMODE 0x3D +#define ADE7753_CHKSUM 0x3E +#define ADE7753_DIEREV 0x3F + +#define ADE7753_READ_REG(a) a +#define ADE7753_WRITE_REG(a) ((a) | 0x80) + +#define ADE7753_MAX_TX 4 +#define ADE7753_MAX_RX 4 +#define ADE7753_STARTUP_DELAY 1 + +#define ADE7753_SPI_SLOW (u32)(300 * 1000) +#define ADE7753_SPI_BURST (u32)(1000 * 1000) +#define ADE7753_SPI_FAST (u32)(2000 * 1000) + +#define DRIVER_NAME "ade7753" + +/** + * struct ade7753_state - device instance specific data + * @us: actual spi_device + * @work_trigger_to_ring: bh for triggered event handling + * @inter: used to check if new interrupt has been triggered + * @last_timestamp: passing timestamp from th to bh of interrupt handler + * @indio_dev: industrial I/O device structure + * @trig: data ready trigger registered with iio + * @tx: transmit buffer + * @rx: recieve buffer + * @buf_lock: mutex to protect tx and rx + **/ +struct ade7753_state { + struct spi_device *us; + struct work_struct work_trigger_to_ring; + s64 last_timestamp; + struct iio_dev *indio_dev; + struct iio_trigger *trig; + u8 *tx; + u8 *rx; + struct mutex buf_lock; +}; +#if defined(CONFIG_IIO_RING_BUFFER) && defined(THIS_HAS_RING_BUFFER_SUPPORT) +/* At the moment triggers are only used for ring buffer + * filling. This may change! + */ + +enum ade7753_scan { + ADE7753_SCAN_ACTIVE_POWER, + ADE7753_SCAN_CH1, + ADE7753_SCAN_CH2, +}; + +void ade7753_remove_trigger(struct iio_dev *indio_dev); +int ade7753_probe_trigger(struct iio_dev *indio_dev); + +ssize_t ade7753_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf); + + +int ade7753_configure_ring(struct iio_dev *indio_dev); +void ade7753_unconfigure_ring(struct iio_dev *indio_dev); + +int ade7753_initialize_ring(struct iio_ring_buffer *ring); +void ade7753_uninitialize_ring(struct iio_ring_buffer *ring); +#else /* CONFIG_IIO_RING_BUFFER */ + +static inline void ade7753_remove_trigger(struct iio_dev *indio_dev) +{ +} +static inline int ade7753_probe_trigger(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline ssize_t +ade7753_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return 0; +} + +static int ade7753_configure_ring(struct iio_dev *indio_dev) +{ + return 0; +} +static inline void ade7753_unconfigure_ring(struct iio_dev *indio_dev) +{ +} +static inline int ade7753_initialize_ring(struct iio_ring_buffer *ring) +{ + return 0; +} +static inline void ade7753_uninitialize_ring(struct iio_ring_buffer *ring) +{ +} +#endif /* CONFIG_IIO_RING_BUFFER */ + +#endif diff --git a/trunk/drivers/staging/iio/meter/ade7754.c b/trunk/drivers/staging/iio/meter/ade7754.c new file mode 100644 index 000000000000..23dedfa7a270 --- /dev/null +++ b/trunk/drivers/staging/iio/meter/ade7754.c @@ -0,0 +1,756 @@ +/* + * ADE7754 Polyphase Multifunction Energy Metering IC Driver + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "meter.h" +#include "ade7754.h" + +static int ade7754_spi_write_reg_8(struct device *dev, + u8 reg_address, + u8 val) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7754_state *st = iio_dev_get_devdata(indio_dev); + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7754_WRITE_REG(reg_address); + st->tx[1] = val; + + ret = spi_write(st->us, st->tx, 2); + mutex_unlock(&st->buf_lock); + + return ret; +} + +static int ade7754_spi_write_reg_16(struct device *dev, + u8 reg_address, + u16 value) +{ + int ret; + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7754_state *st = iio_dev_get_devdata(indio_dev); + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 3, + } + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7754_WRITE_REG(reg_address); + st->tx[1] = (value >> 8) & 0xFF; + st->tx[2] = value & 0xFF; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->us, &msg); + mutex_unlock(&st->buf_lock); + + return ret; +} + +static int ade7754_spi_read_reg_8(struct device *dev, + u8 reg_address, + u8 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7754_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 2, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7754_READ_REG(reg_address); + st->tx[1] = 0; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X", + reg_address); + goto error_ret; + } + *val = st->rx[1]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static int ade7754_spi_read_reg_16(struct device *dev, + u8 reg_address, + u16 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7754_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 3, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7754_READ_REG(reg_address); + st->tx[1] = 0; + st->tx[2] = 0; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", + reg_address); + goto error_ret; + } + *val = (st->rx[1] << 8) | st->rx[2]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static int ade7754_spi_read_reg_24(struct device *dev, + u8 reg_address, + u32 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7754_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 4, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7754_READ_REG(reg_address); + st->tx[1] = 0; + st->tx[2] = 0; + st->tx[3] = 0; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X", + reg_address); + goto error_ret; + } + *val = (st->rx[1] << 16) | (st->rx[2] << 8) | st->rx[3]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static ssize_t ade7754_read_8bit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u8 val = 0; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = ade7754_spi_read_reg_8(dev, this_attr->address, &val); + if (ret) + return ret; + + return sprintf(buf, "%u\n", val); +} + +static ssize_t ade7754_read_16bit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u16 val = 0; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = ade7754_spi_read_reg_16(dev, this_attr->address, &val); + if (ret) + return ret; + + return sprintf(buf, "%u\n", val); +} + +static ssize_t ade7754_read_24bit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u32 val = 0; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = ade7754_spi_read_reg_24(dev, this_attr->address, &val); + if (ret) + return ret; + + return sprintf(buf, "%u\n", val & 0xFFFFFF); +} + +static ssize_t ade7754_write_8bit(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + long val; + + ret = strict_strtol(buf, 10, &val); + if (ret) + goto error_ret; + ret = ade7754_spi_write_reg_8(dev, this_attr->address, val); + +error_ret: + return ret ? ret : len; +} + +static ssize_t ade7754_write_16bit(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + long val; + + ret = strict_strtol(buf, 10, &val); + if (ret) + goto error_ret; + ret = ade7754_spi_write_reg_16(dev, this_attr->address, val); + +error_ret: + return ret ? ret : len; +} + +static int ade7754_reset(struct device *dev) +{ + int ret; + u8 val; + ade7754_spi_read_reg_8(dev, + ADE7754_OPMODE, + &val); + val |= 1 << 6; /* Software Chip Reset */ + ret = ade7754_spi_write_reg_8(dev, + ADE7754_OPMODE, + val); + + return ret; +} + + +static ssize_t ade7754_write_reset(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + if (len < 1) + return -1; + switch (buf[0]) { + case '1': + case 'y': + case 'Y': + return ade7754_reset(dev); + } + return -1; +} + +static IIO_DEV_ATTR_AENERGY(ade7754_read_24bit, ADE7754_AENERGY); +static IIO_DEV_ATTR_LAENERGY(ade7754_read_24bit, ADE7754_LAENERGY); +static IIO_DEV_ATTR_VAENERGY(ade7754_read_24bit, ADE7754_VAENERGY); +static IIO_DEV_ATTR_LVAENERGY(ade7754_read_24bit, ADE7754_LVAENERGY); +static IIO_DEV_ATTR_VPEAK(S_IWUSR | S_IRUGO, + ade7754_read_8bit, + ade7754_write_8bit, + ADE7754_VPEAK); +static IIO_DEV_ATTR_IPEAK(S_IWUSR | S_IRUGO, + ade7754_read_8bit, + ade7754_write_8bit, + ADE7754_VPEAK); +static IIO_DEV_ATTR_APHCAL(S_IWUSR | S_IRUGO, + ade7754_read_8bit, + ade7754_write_8bit, + ADE7754_APHCAL); +static IIO_DEV_ATTR_BPHCAL(S_IWUSR | S_IRUGO, + ade7754_read_8bit, + ade7754_write_8bit, + ADE7754_BPHCAL); +static IIO_DEV_ATTR_CPHCAL(S_IWUSR | S_IRUGO, + ade7754_read_8bit, + ade7754_write_8bit, + ADE7754_CPHCAL); +static IIO_DEV_ATTR_AAPOS(S_IWUSR | S_IRUGO, + ade7754_read_16bit, + ade7754_write_16bit, + ADE7754_AAPOS); +static IIO_DEV_ATTR_BAPOS(S_IWUSR | S_IRUGO, + ade7754_read_16bit, + ade7754_write_16bit, + ADE7754_BAPOS); +static IIO_DEV_ATTR_CAPOS(S_IWUSR | S_IRUGO, + ade7754_read_16bit, + ade7754_write_16bit, + ADE7754_CAPOS); +static IIO_DEV_ATTR_WDIV(S_IWUSR | S_IRUGO, + ade7754_read_8bit, + ade7754_write_8bit, + ADE7754_WDIV); +static IIO_DEV_ATTR_VADIV(S_IWUSR | S_IRUGO, + ade7754_read_8bit, + ade7754_write_8bit, + ADE7754_VADIV); +static IIO_DEV_ATTR_CFNUM(S_IWUSR | S_IRUGO, + ade7754_read_16bit, + ade7754_write_16bit, + ADE7754_CFNUM); +static IIO_DEV_ATTR_CFDEN(S_IWUSR | S_IRUGO, + ade7754_read_16bit, + ade7754_write_16bit, + ADE7754_CFDEN); +static IIO_DEV_ATTR_ACTIVE_POWER_A_GAIN(S_IWUSR | S_IRUGO, + ade7754_read_16bit, + ade7754_write_16bit, + ADE7754_AAPGAIN); +static IIO_DEV_ATTR_ACTIVE_POWER_B_GAIN(S_IWUSR | S_IRUGO, + ade7754_read_16bit, + ade7754_write_16bit, + ADE7754_BAPGAIN); +static IIO_DEV_ATTR_ACTIVE_POWER_C_GAIN(S_IWUSR | S_IRUGO, + ade7754_read_16bit, + ade7754_write_16bit, + ADE7754_CAPGAIN); +static IIO_DEV_ATTR_AIRMS(S_IRUGO, + ade7754_read_24bit, + NULL, + ADE7754_AIRMS); +static IIO_DEV_ATTR_BIRMS(S_IRUGO, + ade7754_read_24bit, + NULL, + ADE7754_BIRMS); +static IIO_DEV_ATTR_CIRMS(S_IRUGO, + ade7754_read_24bit, + NULL, + ADE7754_CIRMS); +static IIO_DEV_ATTR_AVRMS(S_IRUGO, + ade7754_read_24bit, + NULL, + ADE7754_AVRMS); +static IIO_DEV_ATTR_BVRMS(S_IRUGO, + ade7754_read_24bit, + NULL, + ADE7754_BVRMS); +static IIO_DEV_ATTR_CVRMS(S_IRUGO, + ade7754_read_24bit, + NULL, + ADE7754_CVRMS); +static IIO_DEV_ATTR_AIRMSOS(S_IRUGO, + ade7754_read_16bit, + ade7754_write_16bit, + ADE7754_AIRMSOS); +static IIO_DEV_ATTR_BIRMSOS(S_IRUGO, + ade7754_read_16bit, + ade7754_write_16bit, + ADE7754_BIRMSOS); +static IIO_DEV_ATTR_CIRMSOS(S_IRUGO, + ade7754_read_16bit, + ade7754_write_16bit, + ADE7754_CIRMSOS); +static IIO_DEV_ATTR_AVRMSOS(S_IRUGO, + ade7754_read_16bit, + ade7754_write_16bit, + ADE7754_AVRMSOS); +static IIO_DEV_ATTR_BVRMSOS(S_IRUGO, + ade7754_read_16bit, + ade7754_write_16bit, + ADE7754_BVRMSOS); +static IIO_DEV_ATTR_CVRMSOS(S_IRUGO, + ade7754_read_16bit, + ade7754_write_16bit, + ADE7754_CVRMSOS); + +static int ade7754_set_irq(struct device *dev, bool enable) +{ + int ret; + u16 irqen; + ret = ade7754_spi_read_reg_16(dev, ADE7754_IRQEN, &irqen); + if (ret) + goto error_ret; + + if (enable) + irqen |= 1 << 14; /* Enables an interrupt when a data is + present in the waveform register */ + else + irqen &= ~(1 << 14); + + ret = ade7754_spi_write_reg_16(dev, ADE7754_IRQEN, irqen); + if (ret) + goto error_ret; + +error_ret: + return ret; +} + +/* Power down the device */ +static int ade7754_stop_device(struct device *dev) +{ + int ret; + u8 val; + ade7754_spi_read_reg_8(dev, + ADE7754_OPMODE, + &val); + val |= 7 << 3; /* ADE7754 powered down */ + ret = ade7754_spi_write_reg_8(dev, + ADE7754_OPMODE, + val); + + return ret; +} + +static int ade7754_initial_setup(struct ade7754_state *st) +{ + int ret; + struct device *dev = &st->indio_dev->dev; + + /* use low spi speed for init */ + st->us->mode = SPI_MODE_3; + spi_setup(st->us); + + /* Disable IRQ */ + ret = ade7754_set_irq(dev, false); + if (ret) { + dev_err(dev, "disable irq failed"); + goto err_ret; + } + + ade7754_reset(dev); + msleep(ADE7754_STARTUP_DELAY); + +err_ret: + return ret; +} + +static ssize_t ade7754_read_frequency(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret, len = 0; + u8 t; + int sps; + ret = ade7754_spi_read_reg_8(dev, + ADE7754_WAVMODE, + &t); + if (ret) + return ret; + + t = (t >> 3) & 0x3; + sps = 26000 / (1 + t); + + len = sprintf(buf, "%d SPS\n", sps); + return len; +} + +static ssize_t ade7754_write_frequency(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7754_state *st = iio_dev_get_devdata(indio_dev); + unsigned long val; + int ret; + u8 reg, t; + + ret = strict_strtol(buf, 10, &val); + if (ret) + return ret; + + mutex_lock(&indio_dev->mlock); + + t = (26000 / val); + if (t > 0) + t--; + + if (t > 1) + st->us->max_speed_hz = ADE7754_SPI_SLOW; + else + st->us->max_speed_hz = ADE7754_SPI_FAST; + + ret = ade7754_spi_read_reg_8(dev, + ADE7754_WAVMODE, + ®); + if (ret) + goto out; + + reg &= ~(3 << 3); + reg |= t << 3; + + ret = ade7754_spi_write_reg_8(dev, + ADE7754_WAVMODE, + reg); + +out: + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} +static IIO_DEV_ATTR_TEMP_RAW(ade7754_read_8bit); +static IIO_CONST_ATTR(temp_offset, "129 C"); +static IIO_CONST_ATTR(temp_scale, "4 C"); + +static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, + ade7754_read_frequency, + ade7754_write_frequency); + +static IIO_DEV_ATTR_RESET(ade7754_write_reset); + +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("26000 13000 65000 33000"); + +static IIO_CONST_ATTR(name, "ade7754"); + +static struct attribute *ade7754_event_attributes[] = { + NULL +}; + +static struct attribute_group ade7754_event_attribute_group = { + .attrs = ade7754_event_attributes, +}; + +static struct attribute *ade7754_attributes[] = { + &iio_dev_attr_temp_raw.dev_attr.attr, + &iio_const_attr_temp_offset.dev_attr.attr, + &iio_const_attr_temp_scale.dev_attr.attr, + &iio_dev_attr_sampling_frequency.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + &iio_dev_attr_reset.dev_attr.attr, + &iio_const_attr_name.dev_attr.attr, + &iio_dev_attr_aenergy.dev_attr.attr, + &iio_dev_attr_laenergy.dev_attr.attr, + &iio_dev_attr_vaenergy.dev_attr.attr, + &iio_dev_attr_lvaenergy.dev_attr.attr, + &iio_dev_attr_vpeak.dev_attr.attr, + &iio_dev_attr_ipeak.dev_attr.attr, + &iio_dev_attr_aphcal.dev_attr.attr, + &iio_dev_attr_bphcal.dev_attr.attr, + &iio_dev_attr_cphcal.dev_attr.attr, + &iio_dev_attr_aapos.dev_attr.attr, + &iio_dev_attr_bapos.dev_attr.attr, + &iio_dev_attr_capos.dev_attr.attr, + &iio_dev_attr_wdiv.dev_attr.attr, + &iio_dev_attr_vadiv.dev_attr.attr, + &iio_dev_attr_cfnum.dev_attr.attr, + &iio_dev_attr_cfden.dev_attr.attr, + &iio_dev_attr_active_power_a_gain.dev_attr.attr, + &iio_dev_attr_active_power_b_gain.dev_attr.attr, + &iio_dev_attr_active_power_c_gain.dev_attr.attr, + &iio_dev_attr_airms.dev_attr.attr, + &iio_dev_attr_birms.dev_attr.attr, + &iio_dev_attr_cirms.dev_attr.attr, + &iio_dev_attr_avrms.dev_attr.attr, + &iio_dev_attr_bvrms.dev_attr.attr, + &iio_dev_attr_cvrms.dev_attr.attr, + &iio_dev_attr_airmsos.dev_attr.attr, + &iio_dev_attr_birmsos.dev_attr.attr, + &iio_dev_attr_cirmsos.dev_attr.attr, + &iio_dev_attr_avrmsos.dev_attr.attr, + &iio_dev_attr_bvrmsos.dev_attr.attr, + &iio_dev_attr_cvrmsos.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ade7754_attribute_group = { + .attrs = ade7754_attributes, +}; + + + +static int __devinit ade7754_probe(struct spi_device *spi) +{ + int ret, regdone = 0; + struct ade7754_state *st = kzalloc(sizeof *st, GFP_KERNEL); + if (!st) { + ret = -ENOMEM; + goto error_ret; + } + /* this is only used for removal purposes */ + spi_set_drvdata(spi, st); + + /* Allocate the comms buffers */ + st->rx = kzalloc(sizeof(*st->rx)*ADE7754_MAX_RX, GFP_KERNEL); + if (st->rx == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->tx = kzalloc(sizeof(*st->tx)*ADE7754_MAX_TX, GFP_KERNEL); + if (st->tx == NULL) { + ret = -ENOMEM; + goto error_free_rx; + } + st->us = spi; + mutex_init(&st->buf_lock); + /* setup the industrialio driver allocated elements */ + st->indio_dev = iio_allocate_device(); + if (st->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_tx; + } + + st->indio_dev->dev.parent = &spi->dev; + st->indio_dev->num_interrupt_lines = 1; + st->indio_dev->event_attrs = &ade7754_event_attribute_group; + st->indio_dev->attrs = &ade7754_attribute_group; + st->indio_dev->dev_data = (void *)(st); + st->indio_dev->driver_module = THIS_MODULE; + st->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = ade7754_configure_ring(st->indio_dev); + if (ret) + goto error_free_dev; + + ret = iio_device_register(st->indio_dev); + if (ret) + goto error_unreg_ring_funcs; + regdone = 1; + + ret = ade7754_initialize_ring(st->indio_dev->ring); + if (ret) { + printk(KERN_ERR "failed to initialize the ring\n"); + goto error_unreg_ring_funcs; + } + + if (spi->irq) { + ret = iio_register_interrupt_line(spi->irq, + st->indio_dev, + 0, + IRQF_TRIGGER_FALLING, + "ade7754"); + if (ret) + goto error_uninitialize_ring; + + ret = ade7754_probe_trigger(st->indio_dev); + if (ret) + goto error_unregister_line; + } + + /* Get the device into a sane initial state */ + ret = ade7754_initial_setup(st); + if (ret) + goto error_remove_trigger; + return 0; + +error_remove_trigger: + if (st->indio_dev->modes & INDIO_RING_TRIGGERED) + ade7754_remove_trigger(st->indio_dev); +error_unregister_line: + if (st->indio_dev->modes & INDIO_RING_TRIGGERED) + iio_unregister_interrupt_line(st->indio_dev, 0); +error_uninitialize_ring: + ade7754_uninitialize_ring(st->indio_dev->ring); +error_unreg_ring_funcs: + ade7754_unconfigure_ring(st->indio_dev); +error_free_dev: + if (regdone) + iio_device_unregister(st->indio_dev); + else + iio_free_device(st->indio_dev); +error_free_tx: + kfree(st->tx); +error_free_rx: + kfree(st->rx); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +/* fixme, confirm ordering in this function */ +static int ade7754_remove(struct spi_device *spi) +{ + int ret; + struct ade7754_state *st = spi_get_drvdata(spi); + struct iio_dev *indio_dev = st->indio_dev; + + ret = ade7754_stop_device(&(indio_dev->dev)); + if (ret) + goto err_ret; + + flush_scheduled_work(); + + ade7754_remove_trigger(indio_dev); + if (spi->irq) + iio_unregister_interrupt_line(indio_dev, 0); + + ade7754_uninitialize_ring(indio_dev->ring); + ade7754_unconfigure_ring(indio_dev); + iio_device_unregister(indio_dev); + kfree(st->tx); + kfree(st->rx); + kfree(st); + + return 0; + +err_ret: + return ret; +} + +static struct spi_driver ade7754_driver = { + .driver = { + .name = "ade7754", + .owner = THIS_MODULE, + }, + .probe = ade7754_probe, + .remove = __devexit_p(ade7754_remove), +}; + +static __init int ade7754_init(void) +{ + return spi_register_driver(&ade7754_driver); +} +module_init(ade7754_init); + +static __exit void ade7754_exit(void) +{ + spi_unregister_driver(&ade7754_driver); +} +module_exit(ade7754_exit); + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices ADE7754 Polyphase Multifunction Energy Metering IC Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/meter/ade7754.h b/trunk/drivers/staging/iio/meter/ade7754.h new file mode 100644 index 000000000000..f6a3e4b926cf --- /dev/null +++ b/trunk/drivers/staging/iio/meter/ade7754.h @@ -0,0 +1,161 @@ +#ifndef _ADE7754_H +#define _ADE7754_H + +#define ADE7754_AENERGY 0x01 +#define ADE7754_RAENERGY 0x02 +#define ADE7754_LAENERGY 0x03 +#define ADE7754_VAENERGY 0x04 +#define ADE7754_RVAENERGY 0x05 +#define ADE7754_LVAENERGY 0x06 +#define ADE7754_PERIOD 0x07 +#define ADE7754_TEMP 0x08 +#define ADE7754_WFORM 0x09 +#define ADE7754_OPMODE 0x0A +#define ADE7754_MMODE 0x0B +#define ADE7754_WAVMODE 0x0C +#define ADE7754_WATMODE 0x0D +#define ADE7754_VAMODE 0x0E +#define ADE7754_IRQEN 0x0F +#define ADE7754_STATUS 0x10 +#define ADE7754_RSTATUS 0x11 +#define ADE7754_ZXTOUT 0x12 +#define ADE7754_LINCYC 0x13 +#define ADE7754_SAGCYC 0x14 +#define ADE7754_SAGLVL 0x15 +#define ADE7754_VPEAK 0x16 +#define ADE7754_IPEAK 0x17 +#define ADE7754_GAIN 0x18 +#define ADE7754_AWG 0x19 +#define ADE7754_BWG 0x1A +#define ADE7754_CWG 0x1B +#define ADE7754_AVAG 0x1C +#define ADE7754_BVAG 0x1D +#define ADE7754_CVAG 0x1E +#define ADE7754_APHCAL 0x1F +#define ADE7754_BPHCAL 0x20 +#define ADE7754_CPHCAL 0x21 +#define ADE7754_AAPOS 0x22 +#define ADE7754_BAPOS 0x23 +#define ADE7754_CAPOS 0x24 +#define ADE7754_CFNUM 0x25 +#define ADE7754_CFDEN 0x26 +#define ADE7754_WDIV 0x27 +#define ADE7754_VADIV 0x28 +#define ADE7754_AIRMS 0x29 +#define ADE7754_BIRMS 0x2A +#define ADE7754_CIRMS 0x2B +#define ADE7754_AVRMS 0x2C +#define ADE7754_BVRMS 0x2D +#define ADE7754_CVRMS 0x2E +#define ADE7754_AIRMSOS 0x2F +#define ADE7754_BIRMSOS 0x30 +#define ADE7754_CIRMSOS 0x31 +#define ADE7754_AVRMSOS 0x32 +#define ADE7754_BVRMSOS 0x33 +#define ADE7754_CVRMSOS 0x34 +#define ADE7754_AAPGAIN 0x35 +#define ADE7754_BAPGAIN 0x36 +#define ADE7754_CAPGAIN 0x37 +#define ADE7754_AVGAIN 0x38 +#define ADE7754_BVGAIN 0x39 +#define ADE7754_CVGAIN 0x3A +#define ADE7754_CHKSUM 0x3E +#define ADE7754_VERSION 0x3F + +#define ADE7754_READ_REG(a) a +#define ADE7754_WRITE_REG(a) ((a) | 0x80) + +#define ADE7754_MAX_TX 4 +#define ADE7754_MAX_RX 4 +#define ADE7754_STARTUP_DELAY 1 + +#define ADE7754_SPI_SLOW (u32)(300 * 1000) +#define ADE7754_SPI_BURST (u32)(1000 * 1000) +#define ADE7754_SPI_FAST (u32)(2000 * 1000) + +#define DRIVER_NAME "ade7754" + +/** + * struct ade7754_state - device instance specific data + * @us: actual spi_device + * @work_trigger_to_ring: bh for triggered event handling + * @inter: used to check if new interrupt has been triggered + * @last_timestamp: passing timestamp from th to bh of interrupt handler + * @indio_dev: industrial I/O device structure + * @trig: data ready trigger registered with iio + * @tx: transmit buffer + * @rx: recieve buffer + * @buf_lock: mutex to protect tx and rx + **/ +struct ade7754_state { + struct spi_device *us; + struct work_struct work_trigger_to_ring; + s64 last_timestamp; + struct iio_dev *indio_dev; + struct iio_trigger *trig; + u8 *tx; + u8 *rx; + struct mutex buf_lock; +}; +#if defined(CONFIG_IIO_RING_BUFFER) && defined(THIS_HAS_RING_BUFFER_SUPPORT) +/* At the moment triggers are only used for ring buffer + * filling. This may change! + */ + +enum ade7754_scan { + ADE7754_SCAN_PHA_V, + ADE7754_SCAN_PHB_V, + ADE7754_SCAN_PHC_V, + ADE7754_SCAN_PHA_I, + ADE7754_SCAN_PHB_I, + ADE7754_SCAN_PHC_I, +}; + +void ade7754_remove_trigger(struct iio_dev *indio_dev); +int ade7754_probe_trigger(struct iio_dev *indio_dev); + +ssize_t ade7754_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf); + + +int ade7754_configure_ring(struct iio_dev *indio_dev); +void ade7754_unconfigure_ring(struct iio_dev *indio_dev); + +int ade7754_initialize_ring(struct iio_ring_buffer *ring); +void ade7754_uninitialize_ring(struct iio_ring_buffer *ring); +#else /* CONFIG_IIO_RING_BUFFER */ + +static inline void ade7754_remove_trigger(struct iio_dev *indio_dev) +{ +} +static inline int ade7754_probe_trigger(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline ssize_t +ade7754_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return 0; +} + +static int ade7754_configure_ring(struct iio_dev *indio_dev) +{ + return 0; +} +static inline void ade7754_unconfigure_ring(struct iio_dev *indio_dev) +{ +} +static inline int ade7754_initialize_ring(struct iio_ring_buffer *ring) +{ + return 0; +} +static inline void ade7754_uninitialize_ring(struct iio_ring_buffer *ring) +{ +} +#endif /* CONFIG_IIO_RING_BUFFER */ + +#endif diff --git a/trunk/drivers/staging/iio/meter/ade7758.h b/trunk/drivers/staging/iio/meter/ade7758.h new file mode 100644 index 000000000000..df5bb7ba5a0f --- /dev/null +++ b/trunk/drivers/staging/iio/meter/ade7758.h @@ -0,0 +1,171 @@ +#ifndef _ADE7758_H +#define _ADE7758_H + +#define ADE7758_AWATTHR 0x01 +#define ADE7758_BWATTHR 0x02 +#define ADE7758_CWATTHR 0x03 +#define ADE7758_AVARHR 0x04 +#define ADE7758_BVARHR 0x05 +#define ADE7758_CVARHR 0x06 +#define ADE7758_AVAHR 0x07 +#define ADE7758_BVAHR 0x08 +#define ADE7758_CVAHR 0x09 +#define ADE7758_AIRMS 0x0A +#define ADE7758_BIRMS 0x0B +#define ADE7758_CIRMS 0x0C +#define ADE7758_AVRMS 0x0D +#define ADE7758_BVRMS 0x0E +#define ADE7758_CVRMS 0x0F +#define ADE7758_FREQ 0x10 +#define ADE7758_TEMP 0x11 +#define ADE7758_WFORM 0x12 +#define ADE7758_OPMODE 0x13 +#define ADE7758_MMODE 0x14 +#define ADE7758_WAVMODE 0x15 +#define ADE7758_COMPMODE 0x16 +#define ADE7758_LCYCMODE 0x17 +#define ADE7758_MASK 0x18 +#define ADE7758_STATUS 0x19 +#define ADE7758_RSTATUS 0x1A +#define ADE7758_ZXTOUT 0x1B +#define ADE7758_LINECYC 0x1C +#define ADE7758_SAGCYC 0x1D +#define ADE7758_SAGLVL 0x1E +#define ADE7758_VPINTLVL 0x1F +#define ADE7758_IPINTLVL 0x20 +#define ADE7758_VPEAK 0x21 +#define ADE7758_IPEAK 0x22 +#define ADE7758_GAIN 0x23 +#define ADE7758_AVRMSGAIN 0x24 +#define ADE7758_BVRMSGAIN 0x25 +#define ADE7758_CVRMSGAIN 0x26 +#define ADE7758_AIGAIN 0x27 +#define ADE7758_BIGAIN 0x28 +#define ADE7758_CIGAIN 0x29 +#define ADE7758_AWG 0x2A +#define ADE7758_BWG 0x2B +#define ADE7758_CWG 0x2C +#define ADE7758_AVARG 0x2D +#define ADE7758_BVARG 0x2E +#define ADE7758_CVARG 0x2F +#define ADE7758_AVAG 0x30 +#define ADE7758_BVAG 0x31 +#define ADE7758_CVAG 0x32 +#define ADE7758_AVRMSOS 0x33 +#define ADE7758_BVRMSOS 0x34 +#define ADE7758_CVRMSOS 0x35 +#define ADE7758_AIRMSOS 0x36 +#define ADE7758_BIRMSOS 0x37 +#define ADE7758_CIRMSOS 0x38 +#define ADE7758_AWAITOS 0x39 +#define ADE7758_BWAITOS 0x3A +#define ADE7758_CWAITOS 0x3B +#define ADE7758_AVAROS 0x3C +#define ADE7758_BVAROS 0x3D +#define ADE7758_CVAROS 0x3E +#define ADE7758_APHCAL 0x3F +#define ADE7758_BPHCAL 0x40 +#define ADE7758_CPHCAL 0x41 +#define ADE7758_WDIV 0x42 +#define ADE7758_VADIV 0x44 +#define ADE7758_VARDIV 0x43 +#define ADE7758_APCFNUM 0x45 +#define ADE7758_APCFDEN 0x46 +#define ADE7758_VARCFNUM 0x47 +#define ADE7758_VARCFDEN 0x48 +#define ADE7758_CHKSUM 0x7E +#define ADE7758_VERSION 0x7F + +#define ADE7758_READ_REG(a) a +#define ADE7758_WRITE_REG(a) ((a) | 0x80) + +#define ADE7758_MAX_TX 8 +#define ADE7758_MAX_RX 4 +#define ADE7758_STARTUP_DELAY 1 + +#define ADE7758_SPI_SLOW (u32)(300 * 1000) +#define ADE7758_SPI_BURST (u32)(1000 * 1000) +#define ADE7758_SPI_FAST (u32)(2000 * 1000) + +#define DRIVER_NAME "ade7758" + +/** + * struct ade7758_state - device instance specific data + * @us: actual spi_device + * @work_trigger_to_ring: bh for triggered event handling + * @inter: used to check if new interrupt has been triggered + * @last_timestamp: passing timestamp from th to bh of interrupt handler + * @indio_dev: industrial I/O device structure + * @trig: data ready trigger registered with iio + * @tx: transmit buffer + * @rx: recieve buffer + * @buf_lock: mutex to protect tx and rx + **/ +struct ade7758_state { + struct spi_device *us; + struct work_struct work_trigger_to_ring; + s64 last_timestamp; + struct iio_dev *indio_dev; + struct iio_trigger *trig; + u8 *tx; + u8 *rx; + struct mutex buf_lock; +}; +#ifdef CONFIG_IIO_RING_BUFFER +/* At the moment triggers are only used for ring buffer + * filling. This may change! + */ + +enum ade7758_scan { + ADE7758_SCAN_WFORM, +}; + +void ade7758_remove_trigger(struct iio_dev *indio_dev); +int ade7758_probe_trigger(struct iio_dev *indio_dev); + +ssize_t ade7758_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf); + + +int ade7758_configure_ring(struct iio_dev *indio_dev); +void ade7758_unconfigure_ring(struct iio_dev *indio_dev); + +int ade7758_initialize_ring(struct iio_ring_buffer *ring); +void ade7758_uninitialize_ring(struct iio_ring_buffer *ring); +int ade7758_set_irq(struct device *dev, bool enable); +#else /* CONFIG_IIO_RING_BUFFER */ + +static inline void ade7758_remove_trigger(struct iio_dev *indio_dev) +{ +} +static inline int ade7758_probe_trigger(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline ssize_t +ade7758_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return 0; +} + +static int ade7758_configure_ring(struct iio_dev *indio_dev) +{ + return 0; +} +static inline void ade7758_unconfigure_ring(struct iio_dev *indio_dev) +{ +} +static inline int ade7758_initialize_ring(struct iio_ring_buffer *ring) +{ + return 0; +} +static inline void ade7758_uninitialize_ring(struct iio_ring_buffer *ring) +{ +} +#endif /* CONFIG_IIO_RING_BUFFER */ + +#endif diff --git a/trunk/drivers/staging/iio/meter/ade7758_core.c b/trunk/drivers/staging/iio/meter/ade7758_core.c new file mode 100644 index 000000000000..b7634cb7aa4f --- /dev/null +++ b/trunk/drivers/staging/iio/meter/ade7758_core.c @@ -0,0 +1,866 @@ +/* + * ADE7758 Polyphase Multifunction Energy Metering IC Driver + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "meter.h" +#include "ade7758.h" + +int ade7758_spi_write_reg_8(struct device *dev, + u8 reg_address, + u8 val) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7758_state *st = iio_dev_get_devdata(indio_dev); + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7758_WRITE_REG(reg_address); + st->tx[1] = val; + + ret = spi_write(st->us, st->tx, 2); + mutex_unlock(&st->buf_lock); + + return ret; +} + +static int ade7758_spi_write_reg_16(struct device *dev, + u8 reg_address, + u16 value) +{ + int ret; + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7758_state *st = iio_dev_get_devdata(indio_dev); + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 3, + } + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7758_WRITE_REG(reg_address); + st->tx[1] = (value >> 8) & 0xFF; + st->tx[2] = value & 0xFF; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->us, &msg); + mutex_unlock(&st->buf_lock); + + return ret; +} + +static int ade7758_spi_write_reg_24(struct device *dev, + u8 reg_address, + u32 value) +{ + int ret; + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7758_state *st = iio_dev_get_devdata(indio_dev); + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 4, + } + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7758_WRITE_REG(reg_address); + st->tx[1] = (value >> 16) & 0xFF; + st->tx[2] = (value >> 8) & 0xFF; + st->tx[3] = value & 0xFF; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->us, &msg); + mutex_unlock(&st->buf_lock); + + return ret; +} + +static int ade7758_spi_read_reg_8(struct device *dev, + u8 reg_address, + u8 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7758_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 2, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7758_READ_REG(reg_address); + st->tx[1] = 0; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X", + reg_address); + goto error_ret; + } + *val = st->rx[1]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static int ade7758_spi_read_reg_16(struct device *dev, + u8 reg_address, + u16 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7758_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 3, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7758_READ_REG(reg_address); + st->tx[1] = 0; + st->tx[2] = 0; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", + reg_address); + goto error_ret; + } + *val = (st->rx[1] << 8) | st->rx[2]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static int ade7758_spi_read_reg_24(struct device *dev, + u8 reg_address, + u32 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7758_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 4, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7758_READ_REG(reg_address); + st->tx[1] = 0; + st->tx[2] = 0; + st->tx[3] = 0; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X", + reg_address); + goto error_ret; + } + *val = (st->rx[1] << 16) | (st->rx[2] << 8) | st->rx[3]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static ssize_t ade7758_read_8bit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u8 val = 0; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = ade7758_spi_read_reg_8(dev, this_attr->address, &val); + if (ret) + return ret; + + return sprintf(buf, "%u\n", val); +} + +static ssize_t ade7758_read_16bit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u16 val = 0; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = ade7758_spi_read_reg_16(dev, this_attr->address, &val); + if (ret) + return ret; + + return sprintf(buf, "%u\n", val); +} + +static ssize_t ade7758_read_24bit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u32 val = 0; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = ade7758_spi_read_reg_24(dev, this_attr->address, &val); + if (ret) + return ret; + + return sprintf(buf, "%u\n", val & 0xFFFFFF); +} + +static ssize_t ade7758_write_8bit(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + long val; + + ret = strict_strtol(buf, 10, &val); + if (ret) + goto error_ret; + ret = ade7758_spi_write_reg_8(dev, this_attr->address, val); + +error_ret: + return ret ? ret : len; +} + +static ssize_t ade7758_write_16bit(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + long val; + + ret = strict_strtol(buf, 10, &val); + if (ret) + goto error_ret; + ret = ade7758_spi_write_reg_16(dev, this_attr->address, val); + +error_ret: + return ret ? ret : len; +} + +int ade7758_reset(struct device *dev) +{ + int ret; + u8 val; + ade7758_spi_read_reg_8(dev, + ADE7758_OPMODE, + &val); + val |= 1 << 6; /* Software Chip Reset */ + ret = ade7758_spi_write_reg_8(dev, + ADE7758_OPMODE, + val); + + return ret; +} + +static ssize_t ade7758_write_reset(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + if (len < 1) + return -1; + switch (buf[0]) { + case '1': + case 'y': + case 'Y': + return ade7758_reset(dev); + } + return -1; +} + +static IIO_DEV_ATTR_VPEAK(S_IWUSR | S_IRUGO, + ade7758_read_8bit, + ade7758_write_8bit, + ADE7758_VPEAK); +static IIO_DEV_ATTR_IPEAK(S_IWUSR | S_IRUGO, + ade7758_read_8bit, + ade7758_write_8bit, + ADE7758_VPEAK); +static IIO_DEV_ATTR_APHCAL(S_IWUSR | S_IRUGO, + ade7758_read_8bit, + ade7758_write_8bit, + ADE7758_APHCAL); +static IIO_DEV_ATTR_BPHCAL(S_IWUSR | S_IRUGO, + ade7758_read_8bit, + ade7758_write_8bit, + ADE7758_BPHCAL); +static IIO_DEV_ATTR_CPHCAL(S_IWUSR | S_IRUGO, + ade7758_read_8bit, + ade7758_write_8bit, + ADE7758_CPHCAL); +static IIO_DEV_ATTR_WDIV(S_IWUSR | S_IRUGO, + ade7758_read_8bit, + ade7758_write_8bit, + ADE7758_WDIV); +static IIO_DEV_ATTR_VADIV(S_IWUSR | S_IRUGO, + ade7758_read_8bit, + ade7758_write_8bit, + ADE7758_VADIV); +static IIO_DEV_ATTR_AIRMS(S_IRUGO, + ade7758_read_24bit, + NULL, + ADE7758_AIRMS); +static IIO_DEV_ATTR_BIRMS(S_IRUGO, + ade7758_read_24bit, + NULL, + ADE7758_BIRMS); +static IIO_DEV_ATTR_CIRMS(S_IRUGO, + ade7758_read_24bit, + NULL, + ADE7758_CIRMS); +static IIO_DEV_ATTR_AVRMS(S_IRUGO, + ade7758_read_24bit, + NULL, + ADE7758_AVRMS); +static IIO_DEV_ATTR_BVRMS(S_IRUGO, + ade7758_read_24bit, + NULL, + ADE7758_BVRMS); +static IIO_DEV_ATTR_CVRMS(S_IRUGO, + ade7758_read_24bit, + NULL, + ADE7758_CVRMS); +static IIO_DEV_ATTR_AIRMSOS(S_IWUSR | S_IRUGO, + ade7758_read_16bit, + ade7758_write_16bit, + ADE7758_AIRMSOS); +static IIO_DEV_ATTR_BIRMSOS(S_IWUSR | S_IRUGO, + ade7758_read_16bit, + ade7758_write_16bit, + ADE7758_BIRMSOS); +static IIO_DEV_ATTR_CIRMSOS(S_IWUSR | S_IRUGO, + ade7758_read_16bit, + ade7758_write_16bit, + ADE7758_CIRMSOS); +static IIO_DEV_ATTR_AVRMSOS(S_IWUSR | S_IRUGO, + ade7758_read_16bit, + ade7758_write_16bit, + ADE7758_AVRMSOS); +static IIO_DEV_ATTR_BVRMSOS(S_IWUSR | S_IRUGO, + ade7758_read_16bit, + ade7758_write_16bit, + ADE7758_BVRMSOS); +static IIO_DEV_ATTR_CVRMSOS(S_IWUSR | S_IRUGO, + ade7758_read_16bit, + ade7758_write_16bit, + ADE7758_CVRMSOS); +static IIO_DEV_ATTR_AIGAIN(S_IWUSR | S_IRUGO, + ade7758_read_16bit, + ade7758_write_16bit, + ADE7758_AIGAIN); +static IIO_DEV_ATTR_BIGAIN(S_IWUSR | S_IRUGO, + ade7758_read_16bit, + ade7758_write_16bit, + ADE7758_BIGAIN); +static IIO_DEV_ATTR_CIGAIN(S_IWUSR | S_IRUGO, + ade7758_read_16bit, + ade7758_write_16bit, + ADE7758_CIGAIN); +static IIO_DEV_ATTR_AVRMSGAIN(S_IWUSR | S_IRUGO, + ade7758_read_16bit, + ade7758_write_16bit, + ADE7758_AVRMSGAIN); +static IIO_DEV_ATTR_BVRMSGAIN(S_IWUSR | S_IRUGO, + ade7758_read_16bit, + ade7758_write_16bit, + ADE7758_BVRMSGAIN); +static IIO_DEV_ATTR_CVRMSGAIN(S_IWUSR | S_IRUGO, + ade7758_read_16bit, + ade7758_write_16bit, + ADE7758_CVRMSGAIN); + +int ade7758_set_irq(struct device *dev, bool enable) +{ + int ret; + u32 irqen; + ret = ade7758_spi_read_reg_24(dev, ADE7758_MASK, &irqen); + if (ret) + goto error_ret; + + if (enable) + irqen |= 1 << 16; /* Enables an interrupt when a data is + present in the waveform register */ + else + irqen &= ~(1 << 16); + + ret = ade7758_spi_write_reg_24(dev, ADE7758_MASK, irqen); + if (ret) + goto error_ret; + +error_ret: + return ret; +} + +/* Power down the device */ +static int ade7758_stop_device(struct device *dev) +{ + int ret; + u8 val; + ade7758_spi_read_reg_8(dev, + ADE7758_OPMODE, + &val); + val |= 7 << 3; /* ADE7758 powered down */ + ret = ade7758_spi_write_reg_8(dev, + ADE7758_OPMODE, + val); + + return ret; +} + +static int ade7758_initial_setup(struct ade7758_state *st) +{ + int ret; + struct device *dev = &st->indio_dev->dev; + + /* use low spi speed for init */ + st->us->mode = SPI_MODE_3; + spi_setup(st->us); + + /* Disable IRQ */ + ret = ade7758_set_irq(dev, false); + if (ret) { + dev_err(dev, "disable irq failed"); + goto err_ret; + } + + ade7758_reset(dev); + msleep(ADE7758_STARTUP_DELAY); + +err_ret: + return ret; +} + +static ssize_t ade7758_read_frequency(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret, len = 0; + u8 t; + int sps; + ret = ade7758_spi_read_reg_8(dev, + ADE7758_WAVMODE, + &t); + if (ret) + return ret; + + t = (t >> 5) & 0x3; + sps = 26040 / (1 << t); + + len = sprintf(buf, "%d SPS\n", sps); + return len; +} + +static ssize_t ade7758_write_frequency(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7758_state *st = iio_dev_get_devdata(indio_dev); + unsigned long val; + int ret; + u8 reg, t; + + ret = strict_strtol(buf, 10, &val); + if (ret) + return ret; + + mutex_lock(&indio_dev->mlock); + + t = (26040 / val); + if (t > 0) + t >>= 1; + + if (t > 1) + st->us->max_speed_hz = ADE7758_SPI_SLOW; + else + st->us->max_speed_hz = ADE7758_SPI_FAST; + + ret = ade7758_spi_read_reg_8(dev, + ADE7758_WAVMODE, + ®); + if (ret) + goto out; + + reg &= ~(5 << 3); + reg |= t << 5; + + ret = ade7758_spi_write_reg_8(dev, + ADE7758_WAVMODE, + reg); + +out: + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static ssize_t ade7758_read_waveform_type(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret, len = 0; + u8 t; + ret = ade7758_spi_read_reg_8(dev, + ADE7758_WAVMODE, + &t); + if (ret) + return ret; + + t = (t >> 2) & 0x7; + + len = sprintf(buf, "%d\n", t); + + return len; +} + +static ssize_t ade7758_write_waveform_type(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + unsigned long val; + int ret; + u8 reg; + + ret = strict_strtol(buf, 10, &val); + if (ret) + return ret; + + if (val > 4) + return -EINVAL; + + mutex_lock(&indio_dev->mlock); + + ret = ade7758_spi_read_reg_8(dev, + ADE7758_WAVMODE, + ®); + if (ret) + goto out; + + reg &= ~(7 << 2); + reg |= val << 2; + + ret = ade7758_spi_write_reg_8(dev, + ADE7758_WAVMODE, + reg); + +out: + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} + +static IIO_DEV_ATTR_TEMP_RAW(ade7758_read_8bit); +static IIO_CONST_ATTR(temp_offset, "129 C"); +static IIO_CONST_ATTR(temp_scale, "4 C"); + +static IIO_DEV_ATTR_AWATTHR(ade7758_read_16bit, + ADE7758_AWATTHR); +static IIO_DEV_ATTR_BWATTHR(ade7758_read_16bit, + ADE7758_BWATTHR); +static IIO_DEV_ATTR_CWATTHR(ade7758_read_16bit, + ADE7758_CWATTHR); +static IIO_DEV_ATTR_AVARHR(ade7758_read_16bit, + ADE7758_AVARHR); +static IIO_DEV_ATTR_BVARHR(ade7758_read_16bit, + ADE7758_BVARHR); +static IIO_DEV_ATTR_CVARHR(ade7758_read_16bit, + ADE7758_CVARHR); +static IIO_DEV_ATTR_AVAHR(ade7758_read_16bit, + ADE7758_AVAHR); +static IIO_DEV_ATTR_BVAHR(ade7758_read_16bit, + ADE7758_BVAHR); +static IIO_DEV_ATTR_CVAHR(ade7758_read_16bit, + ADE7758_CVAHR); + +static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, + ade7758_read_frequency, + ade7758_write_frequency); + +/** + * IIO_DEV_ATTR_WAVEFORM_TYPE - set the type of waveform. + * @_mode: sysfs file mode/permissions + * @_show: output method for the attribute + * @_store: input method for the attribute + **/ +#define IIO_DEV_ATTR_WAVEFORM_TYPE(_mode, _show, _store) \ + IIO_DEVICE_ATTR(waveform_type, _mode, _show, _store, 0) + +static IIO_DEV_ATTR_WAVEFORM_TYPE(S_IWUSR | S_IRUGO, + ade7758_read_waveform_type, + ade7758_write_waveform_type); + +static IIO_DEV_ATTR_RESET(ade7758_write_reset); + +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("26000 13000 65000 33000"); + +static IIO_CONST_ATTR(name, "ade7758"); + +static struct attribute *ade7758_event_attributes[] = { + NULL +}; + +static struct attribute_group ade7758_event_attribute_group = { + .attrs = ade7758_event_attributes, +}; + +static struct attribute *ade7758_attributes[] = { + &iio_dev_attr_temp_raw.dev_attr.attr, + &iio_const_attr_temp_offset.dev_attr.attr, + &iio_const_attr_temp_scale.dev_attr.attr, + &iio_dev_attr_sampling_frequency.dev_attr.attr, + &iio_dev_attr_waveform_type.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + &iio_dev_attr_reset.dev_attr.attr, + &iio_const_attr_name.dev_attr.attr, + &iio_dev_attr_awatthr.dev_attr.attr, + &iio_dev_attr_bwatthr.dev_attr.attr, + &iio_dev_attr_cwatthr.dev_attr.attr, + &iio_dev_attr_avarhr.dev_attr.attr, + &iio_dev_attr_bvarhr.dev_attr.attr, + &iio_dev_attr_cvarhr.dev_attr.attr, + &iio_dev_attr_avahr.dev_attr.attr, + &iio_dev_attr_bvahr.dev_attr.attr, + &iio_dev_attr_cvahr.dev_attr.attr, + &iio_dev_attr_vpeak.dev_attr.attr, + &iio_dev_attr_ipeak.dev_attr.attr, + &iio_dev_attr_aphcal.dev_attr.attr, + &iio_dev_attr_bphcal.dev_attr.attr, + &iio_dev_attr_cphcal.dev_attr.attr, + &iio_dev_attr_wdiv.dev_attr.attr, + &iio_dev_attr_vadiv.dev_attr.attr, + &iio_dev_attr_airms.dev_attr.attr, + &iio_dev_attr_birms.dev_attr.attr, + &iio_dev_attr_cirms.dev_attr.attr, + &iio_dev_attr_avrms.dev_attr.attr, + &iio_dev_attr_bvrms.dev_attr.attr, + &iio_dev_attr_cvrms.dev_attr.attr, + &iio_dev_attr_aigain.dev_attr.attr, + &iio_dev_attr_bigain.dev_attr.attr, + &iio_dev_attr_cigain.dev_attr.attr, + &iio_dev_attr_avrmsgain.dev_attr.attr, + &iio_dev_attr_bvrmsgain.dev_attr.attr, + &iio_dev_attr_cvrmsgain.dev_attr.attr, + &iio_dev_attr_airmsos.dev_attr.attr, + &iio_dev_attr_birmsos.dev_attr.attr, + &iio_dev_attr_cirmsos.dev_attr.attr, + &iio_dev_attr_avrmsos.dev_attr.attr, + &iio_dev_attr_bvrmsos.dev_attr.attr, + &iio_dev_attr_cvrmsos.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ade7758_attribute_group = { + .attrs = ade7758_attributes, +}; + + + +static int __devinit ade7758_probe(struct spi_device *spi) +{ + int ret, regdone = 0; + struct ade7758_state *st = kzalloc(sizeof *st, GFP_KERNEL); + if (!st) { + ret = -ENOMEM; + goto error_ret; + } + /* this is only used for removal purposes */ + spi_set_drvdata(spi, st); + + /* Allocate the comms buffers */ + st->rx = kzalloc(sizeof(*st->rx)*ADE7758_MAX_RX, GFP_KERNEL); + if (st->rx == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->tx = kzalloc(sizeof(*st->tx)*ADE7758_MAX_TX, GFP_KERNEL); + if (st->tx == NULL) { + ret = -ENOMEM; + goto error_free_rx; + } + st->us = spi; + mutex_init(&st->buf_lock); + /* setup the industrialio driver allocated elements */ + st->indio_dev = iio_allocate_device(); + if (st->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_tx; + } + + st->indio_dev->dev.parent = &spi->dev; + st->indio_dev->num_interrupt_lines = 1; + st->indio_dev->event_attrs = &ade7758_event_attribute_group; + st->indio_dev->attrs = &ade7758_attribute_group; + st->indio_dev->dev_data = (void *)(st); + st->indio_dev->driver_module = THIS_MODULE; + st->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = ade7758_configure_ring(st->indio_dev); + if (ret) + goto error_free_dev; + + ret = iio_device_register(st->indio_dev); + if (ret) + goto error_unreg_ring_funcs; + regdone = 1; + + ret = ade7758_initialize_ring(st->indio_dev->ring); + if (ret) { + printk(KERN_ERR "failed to initialize the ring\n"); + goto error_unreg_ring_funcs; + } + + if (spi->irq) { + ret = iio_register_interrupt_line(spi->irq, + st->indio_dev, + 0, + IRQF_TRIGGER_FALLING, + "ade7758"); + if (ret) + goto error_uninitialize_ring; + + ret = ade7758_probe_trigger(st->indio_dev); + if (ret) + goto error_unregister_line; + } + + /* Get the device into a sane initial state */ + ret = ade7758_initial_setup(st); + if (ret) + goto error_remove_trigger; + return 0; + +error_remove_trigger: + if (st->indio_dev->modes & INDIO_RING_TRIGGERED) + ade7758_remove_trigger(st->indio_dev); +error_unregister_line: + if (st->indio_dev->modes & INDIO_RING_TRIGGERED) + iio_unregister_interrupt_line(st->indio_dev, 0); +error_uninitialize_ring: + ade7758_uninitialize_ring(st->indio_dev->ring); +error_unreg_ring_funcs: + ade7758_unconfigure_ring(st->indio_dev); +error_free_dev: + if (regdone) + iio_device_unregister(st->indio_dev); + else + iio_free_device(st->indio_dev); +error_free_tx: + kfree(st->tx); +error_free_rx: + kfree(st->rx); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +static int ade7758_remove(struct spi_device *spi) +{ + int ret; + struct ade7758_state *st = spi_get_drvdata(spi); + struct iio_dev *indio_dev = st->indio_dev; + + ret = ade7758_stop_device(&(indio_dev->dev)); + if (ret) + goto err_ret; + + flush_scheduled_work(); + + ade7758_remove_trigger(indio_dev); + if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) + iio_unregister_interrupt_line(indio_dev, 0); + + ade7758_uninitialize_ring(indio_dev->ring); + iio_device_unregister(indio_dev); + ade7758_unconfigure_ring(indio_dev); + kfree(st->tx); + kfree(st->rx); + kfree(st); + + return 0; + +err_ret: + return ret; +} + +static struct spi_driver ade7758_driver = { + .driver = { + .name = "ade7758", + .owner = THIS_MODULE, + }, + .probe = ade7758_probe, + .remove = __devexit_p(ade7758_remove), +}; + +static __init int ade7758_init(void) +{ + return spi_register_driver(&ade7758_driver); +} +module_init(ade7758_init); + +static __exit void ade7758_exit(void) +{ + spi_unregister_driver(&ade7758_driver); +} +module_exit(ade7758_exit); + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices ADE7758 Polyphase Multifunction Energy Metering IC Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/meter/ade7758_ring.c b/trunk/drivers/staging/iio/meter/ade7758_ring.c new file mode 100644 index 000000000000..274b4a07808c --- /dev/null +++ b/trunk/drivers/staging/iio/meter/ade7758_ring.c @@ -0,0 +1,212 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "../ring_sw.h" +#include "../accel/accel.h" +#include "../trigger.h" +#include "ade7758.h" + +/** + * combine_8_to_32() utility function to munge to u8s into u32 + **/ +static inline u32 combine_8_to_32(u8 lower, u8 mid, u8 upper) +{ + u32 _lower = lower; + u32 _mid = mid; + u32 _upper = upper; + + return _lower | (_mid << 8) | (_upper << 16); +} + +static IIO_SCAN_EL_C(wform, ADE7758_SCAN_WFORM, ADE7758_WFORM, NULL); +static IIO_CONST_ATTR_SCAN_EL_TYPE(wform, s, 24, 32); +static IIO_SCAN_EL_TIMESTAMP(1); +static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64); + +static struct attribute *ade7758_scan_el_attrs[] = { + &iio_scan_el_wform.dev_attr.attr, + &iio_const_attr_wform_index.dev_attr.attr, + &iio_const_attr_wform_type.dev_attr.attr, + &iio_scan_el_timestamp.dev_attr.attr, + &iio_const_attr_timestamp_index.dev_attr.attr, + &iio_const_attr_timestamp_type.dev_attr.attr, + NULL, +}; + +static struct attribute_group ade7758_scan_el_group = { + .attrs = ade7758_scan_el_attrs, + .name = "scan_elements", +}; + +/** + * ade7758_poll_func_th() top half interrupt handler called by trigger + * @private_data: iio_dev + **/ +static void ade7758_poll_func_th(struct iio_dev *indio_dev, s64 time) +{ + struct ade7758_state *st = iio_dev_get_devdata(indio_dev); + st->last_timestamp = time; + schedule_work(&st->work_trigger_to_ring); + /* Indicate that this interrupt is being handled */ + + /* Technically this is trigger related, but without this + * handler running there is currently no way for the interrupt + * to clear. + */ +} + +/** + * ade7758_spi_read_burst() - read all data registers + * @dev: device associated with child of actual device (iio_dev or iio_trig) + * @rx: somewhere to pass back the value read (min size is 24 bytes) + **/ +static int ade7758_spi_read_burst(struct device *dev, u8 *rx) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7758_state *st = iio_dev_get_devdata(indio_dev); + int ret; + + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .rx_buf = rx, + .bits_per_word = 8, + .len = 4, + }, { + .tx_buf = st->tx + 4, + .rx_buf = rx, + .bits_per_word = 8, + .len = 4, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7758_READ_REG(ADE7758_RSTATUS); + st->tx[1] = 0; + st->tx[2] = 0; + st->tx[3] = 0; + st->tx[4] = ADE7758_READ_REG(ADE7758_WFORM); + st->tx[5] = 0; + st->tx[6] = 0; + st->tx[7] = 0; + + spi_message_init(&msg); + spi_message_add_tail(&xfers[0], &msg); + spi_message_add_tail(&xfers[1], &msg); + ret = spi_sync(st->us, &msg); + if (ret) + dev_err(&st->us->dev, "problem when reading WFORM value\n"); + + mutex_unlock(&st->buf_lock); + + return ret; +} + +/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device + * specific to be rolled into the core. + */ +static void ade7758_trigger_bh_to_ring(struct work_struct *work_s) +{ + struct ade7758_state *st + = container_of(work_s, struct ade7758_state, + work_trigger_to_ring); + struct iio_ring_buffer *ring = st->indio_dev->ring; + + int i = 0; + s32 *data; + size_t datasize = ring->access.get_bytes_per_datum(ring); + + data = kmalloc(datasize, GFP_KERNEL); + if (data == NULL) { + dev_err(&st->us->dev, "memory alloc failed in ring bh"); + return; + } + + if (ring->scan_count) + if (ade7758_spi_read_burst(&st->indio_dev->dev, st->rx) >= 0) + for (; i < ring->scan_count; i++) + data[i] = combine_8_to_32(st->rx[i*2+2], + st->rx[i*2+1], + st->rx[i*2]); + + /* Guaranteed to be aligned with 8 byte boundary */ + if (ring->scan_timestamp) + *((s64 *) + (((u32)data + 4 * ring->scan_count + 4) & ~0x7)) = + st->last_timestamp; + + ring->access.store_to(ring, + (u8 *)data, + st->last_timestamp); + + iio_trigger_notify_done(st->indio_dev->trig); + kfree(data); + + return; +} + +void ade7758_unconfigure_ring(struct iio_dev *indio_dev) +{ + kfree(indio_dev->pollfunc); + iio_sw_rb_free(indio_dev->ring); +} + +int ade7758_configure_ring(struct iio_dev *indio_dev) +{ + int ret = 0; + struct ade7758_state *st = indio_dev->dev_data; + struct iio_ring_buffer *ring; + INIT_WORK(&st->work_trigger_to_ring, ade7758_trigger_bh_to_ring); + + ring = iio_sw_rb_allocate(indio_dev); + if (!ring) { + ret = -ENOMEM; + return ret; + } + indio_dev->ring = ring; + /* Effectively select the ring buffer implementation */ + iio_ring_sw_register_funcs(&ring->access); + ring->bpe = 4; + ring->scan_el_attrs = &ade7758_scan_el_group; + ring->scan_timestamp = true; + ring->preenable = &iio_sw_ring_preenable; + ring->postenable = &iio_triggered_ring_postenable; + ring->predisable = &iio_triggered_ring_predisable; + ring->owner = THIS_MODULE; + + /* Set default scan mode */ + iio_scan_mask_set(ring, iio_scan_el_wform.number); + + ret = iio_alloc_pollfunc(indio_dev, NULL, &ade7758_poll_func_th); + if (ret) + goto error_iio_sw_rb_free; + + indio_dev->modes |= INDIO_RING_TRIGGERED; + return 0; + +error_iio_sw_rb_free: + iio_sw_rb_free(indio_dev->ring); + return ret; +} + +int ade7758_initialize_ring(struct iio_ring_buffer *ring) +{ + return iio_ring_buffer_register(ring, 0); +} + +void ade7758_uninitialize_ring(struct iio_ring_buffer *ring) +{ + iio_ring_buffer_unregister(ring); +} diff --git a/trunk/drivers/staging/iio/meter/ade7758_trigger.c b/trunk/drivers/staging/iio/meter/ade7758_trigger.c new file mode 100644 index 000000000000..60abca0c28ff --- /dev/null +++ b/trunk/drivers/staging/iio/meter/ade7758_trigger.c @@ -0,0 +1,125 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "../trigger.h" +#include "ade7758.h" + +/** + * ade7758_data_rdy_trig_poll() the event handler for the data rdy trig + **/ +static int ade7758_data_rdy_trig_poll(struct iio_dev *dev_info, + int index, + s64 timestamp, + int no_test) +{ + struct ade7758_state *st = iio_dev_get_devdata(dev_info); + struct iio_trigger *trig = st->trig; + + iio_trigger_poll(trig, timestamp); + + return IRQ_HANDLED; +} + +IIO_EVENT_SH(data_rdy_trig, &ade7758_data_rdy_trig_poll); + +static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL); + +static struct attribute *ade7758_trigger_attrs[] = { + &dev_attr_name.attr, + NULL, +}; + +static const struct attribute_group ade7758_trigger_attr_group = { + .attrs = ade7758_trigger_attrs, +}; + +/** + * ade7758_data_rdy_trigger_set_state() set datardy interrupt state + **/ +static int ade7758_data_rdy_trigger_set_state(struct iio_trigger *trig, + bool state) +{ + struct ade7758_state *st = trig->private_data; + struct iio_dev *indio_dev = st->indio_dev; + int ret = 0; + + dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); + ret = ade7758_set_irq(&st->indio_dev->dev, state); + if (state == false) { + iio_remove_event_from_list(&iio_event_data_rdy_trig, + &indio_dev->interrupts[0] + ->ev_list); + /* possible quirk with handler currently worked around + by ensuring the work queue is empty */ + flush_scheduled_work(); + } else { + iio_add_event_to_list(&iio_event_data_rdy_trig, + &indio_dev->interrupts[0]->ev_list); + } + return ret; +} + +/** + * ade7758_trig_try_reen() try renabling irq for data rdy trigger + * @trig: the datardy trigger + **/ +static int ade7758_trig_try_reen(struct iio_trigger *trig) +{ + struct ade7758_state *st = trig->private_data; + enable_irq(st->us->irq); + /* irq reenabled so success! */ + return 0; +} + +int ade7758_probe_trigger(struct iio_dev *indio_dev) +{ + int ret; + struct ade7758_state *st = indio_dev->dev_data; + + st->trig = iio_allocate_trigger(); + st->trig->name = kasprintf(GFP_KERNEL, + "ade7758-dev%d", + indio_dev->id); + if (!st->trig->name) { + ret = -ENOMEM; + goto error_free_trig; + } + st->trig->dev.parent = &st->us->dev; + st->trig->owner = THIS_MODULE; + st->trig->private_data = st; + st->trig->set_trigger_state = &ade7758_data_rdy_trigger_set_state; + st->trig->try_reenable = &ade7758_trig_try_reen; + st->trig->control_attrs = &ade7758_trigger_attr_group; + ret = iio_trigger_register(st->trig); + + /* select default trigger */ + indio_dev->trig = st->trig; + if (ret) + goto error_free_trig_name; + + return 0; + +error_free_trig_name: + kfree(st->trig->name); +error_free_trig: + iio_free_trigger(st->trig); + + return ret; +} + +void ade7758_remove_trigger(struct iio_dev *indio_dev) +{ + struct ade7758_state *state = indio_dev->dev_data; + + iio_trigger_unregister(state->trig); + kfree(state->trig->name); + iio_free_trigger(state->trig); +} diff --git a/trunk/drivers/staging/iio/meter/ade7759.c b/trunk/drivers/staging/iio/meter/ade7759.c new file mode 100644 index 000000000000..fafc3c1e5aaa --- /dev/null +++ b/trunk/drivers/staging/iio/meter/ade7759.c @@ -0,0 +1,670 @@ +/* + * ADE7759 Active Energy Metering IC with di/dt Sensor Interface Driver + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "meter.h" +#include "ade7759.h" + +int ade7759_spi_write_reg_8(struct device *dev, + u8 reg_address, + u8 val) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7759_state *st = iio_dev_get_devdata(indio_dev); + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7759_WRITE_REG(reg_address); + st->tx[1] = val; + + ret = spi_write(st->us, st->tx, 2); + mutex_unlock(&st->buf_lock); + + return ret; +} + +static int ade7759_spi_write_reg_16(struct device *dev, + u8 reg_address, + u16 value) +{ + int ret; + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7759_state *st = iio_dev_get_devdata(indio_dev); + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 3, + } + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7759_WRITE_REG(reg_address); + st->tx[1] = (value >> 8) & 0xFF; + st->tx[2] = value & 0xFF; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->us, &msg); + mutex_unlock(&st->buf_lock); + + return ret; +} + +static int ade7759_spi_read_reg_8(struct device *dev, + u8 reg_address, + u8 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7759_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 2, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7759_READ_REG(reg_address); + st->tx[1] = 0; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X", + reg_address); + goto error_ret; + } + *val = st->rx[1]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static int ade7759_spi_read_reg_16(struct device *dev, + u8 reg_address, + u16 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7759_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 3, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7759_READ_REG(reg_address); + st->tx[1] = 0; + st->tx[2] = 0; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", + reg_address); + goto error_ret; + } + *val = (st->rx[1] << 8) | st->rx[2]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static int ade7759_spi_read_reg_40(struct device *dev, + u8 reg_address, + u64 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7759_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .rx_buf = st->rx, + .bits_per_word = 8, + .len = 6, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7759_READ_REG(reg_address); + memset(&st->tx[1], 0 , 5); + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->us, &msg); + if (ret) { + dev_err(&st->us->dev, "problem when reading 40 bit register 0x%02X", + reg_address); + goto error_ret; + } + *val = ((u64)st->rx[1] << 32) | (st->rx[2] << 24) | + (st->rx[3] << 16) | (st->rx[4] << 8) | st->rx[5]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static ssize_t ade7759_read_8bit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u8 val = 0; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = ade7759_spi_read_reg_8(dev, this_attr->address, &val); + if (ret) + return ret; + + return sprintf(buf, "%u\n", val); +} + +static ssize_t ade7759_read_16bit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u16 val = 0; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = ade7759_spi_read_reg_16(dev, this_attr->address, &val); + if (ret) + return ret; + + return sprintf(buf, "%u\n", val); +} + +static ssize_t ade7759_read_40bit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u64 val = 0; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = ade7759_spi_read_reg_40(dev, this_attr->address, &val); + if (ret) + return ret; + + return sprintf(buf, "%llu\n", val); +} + +static ssize_t ade7759_write_8bit(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + long val; + + ret = strict_strtol(buf, 10, &val); + if (ret) + goto error_ret; + ret = ade7759_spi_write_reg_8(dev, this_attr->address, val); + +error_ret: + return ret ? ret : len; +} + +static ssize_t ade7759_write_16bit(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + int ret; + long val; + + ret = strict_strtol(buf, 10, &val); + if (ret) + goto error_ret; + ret = ade7759_spi_write_reg_16(dev, this_attr->address, val); + +error_ret: + return ret ? ret : len; +} + +static int ade7759_reset(struct device *dev) +{ + int ret; + u16 val; + ade7759_spi_read_reg_16(dev, + ADE7759_MODE, + &val); + val |= 1 << 6; /* Software Chip Reset */ + ret = ade7759_spi_write_reg_16(dev, + ADE7759_MODE, + val); + + return ret; +} + +static ssize_t ade7759_write_reset(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + if (len < 1) + return -1; + switch (buf[0]) { + case '1': + case 'y': + case 'Y': + return ade7759_reset(dev); + } + return -1; +} + +static IIO_DEV_ATTR_AENERGY(ade7759_read_40bit, ADE7759_AENERGY); +static IIO_DEV_ATTR_CFDEN(S_IWUSR | S_IRUGO, + ade7759_read_16bit, + ade7759_write_16bit, + ADE7759_CFDEN); +static IIO_DEV_ATTR_CFNUM(S_IWUSR | S_IRUGO, + ade7759_read_8bit, + ade7759_write_8bit, + ADE7759_CFNUM); +static IIO_DEV_ATTR_CHKSUM(ade7759_read_8bit, ADE7759_CHKSUM); +static IIO_DEV_ATTR_PHCAL(S_IWUSR | S_IRUGO, + ade7759_read_16bit, + ade7759_write_16bit, + ADE7759_PHCAL); +static IIO_DEV_ATTR_APOS(S_IWUSR | S_IRUGO, + ade7759_read_16bit, + ade7759_write_16bit, + ADE7759_APOS); +static IIO_DEV_ATTR_SAGCYC(S_IWUSR | S_IRUGO, + ade7759_read_8bit, + ade7759_write_8bit, + ADE7759_SAGCYC); +static IIO_DEV_ATTR_SAGLVL(S_IWUSR | S_IRUGO, + ade7759_read_8bit, + ade7759_write_8bit, + ADE7759_SAGLVL); +static IIO_DEV_ATTR_LINECYC(S_IWUSR | S_IRUGO, + ade7759_read_8bit, + ade7759_write_8bit, + ADE7759_LINECYC); +static IIO_DEV_ATTR_LENERGY(ade7759_read_40bit, ADE7759_LENERGY); +static IIO_DEV_ATTR_PGA_GAIN(S_IWUSR | S_IRUGO, + ade7759_read_8bit, + ade7759_write_8bit, + ADE7759_GAIN); +static IIO_DEV_ATTR_ACTIVE_POWER_GAIN(S_IWUSR | S_IRUGO, + ade7759_read_16bit, + ade7759_write_16bit, + ADE7759_APGAIN); +static IIO_DEV_ATTR_CH_OFF(1, S_IWUSR | S_IRUGO, + ade7759_read_8bit, + ade7759_write_8bit, + ADE7759_CH1OS); +static IIO_DEV_ATTR_CH_OFF(2, S_IWUSR | S_IRUGO, + ade7759_read_8bit, + ade7759_write_8bit, + ADE7759_CH2OS); + +static int ade7759_set_irq(struct device *dev, bool enable) +{ + int ret; + u8 irqen; + ret = ade7759_spi_read_reg_8(dev, ADE7759_IRQEN, &irqen); + if (ret) + goto error_ret; + + if (enable) + irqen |= 1 << 3; /* Enables an interrupt when a data is + present in the waveform register */ + else + irqen &= ~(1 << 3); + + ret = ade7759_spi_write_reg_8(dev, ADE7759_IRQEN, irqen); + if (ret) + goto error_ret; + +error_ret: + return ret; +} + +/* Power down the device */ +int ade7759_stop_device(struct device *dev) +{ + int ret; + u16 val; + ade7759_spi_read_reg_16(dev, + ADE7759_MODE, + &val); + val |= 1 << 4; /* AD converters can be turned off */ + ret = ade7759_spi_write_reg_16(dev, + ADE7759_MODE, + val); + + return ret; +} + +static int ade7759_initial_setup(struct ade7759_state *st) +{ + int ret; + struct device *dev = &st->indio_dev->dev; + + /* use low spi speed for init */ + st->us->mode = SPI_MODE_3; + spi_setup(st->us); + + /* Disable IRQ */ + ret = ade7759_set_irq(dev, false); + if (ret) { + dev_err(dev, "disable irq failed"); + goto err_ret; + } + + ade7759_reset(dev); + msleep(ADE7759_STARTUP_DELAY); + +err_ret: + return ret; +} + +static ssize_t ade7759_read_frequency(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret, len = 0; + u16 t; + int sps; + ret = ade7759_spi_read_reg_16(dev, + ADE7759_MODE, + &t); + if (ret) + return ret; + + t = (t >> 3) & 0x3; + sps = 27900 / (1 + t); + + len = sprintf(buf, "%d SPS\n", sps); + return len; +} + +static ssize_t ade7759_write_frequency(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7759_state *st = iio_dev_get_devdata(indio_dev); + unsigned long val; + int ret; + u16 reg, t; + + ret = strict_strtol(buf, 10, &val); + if (ret) + return ret; + + mutex_lock(&indio_dev->mlock); + + t = (27900 / val); + if (t > 0) + t--; + + if (t > 1) + st->us->max_speed_hz = ADE7759_SPI_SLOW; + else + st->us->max_speed_hz = ADE7759_SPI_FAST; + + ret = ade7759_spi_read_reg_16(dev, + ADE7759_MODE, + ®); + if (ret) + goto out; + + reg &= ~(3 << 13); + reg |= t << 13; + + ret = ade7759_spi_write_reg_16(dev, + ADE7759_MODE, + reg); + +out: + mutex_unlock(&indio_dev->mlock); + + return ret ? ret : len; +} +static IIO_DEV_ATTR_TEMP_RAW(ade7759_read_8bit); +static IIO_CONST_ATTR(temp_offset, "70 C"); +static IIO_CONST_ATTR(temp_scale, "1 C"); + +static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, + ade7759_read_frequency, + ade7759_write_frequency); + +static IIO_DEV_ATTR_RESET(ade7759_write_reset); + +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("27900 14000 7000 3500"); + +static IIO_CONST_ATTR(name, "ade7759"); + +static struct attribute *ade7759_event_attributes[] = { + NULL +}; + +static struct attribute_group ade7759_event_attribute_group = { + .attrs = ade7759_event_attributes, +}; + +static struct attribute *ade7759_attributes[] = { + &iio_dev_attr_temp_raw.dev_attr.attr, + &iio_const_attr_temp_offset.dev_attr.attr, + &iio_const_attr_temp_scale.dev_attr.attr, + &iio_dev_attr_sampling_frequency.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + &iio_dev_attr_reset.dev_attr.attr, + &iio_const_attr_name.dev_attr.attr, + &iio_dev_attr_phcal.dev_attr.attr, + &iio_dev_attr_cfden.dev_attr.attr, + &iio_dev_attr_aenergy.dev_attr.attr, + &iio_dev_attr_cfnum.dev_attr.attr, + &iio_dev_attr_apos.dev_attr.attr, + &iio_dev_attr_sagcyc.dev_attr.attr, + &iio_dev_attr_saglvl.dev_attr.attr, + &iio_dev_attr_linecyc.dev_attr.attr, + &iio_dev_attr_lenergy.dev_attr.attr, + &iio_dev_attr_chksum.dev_attr.attr, + &iio_dev_attr_pga_gain.dev_attr.attr, + &iio_dev_attr_active_power_gain.dev_attr.attr, + &iio_dev_attr_choff_1.dev_attr.attr, + &iio_dev_attr_choff_2.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ade7759_attribute_group = { + .attrs = ade7759_attributes, +}; + +static int __devinit ade7759_probe(struct spi_device *spi) +{ + int ret, regdone = 0; + struct ade7759_state *st = kzalloc(sizeof *st, GFP_KERNEL); + if (!st) { + ret = -ENOMEM; + goto error_ret; + } + /* this is only used for removal purposes */ + spi_set_drvdata(spi, st); + + /* Allocate the comms buffers */ + st->rx = kzalloc(sizeof(*st->rx)*ADE7759_MAX_RX, GFP_KERNEL); + if (st->rx == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->tx = kzalloc(sizeof(*st->tx)*ADE7759_MAX_TX, GFP_KERNEL); + if (st->tx == NULL) { + ret = -ENOMEM; + goto error_free_rx; + } + st->us = spi; + mutex_init(&st->buf_lock); + /* setup the industrialio driver allocated elements */ + st->indio_dev = iio_allocate_device(); + if (st->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_tx; + } + + st->indio_dev->dev.parent = &spi->dev; + st->indio_dev->num_interrupt_lines = 1; + st->indio_dev->event_attrs = &ade7759_event_attribute_group; + st->indio_dev->attrs = &ade7759_attribute_group; + st->indio_dev->dev_data = (void *)(st); + st->indio_dev->driver_module = THIS_MODULE; + st->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = ade7759_configure_ring(st->indio_dev); + if (ret) + goto error_free_dev; + + ret = iio_device_register(st->indio_dev); + if (ret) + goto error_unreg_ring_funcs; + regdone = 1; + + ret = ade7759_initialize_ring(st->indio_dev->ring); + if (ret) { + printk(KERN_ERR "failed to initialize the ring\n"); + goto error_unreg_ring_funcs; + } + + if (spi->irq) { + ret = iio_register_interrupt_line(spi->irq, + st->indio_dev, + 0, + IRQF_TRIGGER_FALLING, + "ade7759"); + if (ret) + goto error_uninitialize_ring; + + ret = ade7759_probe_trigger(st->indio_dev); + if (ret) + goto error_unregister_line; + } + + /* Get the device into a sane initial state */ + ret = ade7759_initial_setup(st); + if (ret) + goto error_remove_trigger; + return 0; + +error_remove_trigger: + if (st->indio_dev->modes & INDIO_RING_TRIGGERED) + ade7759_remove_trigger(st->indio_dev); +error_unregister_line: + if (st->indio_dev->modes & INDIO_RING_TRIGGERED) + iio_unregister_interrupt_line(st->indio_dev, 0); +error_uninitialize_ring: + ade7759_uninitialize_ring(st->indio_dev->ring); +error_unreg_ring_funcs: + ade7759_unconfigure_ring(st->indio_dev); +error_free_dev: + if (regdone) + iio_device_unregister(st->indio_dev); + else + iio_free_device(st->indio_dev); +error_free_tx: + kfree(st->tx); +error_free_rx: + kfree(st->rx); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +/* fixme, confirm ordering in this function */ +static int ade7759_remove(struct spi_device *spi) +{ + int ret; + struct ade7759_state *st = spi_get_drvdata(spi); + struct iio_dev *indio_dev = st->indio_dev; + + ret = ade7759_stop_device(&(indio_dev->dev)); + if (ret) + goto err_ret; + + flush_scheduled_work(); + + ade7759_remove_trigger(indio_dev); + if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) + iio_unregister_interrupt_line(indio_dev, 0); + + ade7759_uninitialize_ring(indio_dev->ring); + ade7759_unconfigure_ring(indio_dev); + iio_device_unregister(indio_dev); + kfree(st->tx); + kfree(st->rx); + kfree(st); + + return 0; + +err_ret: + return ret; +} + +static struct spi_driver ade7759_driver = { + .driver = { + .name = "ade7759", + .owner = THIS_MODULE, + }, + .probe = ade7759_probe, + .remove = __devexit_p(ade7759_remove), +}; + +static __init int ade7759_init(void) +{ + return spi_register_driver(&ade7759_driver); +} +module_init(ade7759_init); + +static __exit void ade7759_exit(void) +{ + spi_unregister_driver(&ade7759_driver); +} +module_exit(ade7759_exit); + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices ADE7759 Active Energy Metering IC Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/meter/ade7759.h b/trunk/drivers/staging/iio/meter/ade7759.h new file mode 100644 index 000000000000..813dea2676a9 --- /dev/null +++ b/trunk/drivers/staging/iio/meter/ade7759.h @@ -0,0 +1,122 @@ +#ifndef _ADE7759_H +#define _ADE7759_H + +#define ADE7759_WAVEFORM 0x01 +#define ADE7759_AENERGY 0x02 +#define ADE7759_RSTENERGY 0x03 +#define ADE7759_STATUS 0x04 +#define ADE7759_RSTSTATUS 0x05 +#define ADE7759_MODE 0x06 +#define ADE7759_CFDEN 0x07 +#define ADE7759_CH1OS 0x08 +#define ADE7759_CH2OS 0x09 +#define ADE7759_GAIN 0x0A +#define ADE7759_APGAIN 0x0B +#define ADE7759_PHCAL 0x0C +#define ADE7759_APOS 0x0D +#define ADE7759_ZXTOUT 0x0E +#define ADE7759_SAGCYC 0x0F +#define ADE7759_IRQEN 0x10 +#define ADE7759_SAGLVL 0x11 +#define ADE7759_TEMP 0x12 +#define ADE7759_LINECYC 0x13 +#define ADE7759_LENERGY 0x14 +#define ADE7759_CFNUM 0x15 +#define ADE7759_CHKSUM 0x1E +#define ADE7759_DIEREV 0x1F + +#define ADE7759_READ_REG(a) a +#define ADE7759_WRITE_REG(a) ((a) | 0x80) + +#define ADE7759_MAX_TX 6 +#define ADE7759_MAX_RX 6 +#define ADE7759_STARTUP_DELAY 1 + +#define ADE7759_SPI_SLOW (u32)(300 * 1000) +#define ADE7759_SPI_BURST (u32)(1000 * 1000) +#define ADE7759_SPI_FAST (u32)(2000 * 1000) + +#define DRIVER_NAME "ade7759" + +/** + * struct ade7759_state - device instance specific data + * @us: actual spi_device + * @work_trigger_to_ring: bh for triggered event handling + * @inter: used to check if new interrupt has been triggered + * @last_timestamp: passing timestamp from th to bh of interrupt handler + * @indio_dev: industrial I/O device structure + * @trig: data ready trigger registered with iio + * @tx: transmit buffer + * @rx: recieve buffer + * @buf_lock: mutex to protect tx and rx + **/ +struct ade7759_state { + struct spi_device *us; + struct work_struct work_trigger_to_ring; + s64 last_timestamp; + struct iio_dev *indio_dev; + struct iio_trigger *trig; + u8 *tx; + u8 *rx; + struct mutex buf_lock; +}; +#if defined(CONFIG_IIO_RING_BUFFER) && defined(THIS_HAS_RING_BUFFER_SUPPORT) +/* At the moment triggers are only used for ring buffer + * filling. This may change! + */ + +enum ade7759_scan { + ADE7759_SCAN_ACTIVE_POWER, + ADE7759_SCAN_CH1_CH2, + ADE7759_SCAN_CH1, + ADE7759_SCAN_CH2, +}; + +void ade7759_remove_trigger(struct iio_dev *indio_dev); +int ade7759_probe_trigger(struct iio_dev *indio_dev); + +ssize_t ade7759_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf); + + +int ade7759_configure_ring(struct iio_dev *indio_dev); +void ade7759_unconfigure_ring(struct iio_dev *indio_dev); + +int ade7759_initialize_ring(struct iio_ring_buffer *ring); +void ade7759_uninitialize_ring(struct iio_ring_buffer *ring); +#else /* CONFIG_IIO_RING_BUFFER */ + +static inline void ade7759_remove_trigger(struct iio_dev *indio_dev) +{ +} +static inline int ade7759_probe_trigger(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline ssize_t +ade7759_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return 0; +} + +static int ade7759_configure_ring(struct iio_dev *indio_dev) +{ + return 0; +} +static inline void ade7759_unconfigure_ring(struct iio_dev *indio_dev) +{ +} +static inline int ade7759_initialize_ring(struct iio_ring_buffer *ring) +{ + return 0; +} +static inline void ade7759_uninitialize_ring(struct iio_ring_buffer *ring) +{ +} +#endif /* CONFIG_IIO_RING_BUFFER */ + +#endif diff --git a/trunk/drivers/staging/iio/meter/ade7854-i2c.c b/trunk/drivers/staging/iio/meter/ade7854-i2c.c new file mode 100644 index 000000000000..4578e7b7f460 --- /dev/null +++ b/trunk/drivers/staging/iio/meter/ade7854-i2c.c @@ -0,0 +1,272 @@ +/* + * ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC Driver (I2C Bus) + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include + +#include "../iio.h" +#include "ade7854.h" + +static int ade7854_i2c_write_reg_8(struct device *dev, + u16 reg_address, + u8 value) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + + mutex_lock(&st->buf_lock); + st->tx[0] = (reg_address >> 8) & 0xFF; + st->tx[1] = reg_address & 0xFF; + st->tx[2] = value; + + ret = i2c_master_send(st->i2c, st->tx, 3); + mutex_unlock(&st->buf_lock); + + return ret; +} + +static int ade7854_i2c_write_reg_16(struct device *dev, + u16 reg_address, + u16 value) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + + mutex_lock(&st->buf_lock); + st->tx[0] = (reg_address >> 8) & 0xFF; + st->tx[1] = reg_address & 0xFF; + st->tx[2] = (value >> 8) & 0xFF; + st->tx[3] = value & 0xFF; + + ret = i2c_master_send(st->i2c, st->tx, 4); + mutex_unlock(&st->buf_lock); + + return ret; +} + +static int ade7854_i2c_write_reg_24(struct device *dev, + u16 reg_address, + u32 value) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + + mutex_lock(&st->buf_lock); + st->tx[0] = (reg_address >> 8) & 0xFF; + st->tx[1] = reg_address & 0xFF; + st->tx[2] = (value >> 16) & 0xFF; + st->tx[3] = (value >> 8) & 0xFF; + st->tx[4] = value & 0xFF; + + ret = i2c_master_send(st->i2c, st->tx, 5); + mutex_unlock(&st->buf_lock); + + return ret; +} + +static int ade7854_i2c_write_reg_32(struct device *dev, + u16 reg_address, + u32 value) +{ + int ret; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + + mutex_lock(&st->buf_lock); + st->tx[0] = (reg_address >> 8) & 0xFF; + st->tx[1] = reg_address & 0xFF; + st->tx[2] = (value >> 24) & 0xFF; + st->tx[3] = (value >> 16) & 0xFF; + st->tx[4] = (value >> 8) & 0xFF; + st->tx[5] = value & 0xFF; + + ret = i2c_master_send(st->i2c, st->tx, 6); + mutex_unlock(&st->buf_lock); + + return ret; +} + +static int ade7854_i2c_read_reg_8(struct device *dev, + u16 reg_address, + u8 *val) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + int ret; + + mutex_lock(&st->buf_lock); + st->tx[0] = (reg_address >> 8) & 0xFF; + st->tx[1] = reg_address & 0xFF; + + ret = i2c_master_send(st->i2c, st->tx, 2); + if (ret) + goto out; + + ret = i2c_master_recv(st->i2c, st->rx, 1); + if (ret) + goto out; + + *val = st->rx[0]; +out: + mutex_unlock(&st->buf_lock); + return ret; +} + +static int ade7854_i2c_read_reg_16(struct device *dev, + u16 reg_address, + u16 *val) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + int ret; + + mutex_lock(&st->buf_lock); + st->tx[0] = (reg_address >> 8) & 0xFF; + st->tx[1] = reg_address & 0xFF; + + ret = i2c_master_send(st->i2c, st->tx, 2); + if (ret) + goto out; + + ret = i2c_master_recv(st->i2c, st->rx, 2); + if (ret) + goto out; + + *val = (st->rx[0] << 8) | st->rx[1]; +out: + mutex_unlock(&st->buf_lock); + return ret; +} + +static int ade7854_i2c_read_reg_24(struct device *dev, + u16 reg_address, + u32 *val) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + int ret; + + mutex_lock(&st->buf_lock); + st->tx[0] = (reg_address >> 8) & 0xFF; + st->tx[1] = reg_address & 0xFF; + + ret = i2c_master_send(st->i2c, st->tx, 2); + if (ret) + goto out; + + ret = i2c_master_recv(st->i2c, st->rx, 3); + if (ret) + goto out; + + *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2]; +out: + mutex_unlock(&st->buf_lock); + return ret; +} + +static int ade7854_i2c_read_reg_32(struct device *dev, + u16 reg_address, + u32 *val) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + int ret; + + mutex_lock(&st->buf_lock); + st->tx[0] = (reg_address >> 8) & 0xFF; + st->tx[1] = reg_address & 0xFF; + + ret = i2c_master_send(st->i2c, st->tx, 2); + if (ret) + goto out; + + ret = i2c_master_recv(st->i2c, st->rx, 3); + if (ret) + goto out; + + *val = (st->rx[0] << 24) | (st->rx[1] << 16) | (st->rx[2] << 8) | st->rx[3]; +out: + mutex_unlock(&st->buf_lock); + return ret; +} + +static int __devinit ade7854_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret; + struct ade7854_state *st = kzalloc(sizeof *st, GFP_KERNEL); + if (!st) { + ret = -ENOMEM; + return ret; + } + + i2c_set_clientdata(client, st); + st->read_reg_8 = ade7854_i2c_read_reg_8; + st->read_reg_16 = ade7854_i2c_read_reg_16; + st->read_reg_24 = ade7854_i2c_read_reg_24; + st->read_reg_32 = ade7854_i2c_read_reg_32; + st->write_reg_8 = ade7854_i2c_write_reg_8; + st->write_reg_16 = ade7854_i2c_write_reg_16; + st->write_reg_24 = ade7854_i2c_write_reg_24; + st->write_reg_32 = ade7854_i2c_write_reg_32; + st->i2c = client; + st->irq = client->irq; + + ret = ade7854_probe(st, &client->dev); + if (ret) { + kfree(st); + return ret; + } + + return ret; +} + +static int __devexit ade7854_i2c_remove(struct i2c_client *client) +{ + return ade7854_remove(i2c_get_clientdata(client)); +} + +static const struct i2c_device_id ade7854_id[] = { + { "ade7854", 0 }, + { "ade7858", 0 }, + { "ade7868", 0 }, + { "ade7878", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ade7854_id); + +static struct i2c_driver ade7854_i2c_driver = { + .driver = { + .name = "ade7854", + }, + .probe = ade7854_i2c_probe, + .remove = __devexit_p(ade7854_i2c_remove), + .id_table = ade7854_id, +}; + +static __init int ade7854_i2c_init(void) +{ + return i2c_add_driver(&ade7854_i2c_driver); +} +module_init(ade7854_i2c_init); + +static __exit void ade7854_i2c_exit(void) +{ + i2c_del_driver(&ade7854_i2c_driver); +} +module_exit(ade7854_i2c_exit); + + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC I2C Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/meter/ade7854-spi.c b/trunk/drivers/staging/iio/meter/ade7854-spi.c new file mode 100644 index 000000000000..fe58103ed4ca --- /dev/null +++ b/trunk/drivers/staging/iio/meter/ade7854-spi.c @@ -0,0 +1,360 @@ +/* + * ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC Driver (SPI Bus) + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include + +#include "../iio.h" +#include "ade7854.h" + +static int ade7854_spi_write_reg_8(struct device *dev, + u16 reg_address, + u8 value) +{ + int ret; + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 4, + } + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7854_WRITE_REG; + st->tx[1] = (reg_address >> 8) & 0xFF; + st->tx[2] = reg_address & 0xFF; + st->tx[3] = value & 0xFF; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->spi, &msg); + mutex_unlock(&st->buf_lock); + + return ret; +} + +static int ade7854_spi_write_reg_16(struct device *dev, + u16 reg_address, + u16 value) +{ + int ret; + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 5, + } + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7854_WRITE_REG; + st->tx[1] = (reg_address >> 8) & 0xFF; + st->tx[2] = reg_address & 0xFF; + st->tx[3] = (value >> 8) & 0xFF; + st->tx[4] = value & 0xFF; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->spi, &msg); + mutex_unlock(&st->buf_lock); + + return ret; +} + +static int ade7854_spi_write_reg_24(struct device *dev, + u16 reg_address, + u32 value) +{ + int ret; + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 6, + } + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7854_WRITE_REG; + st->tx[1] = (reg_address >> 8) & 0xFF; + st->tx[2] = reg_address & 0xFF; + st->tx[3] = (value >> 16) & 0xFF; + st->tx[4] = (value >> 8) & 0xFF; + st->tx[5] = value & 0xFF; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->spi, &msg); + mutex_unlock(&st->buf_lock); + + return ret; +} + +static int ade7854_spi_write_reg_32(struct device *dev, + u16 reg_address, + u32 value) +{ + int ret; + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 7, + } + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7854_WRITE_REG; + st->tx[1] = (reg_address >> 8) & 0xFF; + st->tx[2] = reg_address & 0xFF; + st->tx[3] = (value >> 24) & 0xFF; + st->tx[4] = (value >> 16) & 0xFF; + st->tx[5] = (value >> 8) & 0xFF; + st->tx[6] = value & 0xFF; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->spi, &msg); + mutex_unlock(&st->buf_lock); + + return ret; +} + +static int ade7854_spi_read_reg_8(struct device *dev, + u16 reg_address, + u8 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 4, + }, + }; + + mutex_lock(&st->buf_lock); + + st->tx[0] = ADE7854_READ_REG; + st->tx[1] = (reg_address >> 8) & 0xFF; + st->tx[2] = reg_address & 0xFF; + st->tx[3] = 0; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->spi, &msg); + if (ret) { + dev_err(&st->spi->dev, "problem when reading 8 bit register 0x%02X", + reg_address); + goto error_ret; + } + *val = st->rx[3]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static int ade7854_spi_read_reg_16(struct device *dev, + u16 reg_address, + u16 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 5, + }, + }; + + mutex_lock(&st->buf_lock); + st->tx[0] = ADE7854_READ_REG; + st->tx[1] = (reg_address >> 8) & 0xFF; + st->tx[2] = reg_address & 0xFF; + st->tx[3] = 0; + st->tx[4] = 0; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->spi, &msg); + if (ret) { + dev_err(&st->spi->dev, "problem when reading 16 bit register 0x%02X", + reg_address); + goto error_ret; + } + *val = (st->rx[3] << 8) | st->rx[4]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static int ade7854_spi_read_reg_24(struct device *dev, + u16 reg_address, + u32 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 6, + }, + }; + + mutex_lock(&st->buf_lock); + + st->tx[0] = ADE7854_READ_REG; + st->tx[1] = (reg_address >> 8) & 0xFF; + st->tx[2] = reg_address & 0xFF; + st->tx[3] = 0; + st->tx[4] = 0; + st->tx[5] = 0; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->spi, &msg); + if (ret) { + dev_err(&st->spi->dev, "problem when reading 24 bit register 0x%02X", + reg_address); + goto error_ret; + } + *val = (st->rx[3] << 16) | (st->rx[4] << 8) | st->rx[5]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static int ade7854_spi_read_reg_32(struct device *dev, + u16 reg_address, + u32 *val) +{ + struct spi_message msg; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = st->tx, + .bits_per_word = 8, + .len = 7, + }, + }; + + mutex_lock(&st->buf_lock); + + st->tx[0] = ADE7854_READ_REG; + st->tx[1] = (reg_address >> 8) & 0xFF; + st->tx[2] = reg_address & 0xFF; + st->tx[3] = 0; + st->tx[4] = 0; + st->tx[5] = 0; + st->tx[6] = 0; + + spi_message_init(&msg); + spi_message_add_tail(xfers, &msg); + ret = spi_sync(st->spi, &msg); + if (ret) { + dev_err(&st->spi->dev, "problem when reading 32 bit register 0x%02X", + reg_address); + goto error_ret; + } + *val = (st->rx[3] << 24) | (st->rx[4] << 16) | (st->rx[5] << 8) | st->rx[6]; + +error_ret: + mutex_unlock(&st->buf_lock); + return ret; +} + +static int __devinit ade7854_spi_probe(struct spi_device *spi) +{ + int ret; + struct ade7854_state *st = kzalloc(sizeof *st, GFP_KERNEL); + if (!st) { + ret = -ENOMEM; + return ret; + } + + spi_set_drvdata(spi, st); + st->read_reg_8 = ade7854_spi_read_reg_8; + st->read_reg_16 = ade7854_spi_read_reg_16; + st->read_reg_24 = ade7854_spi_read_reg_24; + st->read_reg_32 = ade7854_spi_read_reg_32; + st->write_reg_8 = ade7854_spi_write_reg_8; + st->write_reg_16 = ade7854_spi_write_reg_16; + st->write_reg_24 = ade7854_spi_write_reg_24; + st->write_reg_32 = ade7854_spi_write_reg_32; + st->irq = spi->irq; + st->spi = spi; + + ret = ade7854_probe(st, &spi->dev); + if (ret) { + kfree(st); + return ret; + } + + return 0; +} + +static int ade7854_spi_remove(struct spi_device *spi) +{ + ade7854_remove(spi_get_drvdata(spi)); + + return 0; +} + +static struct spi_driver ade7854_driver = { + .driver = { + .name = "ade7854", + .owner = THIS_MODULE, + }, + .probe = ade7854_spi_probe, + .remove = __devexit_p(ade7854_spi_remove), +}; + +static __init int ade7854_init(void) +{ + return spi_register_driver(&ade7854_driver); +} +module_init(ade7854_init); + +static __exit void ade7854_exit(void) +{ + spi_unregister_driver(&ade7854_driver); +} +module_exit(ade7854_exit); + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC SPI Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/meter/ade7854.c b/trunk/drivers/staging/iio/meter/ade7854.c new file mode 100644 index 000000000000..a13d5048cf42 --- /dev/null +++ b/trunk/drivers/staging/iio/meter/ade7854.c @@ -0,0 +1,680 @@ +/* + * ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC Driver + * + * Copyright 2010 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "meter.h" +#include "ade7854.h" + +static ssize_t ade7854_read_8bit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u8 val = 0; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = st->read_reg_8(dev, this_attr->address, &val); + if (ret) + return ret; + + return sprintf(buf, "%u\n", val); +} + +static ssize_t ade7854_read_16bit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u16 val = 0; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = st->read_reg_16(dev, this_attr->address, &val); + if (ret) + return ret; + + return sprintf(buf, "%u\n", val); +} + +static ssize_t ade7854_read_24bit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u32 val = 0; + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + + ret = st->read_reg_24(dev, this_attr->address, &val); + if (ret) + return ret; + + return sprintf(buf, "%u\n", val & 0xFFFFFF); +} + +static ssize_t ade7854_read_32bit(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + u32 val = 0; + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + + ret = st->read_reg_32(dev, this_attr->address, &val); + if (ret) + return ret; + + return sprintf(buf, "%u\n", val); +} + +static ssize_t ade7854_write_8bit(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + + int ret; + long val; + + ret = strict_strtol(buf, 10, &val); + if (ret) + goto error_ret; + ret = st->write_reg_8(dev, this_attr->address, val); + +error_ret: + return ret ? ret : len; +} + +static ssize_t ade7854_write_16bit(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + + int ret; + long val; + + ret = strict_strtol(buf, 10, &val); + if (ret) + goto error_ret; + ret = st->write_reg_16(dev, this_attr->address, val); + +error_ret: + return ret ? ret : len; +} + +static ssize_t ade7854_write_24bit(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + + int ret; + long val; + + ret = strict_strtol(buf, 10, &val); + if (ret) + goto error_ret; + ret = st->write_reg_24(dev, this_attr->address, val); + +error_ret: + return ret ? ret : len; +} + +static ssize_t ade7854_write_32bit(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + + int ret; + long val; + + ret = strict_strtol(buf, 10, &val); + if (ret) + goto error_ret; + ret = st->write_reg_32(dev, this_attr->address, val); + +error_ret: + return ret ? ret : len; +} + +static int ade7854_reset(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + + int ret; + u16 val; + + st->read_reg_16(dev, ADE7854_CONFIG, &val); + val |= 1 << 7; /* Software Chip Reset */ + ret = st->write_reg_16(dev, ADE7854_CONFIG, val); + + return ret; +} + + +static ssize_t ade7854_write_reset(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + if (len < 1) + return -1; + switch (buf[0]) { + case '1': + case 'y': + case 'Y': + return ade7854_reset(dev); + } + return -1; +} + +static IIO_DEV_ATTR_AIGAIN(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_AIGAIN); +static IIO_DEV_ATTR_BIGAIN(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_BIGAIN); +static IIO_DEV_ATTR_CIGAIN(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_CIGAIN); +static IIO_DEV_ATTR_NIGAIN(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_NIGAIN); +static IIO_DEV_ATTR_AVGAIN(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_AVGAIN); +static IIO_DEV_ATTR_BVGAIN(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_BVGAIN); +static IIO_DEV_ATTR_CVGAIN(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_CVGAIN); +static IIO_DEV_ATTR_APPARENT_POWER_A_GAIN(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_AVAGAIN); +static IIO_DEV_ATTR_APPARENT_POWER_B_GAIN(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_BVAGAIN); +static IIO_DEV_ATTR_APPARENT_POWER_C_GAIN(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_CVAGAIN); +static IIO_DEV_ATTR_ACTIVE_POWER_A_OFFSET(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_AWATTOS); +static IIO_DEV_ATTR_ACTIVE_POWER_B_OFFSET(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_BWATTOS); +static IIO_DEV_ATTR_ACTIVE_POWER_C_OFFSET(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_CWATTOS); +static IIO_DEV_ATTR_REACTIVE_POWER_A_GAIN(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_AVARGAIN); +static IIO_DEV_ATTR_REACTIVE_POWER_B_GAIN(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_BVARGAIN); +static IIO_DEV_ATTR_REACTIVE_POWER_C_GAIN(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_CVARGAIN); +static IIO_DEV_ATTR_REACTIVE_POWER_A_OFFSET(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_AVAROS); +static IIO_DEV_ATTR_REACTIVE_POWER_B_OFFSET(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_BVAROS); +static IIO_DEV_ATTR_REACTIVE_POWER_C_OFFSET(S_IWUSR | S_IRUGO, + ade7854_read_24bit, + ade7854_write_24bit, + ADE7854_CVAROS); +static IIO_DEV_ATTR_VPEAK(S_IWUSR | S_IRUGO, + ade7854_read_32bit, + ade7854_write_32bit, + ADE7854_VPEAK); +static IIO_DEV_ATTR_IPEAK(S_IWUSR | S_IRUGO, + ade7854_read_32bit, + ade7854_write_32bit, + ADE7854_VPEAK); +static IIO_DEV_ATTR_APHCAL(S_IWUSR | S_IRUGO, + ade7854_read_16bit, + ade7854_write_16bit, + ADE7854_APHCAL); +static IIO_DEV_ATTR_BPHCAL(S_IWUSR | S_IRUGO, + ade7854_read_16bit, + ade7854_write_16bit, + ADE7854_BPHCAL); +static IIO_DEV_ATTR_CPHCAL(S_IWUSR | S_IRUGO, + ade7854_read_16bit, + ade7854_write_16bit, + ADE7854_CPHCAL); +static IIO_DEV_ATTR_CF1DEN(S_IWUSR | S_IRUGO, + ade7854_read_16bit, + ade7854_write_16bit, + ADE7854_CF1DEN); +static IIO_DEV_ATTR_CF2DEN(S_IWUSR | S_IRUGO, + ade7854_read_16bit, + ade7854_write_16bit, + ADE7854_CF2DEN); +static IIO_DEV_ATTR_CF3DEN(S_IWUSR | S_IRUGO, + ade7854_read_16bit, + ade7854_write_16bit, + ADE7854_CF3DEN); +static IIO_DEV_ATTR_LINECYC(S_IWUSR | S_IRUGO, + ade7854_read_16bit, + ade7854_write_16bit, + ADE7854_LINECYC); +static IIO_DEV_ATTR_SAGCYC(S_IWUSR | S_IRUGO, + ade7854_read_8bit, + ade7854_write_8bit, + ADE7854_SAGCYC); +static IIO_DEV_ATTR_CFCYC(S_IWUSR | S_IRUGO, + ade7854_read_8bit, + ade7854_write_8bit, + ADE7854_CFCYC); +static IIO_DEV_ATTR_PEAKCYC(S_IWUSR | S_IRUGO, + ade7854_read_8bit, + ade7854_write_8bit, + ADE7854_PEAKCYC); +static IIO_DEV_ATTR_CHKSUM(ade7854_read_24bit, + ADE7854_CHECKSUM); +static IIO_DEV_ATTR_ANGLE0(ade7854_read_24bit, + ADE7854_ANGLE0); +static IIO_DEV_ATTR_ANGLE1(ade7854_read_24bit, + ADE7854_ANGLE1); +static IIO_DEV_ATTR_ANGLE2(ade7854_read_24bit, + ADE7854_ANGLE2); +static IIO_DEV_ATTR_AIRMS(S_IRUGO, + ade7854_read_24bit, + NULL, + ADE7854_AIRMS); +static IIO_DEV_ATTR_BIRMS(S_IRUGO, + ade7854_read_24bit, + NULL, + ADE7854_BIRMS); +static IIO_DEV_ATTR_CIRMS(S_IRUGO, + ade7854_read_24bit, + NULL, + ADE7854_CIRMS); +static IIO_DEV_ATTR_NIRMS(S_IRUGO, + ade7854_read_24bit, + NULL, + ADE7854_NIRMS); +static IIO_DEV_ATTR_AVRMS(S_IRUGO, + ade7854_read_24bit, + NULL, + ADE7854_AVRMS); +static IIO_DEV_ATTR_BVRMS(S_IRUGO, + ade7854_read_24bit, + NULL, + ADE7854_BVRMS); +static IIO_DEV_ATTR_CVRMS(S_IRUGO, + ade7854_read_24bit, + NULL, + ADE7854_CVRMS); +static IIO_DEV_ATTR_AIRMSOS(S_IRUGO, + ade7854_read_16bit, + ade7854_write_16bit, + ADE7854_AIRMSOS); +static IIO_DEV_ATTR_BIRMSOS(S_IRUGO, + ade7854_read_16bit, + ade7854_write_16bit, + ADE7854_BIRMSOS); +static IIO_DEV_ATTR_CIRMSOS(S_IRUGO, + ade7854_read_16bit, + ade7854_write_16bit, + ADE7854_CIRMSOS); +static IIO_DEV_ATTR_AVRMSOS(S_IRUGO, + ade7854_read_16bit, + ade7854_write_16bit, + ADE7854_AVRMSOS); +static IIO_DEV_ATTR_BVRMSOS(S_IRUGO, + ade7854_read_16bit, + ade7854_write_16bit, + ADE7854_BVRMSOS); +static IIO_DEV_ATTR_CVRMSOS(S_IRUGO, + ade7854_read_16bit, + ade7854_write_16bit, + ADE7854_CVRMSOS); +static IIO_DEV_ATTR_VOLT_A(ade7854_read_24bit, + ADE7854_VAWV); +static IIO_DEV_ATTR_VOLT_B(ade7854_read_24bit, + ADE7854_VBWV); +static IIO_DEV_ATTR_VOLT_C(ade7854_read_24bit, + ADE7854_VCWV); +static IIO_DEV_ATTR_CURRENT_A(ade7854_read_24bit, + ADE7854_IAWV); +static IIO_DEV_ATTR_CURRENT_B(ade7854_read_24bit, + ADE7854_IBWV); +static IIO_DEV_ATTR_CURRENT_C(ade7854_read_24bit, + ADE7854_ICWV); +static IIO_DEV_ATTR_AWATTHR(ade7854_read_32bit, + ADE7854_AWATTHR); +static IIO_DEV_ATTR_BWATTHR(ade7854_read_32bit, + ADE7854_BWATTHR); +static IIO_DEV_ATTR_CWATTHR(ade7854_read_32bit, + ADE7854_CWATTHR); +static IIO_DEV_ATTR_AFWATTHR(ade7854_read_32bit, + ADE7854_AFWATTHR); +static IIO_DEV_ATTR_BFWATTHR(ade7854_read_32bit, + ADE7854_BFWATTHR); +static IIO_DEV_ATTR_CFWATTHR(ade7854_read_32bit, + ADE7854_CFWATTHR); +static IIO_DEV_ATTR_AVARHR(ade7854_read_32bit, + ADE7854_AVARHR); +static IIO_DEV_ATTR_BVARHR(ade7854_read_32bit, + ADE7854_BVARHR); +static IIO_DEV_ATTR_CVARHR(ade7854_read_32bit, + ADE7854_CVARHR); +static IIO_DEV_ATTR_AVAHR(ade7854_read_32bit, + ADE7854_AVAHR); +static IIO_DEV_ATTR_BVAHR(ade7854_read_32bit, + ADE7854_BVAHR); +static IIO_DEV_ATTR_CVAHR(ade7854_read_32bit, + ADE7854_CVAHR); + +static int ade7854_set_irq(struct device *dev, bool enable) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ade7854_state *st = iio_dev_get_devdata(indio_dev); + + int ret; + u32 irqen; + + ret = st->read_reg_32(dev, ADE7854_MASK0, &irqen); + if (ret) + goto error_ret; + + if (enable) + irqen |= 1 << 17; /* 1: interrupt enabled when all periodical + (at 8 kHz rate) DSP computations finish. */ + else + irqen &= ~(1 << 17); + + ret = st->write_reg_32(dev, ADE7854_MASK0, irqen); + if (ret) + goto error_ret; + +error_ret: + return ret; +} + +static int ade7854_initial_setup(struct ade7854_state *st) +{ + int ret; + struct device *dev = &st->indio_dev->dev; + + /* Disable IRQ */ + ret = ade7854_set_irq(dev, false); + if (ret) { + dev_err(dev, "disable irq failed"); + goto err_ret; + } + + ade7854_reset(dev); + msleep(ADE7854_STARTUP_DELAY); + +err_ret: + return ret; +} + +static IIO_DEV_ATTR_RESET(ade7854_write_reset); + +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("8000"); + +static IIO_CONST_ATTR(name, "ade7854"); + +static struct attribute *ade7854_event_attributes[] = { + NULL +}; + +static struct attribute_group ade7854_event_attribute_group = { + .attrs = ade7854_event_attributes, +}; + +static struct attribute *ade7854_attributes[] = { + &iio_dev_attr_aigain.dev_attr.attr, + &iio_dev_attr_bigain.dev_attr.attr, + &iio_dev_attr_cigain.dev_attr.attr, + &iio_dev_attr_nigain.dev_attr.attr, + &iio_dev_attr_avgain.dev_attr.attr, + &iio_dev_attr_bvgain.dev_attr.attr, + &iio_dev_attr_cvgain.dev_attr.attr, + &iio_dev_attr_linecyc.dev_attr.attr, + &iio_dev_attr_sagcyc.dev_attr.attr, + &iio_dev_attr_cfcyc.dev_attr.attr, + &iio_dev_attr_peakcyc.dev_attr.attr, + &iio_dev_attr_chksum.dev_attr.attr, + &iio_dev_attr_apparent_power_a_gain.dev_attr.attr, + &iio_dev_attr_apparent_power_b_gain.dev_attr.attr, + &iio_dev_attr_apparent_power_c_gain.dev_attr.attr, + &iio_dev_attr_active_power_a_offset.dev_attr.attr, + &iio_dev_attr_active_power_b_offset.dev_attr.attr, + &iio_dev_attr_active_power_c_offset.dev_attr.attr, + &iio_dev_attr_reactive_power_a_gain.dev_attr.attr, + &iio_dev_attr_reactive_power_b_gain.dev_attr.attr, + &iio_dev_attr_reactive_power_c_gain.dev_attr.attr, + &iio_dev_attr_reactive_power_a_offset.dev_attr.attr, + &iio_dev_attr_reactive_power_b_offset.dev_attr.attr, + &iio_dev_attr_reactive_power_c_offset.dev_attr.attr, + &iio_dev_attr_awatthr.dev_attr.attr, + &iio_dev_attr_bwatthr.dev_attr.attr, + &iio_dev_attr_cwatthr.dev_attr.attr, + &iio_dev_attr_afwatthr.dev_attr.attr, + &iio_dev_attr_bfwatthr.dev_attr.attr, + &iio_dev_attr_cfwatthr.dev_attr.attr, + &iio_dev_attr_avarhr.dev_attr.attr, + &iio_dev_attr_bvarhr.dev_attr.attr, + &iio_dev_attr_cvarhr.dev_attr.attr, + &iio_dev_attr_angle0.dev_attr.attr, + &iio_dev_attr_angle1.dev_attr.attr, + &iio_dev_attr_angle2.dev_attr.attr, + &iio_dev_attr_avahr.dev_attr.attr, + &iio_dev_attr_bvahr.dev_attr.attr, + &iio_dev_attr_cvahr.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + &iio_dev_attr_reset.dev_attr.attr, + &iio_const_attr_name.dev_attr.attr, + &iio_dev_attr_vpeak.dev_attr.attr, + &iio_dev_attr_ipeak.dev_attr.attr, + &iio_dev_attr_aphcal.dev_attr.attr, + &iio_dev_attr_bphcal.dev_attr.attr, + &iio_dev_attr_cphcal.dev_attr.attr, + &iio_dev_attr_cf1den.dev_attr.attr, + &iio_dev_attr_cf2den.dev_attr.attr, + &iio_dev_attr_cf3den.dev_attr.attr, + &iio_dev_attr_airms.dev_attr.attr, + &iio_dev_attr_birms.dev_attr.attr, + &iio_dev_attr_cirms.dev_attr.attr, + &iio_dev_attr_nirms.dev_attr.attr, + &iio_dev_attr_avrms.dev_attr.attr, + &iio_dev_attr_bvrms.dev_attr.attr, + &iio_dev_attr_cvrms.dev_attr.attr, + &iio_dev_attr_airmsos.dev_attr.attr, + &iio_dev_attr_birmsos.dev_attr.attr, + &iio_dev_attr_cirmsos.dev_attr.attr, + &iio_dev_attr_avrmsos.dev_attr.attr, + &iio_dev_attr_bvrmsos.dev_attr.attr, + &iio_dev_attr_cvrmsos.dev_attr.attr, + &iio_dev_attr_volt_a.dev_attr.attr, + &iio_dev_attr_volt_b.dev_attr.attr, + &iio_dev_attr_volt_c.dev_attr.attr, + &iio_dev_attr_current_a.dev_attr.attr, + &iio_dev_attr_current_b.dev_attr.attr, + &iio_dev_attr_current_c.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ade7854_attribute_group = { + .attrs = ade7854_attributes, +}; + +int ade7854_probe(struct ade7854_state *st, struct device *dev) +{ + int ret, regdone = 0; + + /* Allocate the comms buffers */ + st->rx = kzalloc(sizeof(*st->rx)*ADE7854_MAX_RX, GFP_KERNEL); + if (st->rx == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->tx = kzalloc(sizeof(*st->tx)*ADE7854_MAX_TX, GFP_KERNEL); + if (st->tx == NULL) { + ret = -ENOMEM; + goto error_free_rx; + } + mutex_init(&st->buf_lock); + /* setup the industrialio driver allocated elements */ + st->indio_dev = iio_allocate_device(); + if (st->indio_dev == NULL) { + ret = -ENOMEM; + goto error_free_tx; + } + + st->indio_dev->dev.parent = dev; + st->indio_dev->num_interrupt_lines = 1; + st->indio_dev->event_attrs = &ade7854_event_attribute_group; + st->indio_dev->attrs = &ade7854_attribute_group; + st->indio_dev->dev_data = (void *)(st); + st->indio_dev->driver_module = THIS_MODULE; + st->indio_dev->modes = INDIO_DIRECT_MODE; + + ret = ade7854_configure_ring(st->indio_dev); + if (ret) + goto error_free_dev; + + ret = iio_device_register(st->indio_dev); + if (ret) + goto error_unreg_ring_funcs; + regdone = 1; + + ret = ade7854_initialize_ring(st->indio_dev->ring); + if (ret) { + printk(KERN_ERR "failed to initialize the ring\n"); + goto error_unreg_ring_funcs; + } + + if (st->irq) { + ret = iio_register_interrupt_line(st->irq, + st->indio_dev, + 0, + IRQF_TRIGGER_FALLING, + "ade7854"); + if (ret) + goto error_uninitialize_ring; + + ret = ade7854_probe_trigger(st->indio_dev); + if (ret) + goto error_unregister_line; + } + /* Get the device into a sane initial state */ + ret = ade7854_initial_setup(st); + if (ret) + goto error_remove_trigger; + + return 0; + +error_remove_trigger: + if (st->indio_dev->modes & INDIO_RING_TRIGGERED) + ade7854_remove_trigger(st->indio_dev); +error_unregister_line: + if (st->indio_dev->modes & INDIO_RING_TRIGGERED) + iio_unregister_interrupt_line(st->indio_dev, 0); +error_uninitialize_ring: + ade7854_uninitialize_ring(st->indio_dev->ring); +error_unreg_ring_funcs: + ade7854_unconfigure_ring(st->indio_dev); +error_free_dev: + if (regdone) + iio_device_unregister(st->indio_dev); + else + iio_free_device(st->indio_dev); +error_free_tx: + kfree(st->tx); +error_free_rx: + kfree(st->rx); +error_free_st: + kfree(st); + return ret; + +} +EXPORT_SYMBOL(ade7854_probe); + +int ade7854_remove(struct ade7854_state *st) +{ + struct iio_dev *indio_dev = st->indio_dev; + + flush_scheduled_work(); + + ade7854_remove_trigger(indio_dev); + if (st->irq) + iio_unregister_interrupt_line(indio_dev, 0); + + ade7854_uninitialize_ring(indio_dev->ring); + ade7854_unconfigure_ring(indio_dev); + iio_device_unregister(indio_dev); + kfree(st->tx); + kfree(st->rx); + kfree(st); + + return 0; +} +EXPORT_SYMBOL(ade7854_remove); + +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/meter/ade7854.h b/trunk/drivers/staging/iio/meter/ade7854.h new file mode 100644 index 000000000000..47690e521ec1 --- /dev/null +++ b/trunk/drivers/staging/iio/meter/ade7854.h @@ -0,0 +1,245 @@ +#ifndef _ADE7854_H +#define _ADE7854_H + +#define ADE7854_AIGAIN 0x4380 +#define ADE7854_AVGAIN 0x4381 +#define ADE7854_BIGAIN 0x4382 +#define ADE7854_BVGAIN 0x4383 +#define ADE7854_CIGAIN 0x4384 +#define ADE7854_CVGAIN 0x4385 +#define ADE7854_NIGAIN 0x4386 +#define ADE7854_AIRMSOS 0x4387 +#define ADE7854_AVRMSOS 0x4388 +#define ADE7854_BIRMSOS 0x4389 +#define ADE7854_BVRMSOS 0x438A +#define ADE7854_CIRMSOS 0x438B +#define ADE7854_CVRMSOS 0x438C +#define ADE7854_NIRMSOS 0x438D +#define ADE7854_AVAGAIN 0x438E +#define ADE7854_BVAGAIN 0x438F +#define ADE7854_CVAGAIN 0x4390 +#define ADE7854_AWGAIN 0x4391 +#define ADE7854_AWATTOS 0x4392 +#define ADE7854_BWGAIN 0x4393 +#define ADE7854_BWATTOS 0x4394 +#define ADE7854_CWGAIN 0x4395 +#define ADE7854_CWATTOS 0x4396 +#define ADE7854_AVARGAIN 0x4397 +#define ADE7854_AVAROS 0x4398 +#define ADE7854_BVARGAIN 0x4399 +#define ADE7854_BVAROS 0x439A +#define ADE7854_CVARGAIN 0x439B +#define ADE7854_CVAROS 0x439C +#define ADE7854_AFWGAIN 0x439D +#define ADE7854_AFWATTOS 0x439E +#define ADE7854_BFWGAIN 0x439F +#define ADE7854_BFWATTOS 0x43A0 +#define ADE7854_CFWGAIN 0x43A1 +#define ADE7854_CFWATTOS 0x43A2 +#define ADE7854_AFVARGAIN 0x43A3 +#define ADE7854_AFVAROS 0x43A4 +#define ADE7854_BFVARGAIN 0x43A5 +#define ADE7854_BFVAROS 0x43A6 +#define ADE7854_CFVARGAIN 0x43A7 +#define ADE7854_CFVAROS 0x43A8 +#define ADE7854_VATHR1 0x43A9 +#define ADE7854_VATHR0 0x43AA +#define ADE7854_WTHR1 0x43AB +#define ADE7854_WTHR0 0x43AC +#define ADE7854_VARTHR1 0x43AD +#define ADE7854_VARTHR0 0x43AE +#define ADE7854_RSV 0x43AF +#define ADE7854_VANOLOAD 0x43B0 +#define ADE7854_APNOLOAD 0x43B1 +#define ADE7854_VARNOLOAD 0x43B2 +#define ADE7854_VLEVEL 0x43B3 +#define ADE7854_DICOEFF 0x43B5 +#define ADE7854_HPFDIS 0x43B6 +#define ADE7854_ISUMLVL 0x43B8 +#define ADE7854_ISUM 0x43BF +#define ADE7854_AIRMS 0x43C0 +#define ADE7854_AVRMS 0x43C1 +#define ADE7854_BIRMS 0x43C2 +#define ADE7854_BVRMS 0x43C3 +#define ADE7854_CIRMS 0x43C4 +#define ADE7854_CVRMS 0x43C5 +#define ADE7854_NIRMS 0x43C6 +#define ADE7854_RUN 0xE228 +#define ADE7854_AWATTHR 0xE400 +#define ADE7854_BWATTHR 0xE401 +#define ADE7854_CWATTHR 0xE402 +#define ADE7854_AFWATTHR 0xE403 +#define ADE7854_BFWATTHR 0xE404 +#define ADE7854_CFWATTHR 0xE405 +#define ADE7854_AVARHR 0xE406 +#define ADE7854_BVARHR 0xE407 +#define ADE7854_CVARHR 0xE408 +#define ADE7854_AFVARHR 0xE409 +#define ADE7854_BFVARHR 0xE40A +#define ADE7854_CFVARHR 0xE40B +#define ADE7854_AVAHR 0xE40C +#define ADE7854_BVAHR 0xE40D +#define ADE7854_CVAHR 0xE40E +#define ADE7854_IPEAK 0xE500 +#define ADE7854_VPEAK 0xE501 +#define ADE7854_STATUS0 0xE502 +#define ADE7854_STATUS1 0xE503 +#define ADE7854_OILVL 0xE507 +#define ADE7854_OVLVL 0xE508 +#define ADE7854_SAGLVL 0xE509 +#define ADE7854_MASK0 0xE50A +#define ADE7854_MASK1 0xE50B +#define ADE7854_IAWV 0xE50C +#define ADE7854_IBWV 0xE50D +#define ADE7854_ICWV 0xE50E +#define ADE7854_VAWV 0xE510 +#define ADE7854_VBWV 0xE511 +#define ADE7854_VCWV 0xE512 +#define ADE7854_AWATT 0xE513 +#define ADE7854_BWATT 0xE514 +#define ADE7854_CWATT 0xE515 +#define ADE7854_AVA 0xE519 +#define ADE7854_BVA 0xE51A +#define ADE7854_CVA 0xE51B +#define ADE7854_CHECKSUM 0xE51F +#define ADE7854_VNOM 0xE520 +#define ADE7854_PHSTATUS 0xE600 +#define ADE7854_ANGLE0 0xE601 +#define ADE7854_ANGLE1 0xE602 +#define ADE7854_ANGLE2 0xE603 +#define ADE7854_PERIOD 0xE607 +#define ADE7854_PHNOLOAD 0xE608 +#define ADE7854_LINECYC 0xE60C +#define ADE7854_ZXTOUT 0xE60D +#define ADE7854_COMPMODE 0xE60E +#define ADE7854_GAIN 0xE60F +#define ADE7854_CFMODE 0xE610 +#define ADE7854_CF1DEN 0xE611 +#define ADE7854_CF2DEN 0xE612 +#define ADE7854_CF3DEN 0xE613 +#define ADE7854_APHCAL 0xE614 +#define ADE7854_BPHCAL 0xE615 +#define ADE7854_CPHCAL 0xE616 +#define ADE7854_PHSIGN 0xE617 +#define ADE7854_CONFIG 0xE618 +#define ADE7854_MMODE 0xE700 +#define ADE7854_ACCMODE 0xE701 +#define ADE7854_LCYCMODE 0xE702 +#define ADE7854_PEAKCYC 0xE703 +#define ADE7854_SAGCYC 0xE704 +#define ADE7854_CFCYC 0xE705 +#define ADE7854_HSDC_CFG 0xE706 +#define ADE7854_CONFIG2 0xEC01 + +#define ADE7854_READ_REG 0x1 +#define ADE7854_WRITE_REG 0x0 + +#define ADE7854_MAX_TX 7 +#define ADE7854_MAX_RX 7 +#define ADE7854_STARTUP_DELAY 1 + +#define ADE7854_SPI_SLOW (u32)(300 * 1000) +#define ADE7854_SPI_BURST (u32)(1000 * 1000) +#define ADE7854_SPI_FAST (u32)(2000 * 1000) + +#define DRIVER_NAME "ade7854" + +/** + * struct ade7854_state - device instance specific data + * @spi: actual spi_device + * @work_trigger_to_ring: bh for triggered event handling + * @inter: used to check if new interrupt has been triggered + * @last_timestamp: passing timestamp from th to bh of interrupt handler + * @indio_dev: industrial I/O device structure + * @trig: data ready trigger registered with iio + * @tx: transmit buffer + * @rx: recieve buffer + * @buf_lock: mutex to protect tx and rx + **/ +struct ade7854_state { + struct spi_device *spi; + struct i2c_client *i2c; + struct work_struct work_trigger_to_ring; + s64 last_timestamp; + struct iio_dev *indio_dev; + struct iio_trigger *trig; + u8 *tx; + u8 *rx; + int (*read_reg_8) (struct device *, u16, u8 *); + int (*read_reg_16) (struct device *, u16, u16 *); + int (*read_reg_24) (struct device *, u16, u32 *); + int (*read_reg_32) (struct device *, u16, u32 *); + int (*write_reg_8) (struct device *, u16, u8); + int (*write_reg_16) (struct device *, u16, u16); + int (*write_reg_24) (struct device *, u16, u32); + int (*write_reg_32) (struct device *, u16, u32); + int irq; + struct mutex buf_lock; +}; + +extern int ade7854_probe(struct ade7854_state *st, struct device *dev); +extern int ade7854_remove(struct ade7854_state *st); + +#if defined(CONFIG_IIO_RING_BUFFER) && defined(THIS_HAS_RING_BUFFER_SUPPORT) +/* At the moment triggers are only used for ring buffer + * filling. This may change! + */ + +enum ade7854_scan { + ADE7854_SCAN_PHA_V, + ADE7854_SCAN_PHB_V, + ADE7854_SCAN_PHC_V, + ADE7854_SCAN_PHA_I, + ADE7854_SCAN_PHB_I, + ADE7854_SCAN_PHC_I, +}; + +void ade7854_remove_trigger(struct iio_dev *indio_dev); +int ade7854_probe_trigger(struct iio_dev *indio_dev); + +ssize_t ade7854_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf); + + +int ade7854_configure_ring(struct iio_dev *indio_dev); +void ade7854_unconfigure_ring(struct iio_dev *indio_dev); + +int ade7854_initialize_ring(struct iio_ring_buffer *ring); +void ade7854_uninitialize_ring(struct iio_ring_buffer *ring); +#else /* CONFIG_IIO_RING_BUFFER */ + +static inline void ade7854_remove_trigger(struct iio_dev *indio_dev) +{ +} +static inline int ade7854_probe_trigger(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline ssize_t +ade7854_read_data_from_ring(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return 0; +} + +static inline int ade7854_configure_ring(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline void ade7854_unconfigure_ring(struct iio_dev *indio_dev) +{ +} +static inline int ade7854_initialize_ring(struct iio_ring_buffer *ring) +{ + return 0; +} +static inline void ade7854_uninitialize_ring(struct iio_ring_buffer *ring) +{ +} +#endif /* CONFIG_IIO_RING_BUFFER */ + +#endif diff --git a/trunk/drivers/staging/iio/meter/meter.h b/trunk/drivers/staging/iio/meter/meter.h new file mode 100644 index 000000000000..142c50d71fda --- /dev/null +++ b/trunk/drivers/staging/iio/meter/meter.h @@ -0,0 +1,396 @@ +#include "../sysfs.h" + +/* metering ic types of attribute */ + +#define IIO_DEV_ATTR_CURRENT_A_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(current_a_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CURRENT_B_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(current_b_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CURRENT_C_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(current_c_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_VOLT_A_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(volt_a_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_VOLT_B_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(volt_b_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_VOLT_C_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(volt_c_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_REACTIVE_POWER_A_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(reactive_power_a_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_REACTIVE_POWER_B_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(reactive_power_b_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_REACTIVE_POWER_C_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(reactive_power_c_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACTIVE_POWER_A_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(active_power_a_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACTIVE_POWER_B_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(active_power_b_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACTIVE_POWER_C_OFFSET(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(active_power_c_offset, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CURRENT_A_GAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(current_a_gain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CURRENT_B_GAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(current_b_gain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CURRENT_C_GAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(current_c_gain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_APPARENT_POWER_A_GAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(apparent_power_a_gain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_APPARENT_POWER_B_GAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(apparent_power_b_gain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_APPARENT_POWER_C_GAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(apparent_power_c_gain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACTIVE_POWER_GAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(active_power_gain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACTIVE_POWER_A_GAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(active_power_a_gain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACTIVE_POWER_B_GAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(active_power_b_gain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_ACTIVE_POWER_C_GAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(active_power_c_gain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_REACTIVE_POWER_A_GAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(reactive_power_a_gain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_REACTIVE_POWER_B_GAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(reactive_power_b_gain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_REACTIVE_POWER_C_GAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(reactive_power_c_gain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CURRENT_A(_show, _addr) \ + IIO_DEVICE_ATTR(current_a, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_CURRENT_B(_show, _addr) \ + IIO_DEVICE_ATTR(current_b, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_CURRENT_C(_show, _addr) \ + IIO_DEVICE_ATTR(current_c, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_VOLT_A(_show, _addr) \ + IIO_DEVICE_ATTR(volt_a, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_VOLT_B(_show, _addr) \ + IIO_DEVICE_ATTR(volt_b, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_VOLT_C(_show, _addr) \ + IIO_DEVICE_ATTR(volt_c, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_AENERGY(_show, _addr) \ + IIO_DEVICE_ATTR(aenergy, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_LENERGY(_show, _addr) \ + IIO_DEVICE_ATTR(lenergy, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_RAENERGY(_show, _addr) \ + IIO_DEVICE_ATTR(raenergy, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_LAENERGY(_show, _addr) \ + IIO_DEVICE_ATTR(laenergy, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_VAENERGY(_show, _addr) \ + IIO_DEVICE_ATTR(vaenergy, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_LVAENERGY(_show, _addr) \ + IIO_DEVICE_ATTR(lvaenergy, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_RVAENERGY(_show, _addr) \ + IIO_DEVICE_ATTR(rvaenergy, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_LVARENERGY(_show, _addr) \ + IIO_DEVICE_ATTR(lvarenergy, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_CHKSUM(_show, _addr) \ + IIO_DEVICE_ATTR(chksum, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ANGLE0(_show, _addr) \ + IIO_DEVICE_ATTR(angle0, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ANGLE1(_show, _addr) \ + IIO_DEVICE_ATTR(angle1, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_ANGLE2(_show, _addr) \ + IIO_DEVICE_ATTR(angle2, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_AWATTHR(_show, _addr) \ + IIO_DEVICE_ATTR(awatthr, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_BWATTHR(_show, _addr) \ + IIO_DEVICE_ATTR(bwatthr, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_CWATTHR(_show, _addr) \ + IIO_DEVICE_ATTR(cwatthr, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_AFWATTHR(_show, _addr) \ + IIO_DEVICE_ATTR(afwatthr, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_BFWATTHR(_show, _addr) \ + IIO_DEVICE_ATTR(bfwatthr, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_CFWATTHR(_show, _addr) \ + IIO_DEVICE_ATTR(cfwatthr, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_AVARHR(_show, _addr) \ + IIO_DEVICE_ATTR(avarhr, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_BVARHR(_show, _addr) \ + IIO_DEVICE_ATTR(bvarhr, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_CVARHR(_show, _addr) \ + IIO_DEVICE_ATTR(cvarhr, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_AVAHR(_show, _addr) \ + IIO_DEVICE_ATTR(avahr, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_BVAHR(_show, _addr) \ + IIO_DEVICE_ATTR(bvahr, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_CVAHR(_show, _addr) \ + IIO_DEVICE_ATTR(cvahr, S_IRUGO, _show, NULL, _addr) + +#define IIO_DEV_ATTR_IOS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(ios, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_VOS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(vos, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_PHCAL(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(phcal, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_APHCAL(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(aphcal, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_BPHCAL(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(bphcal, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CPHCAL(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(cphcal, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_APOS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(apos, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_AAPOS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(aapos, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_BAPOS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(bapos, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CAPOS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(capos, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_AVRMSGAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(avrmsgain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_BVRMSGAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(bvrmsgain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CVRMSGAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(cvrmsgain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_AIGAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(aigain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_BIGAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(bigain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CIGAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(cigain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_NIGAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(nigain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_AVGAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(avgain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_BVGAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(bvgain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CVGAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(cvgain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_WGAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(wgain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_WDIV(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(wdiv, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CFNUM(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(cfnum, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CFDEN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(cfden, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CF1DEN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(cf1den, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CF2DEN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(cf2den, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CF3DEN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(cf3den, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_IRMS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(irms, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_VRMS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(vrms, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_AIRMS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(airms, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_BIRMS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(birms, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CIRMS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(cirms, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_NIRMS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(nirms, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_AVRMS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(avrms, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_BVRMS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(bvrms, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CVRMS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(cvrms, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_IRMSOS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(irmsos, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_VRMSOS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(vrmsos, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_AIRMSOS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(airmsos, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_BIRMSOS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(birmsos, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CIRMSOS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(cirmsos, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_AVRMSOS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(avrmsos, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_BVRMSOS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(bvrmsos, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CVRMSOS(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(cvrmsos, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_VAGAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(vagain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_PGA_GAIN(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(pga_gain, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_VADIV(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(vadiv, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_LINECYC(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(linecyc, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_SAGCYC(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(sagcyc, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CFCYC(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(cfcyc, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_PEAKCYC(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(peakcyc, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_SAGLVL(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(saglvl, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_IPKLVL(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(ipklvl, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_VPKLVL(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(vpklvl, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_IPEAK(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(ipeak, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_RIPEAK(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(ripeak, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_VPEAK(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(vpeak, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_RVPEAK(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(rvpeak, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_VPERIOD(_mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(vperiod, _mode, _show, _store, _addr) + +#define IIO_DEV_ATTR_CH_OFF(_num, _mode, _show, _store, _addr) \ + IIO_DEVICE_ATTR(choff_##_num, _mode, _show, _store, _addr) + +/* active energy register, AENERGY, is more than half full */ +#define IIO_EVENT_ATTR_AENERGY_HALF_FULL(_evlist, _show, _store, _mask) \ + IIO_EVENT_ATTR_SH(aenergy_half_full, _evlist, _show, _store, _mask) + +/* a SAG on the line voltage */ +#define IIO_EVENT_ATTR_LINE_VOLT_SAG(_evlist, _show, _store, _mask) \ + IIO_EVENT_ATTR_SH(line_volt_sag, _evlist, _show, _store, _mask) + +/* + * Indicates the end of energy accumulation over an integer number + * of half line cycles + */ +#define IIO_EVENT_ATTR_CYCEND(_evlist, _show, _store, _mask) \ + IIO_EVENT_ATTR_SH(cycend, _evlist, _show, _store, _mask) + +/* on the rising and falling edge of the the voltage waveform */ +#define IIO_EVENT_ATTR_ZERO_CROSS(_evlist, _show, _store, _mask) \ + IIO_EVENT_ATTR_SH(zero_cross, _evlist, _show, _store, _mask) + +/* the active energy register has overflowed */ +#define IIO_EVENT_ATTR_AENERGY_OVERFLOW(_evlist, _show, _store, _mask) \ + IIO_EVENT_ATTR_SH(aenergy_overflow, _evlist, _show, _store, _mask) + +/* the apparent energy register has overflowed */ +#define IIO_EVENT_ATTR_VAENERGY_OVERFLOW(_evlist, _show, _store, _mask) \ + IIO_EVENT_ATTR_SH(vaenergy_overflow, _evlist, _show, _store, _mask) + +/* the active energy register, VAENERGY, is more than half full */ +#define IIO_EVENT_ATTR_VAENERGY_HALF_FULL(_evlist, _show, _store, _mask) \ + IIO_EVENT_ATTR_SH(vaenergy_half_full, _evlist, _show, _store, _mask) + +/* the power has gone from negative to positive */ +#define IIO_EVENT_ATTR_PPOS(_evlist, _show, _store, _mask) \ + IIO_EVENT_ATTR_SH(ppos, _evlist, _show, _store, _mask) + +/* the power has gone from positive to negative */ +#define IIO_EVENT_ATTR_PNEG(_evlist, _show, _store, _mask) \ + IIO_EVENT_ATTR_SH(pneg, _evlist, _show, _store, _mask) + +/* waveform sample from Channel 1 has exceeded the IPKLVL value */ +#define IIO_EVENT_ATTR_IPKLVL_EXC(_evlist, _show, _store, _mask) \ + IIO_EVENT_ATTR_SH(ipklvl_exc, _evlist, _show, _store, _mask) + +/* waveform sample from Channel 2 has exceeded the VPKLVL value */ +#define IIO_EVENT_ATTR_VPKLVL_EXC(_evlist, _show, _store, _mask) \ + IIO_EVENT_ATTR_SH(vpklvl_exc, _evlist, _show, _store, _mask) + diff --git a/trunk/drivers/staging/iio/resolver/Kconfig b/trunk/drivers/staging/iio/resolver/Kconfig new file mode 100644 index 000000000000..a4a363429355 --- /dev/null +++ b/trunk/drivers/staging/iio/resolver/Kconfig @@ -0,0 +1,54 @@ +# +# Resolver/Synchro drivers +# +comment "Resolver to digital converters" + +config AD2S90 + tristate "Analog Devices ad2s90 driver" + depends on SPI + help + Say yes here to build support for Analog Devices spi resolver + to digital converters, ad2s90, provides direct access via sysfs. + +config AD2S120X + tristate "Analog Devices ad2s120x driver" + depends on SPI + help + Say yes here to build support for Analog Devices spi resolver + to digital converters, ad2s1200 and ad2s1205, provides direct access + via sysfs. + +config AD2S1210 + tristate "Analog Devices ad2s1210 driver" + depends on SPI + help + Say yes here to build support for Analog Devices spi resolver + to digital converters, ad2s1210, provides direct access via sysfs. + +choice + prompt "Resolution Control" + depends on AD2S1210 + default AD2S1210_GPIO_NONE + help + In normal mode, the resolution of the digital output is selected + using the RES0 and RES1 input pins. In configuration mode, the + resolution is selected by setting the RES0 and RES1 bits in the + control regsiter. When switching between normal mode and configuration + mode, there are some schemes to keep them matchs. + +config AD2S1210_GPIO_INPUT + bool "read resolution from gpio pins" + help + GPIO pins are sampling RES0 and RES1 pins, read the resolution + settings from the GPIO pins. + +config AD2S1210_GPIO_OUTPUT + bool "set gpio pins to set resolution" + help + RES0 and RES1 pins are controlled by GPIOs, setting GPIO pins to + set the resolution. + +config AD2S1210_GPIO_NONE + bool "take the responsibility by user" + +endchoice diff --git a/trunk/drivers/staging/iio/resolver/Makefile b/trunk/drivers/staging/iio/resolver/Makefile new file mode 100644 index 000000000000..0b84a89e6cac --- /dev/null +++ b/trunk/drivers/staging/iio/resolver/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for Resolver/Synchro drivers +# + +obj-$(CONFIG_AD2S90) += ad2s90.o +obj-$(CONFIG_AD2S120X) += ad2s120x.o +obj-$(CONFIG_AD2S1210) += ad2s1210.o diff --git a/trunk/drivers/staging/iio/resolver/ad2s120x.c b/trunk/drivers/staging/iio/resolver/ad2s120x.c new file mode 100644 index 000000000000..8f497a23976c --- /dev/null +++ b/trunk/drivers/staging/iio/resolver/ad2s120x.c @@ -0,0 +1,310 @@ +/* + * ad2s120x.c simple support for the ADI Resolver to Digital Converters: AD2S1200/1205 + * + * Copyright (c) 2010-2010 Analog Devices Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +#define DRV_NAME "ad2s120x" + +/* input pin sample and rdvel is controlled by driver */ +#define AD2S120X_PN 2 + +/* input clock on serial interface */ +#define AD2S120X_HZ 8192000 +/* clock period in nano second */ +#define AD2S120X_TSCLK (1000000000/AD2S120X_HZ) + +struct ad2s120x_state { + struct mutex lock; + struct iio_dev *idev; + struct spi_device *sdev; + unsigned short sample; + unsigned short rdvel; + u8 rx[2]; + u8 tx[2]; +}; + +static ssize_t ad2s120x_show_pos_vel(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct spi_message msg; + struct spi_transfer xfer; + int ret = 0; + ssize_t len = 0; + u16 pos; + s16 vel; + u8 status; + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s120x_state *st = idev->dev_data; + + xfer.len = 1; + xfer.tx_buf = st->tx; + xfer.rx_buf = st->rx; + mutex_lock(&st->lock); + + gpio_set_value(st->sample, 0); + /* delay (6 * AD2S120X_TSCLK + 20) nano seconds */ + udelay(1); + gpio_set_value(st->sample, 1); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + status = st->rx[1]; + pos = (((u16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4); + len = sprintf(buf, "%d %c%c%c%c ", pos, + (status & 0x8) ? 'P' : 'V', + (status & 0x4) ? 'd' : '_', + (status & 0x2) ? 'l' : '_', + (status & 0x1) ? '1' : '0'); + + /* delay 18 ns */ + /* ndelay(18); */ + + gpio_set_value(st->rdvel, 0); + /* ndelay(5);*/ + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + status = st->rx[1]; + vel = (st->rx[0] & 0x80) ? 0xf000 : 0; + vel |= (((s16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4); + len += sprintf(buf + len, "%d %c%c%c%c\n", vel, + (status & 0x8) ? 'P' : 'V', + (status & 0x4) ? 'd' : '_', + (status & 0x2) ? 'l' : '_', + (status & 0x1) ? '1' : '0'); +error_ret: + gpio_set_value(st->rdvel, 1); + /* delay (2 * AD2S120X_TSCLK + 20) ns for sample pulse */ + udelay(1); + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +static ssize_t ad2s120x_show_pos(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct spi_message msg; + struct spi_transfer xfer; + int ret = 0; + ssize_t len = 0; + u16 pos; + u8 status; + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s120x_state *st = idev->dev_data; + + xfer.len = 1; + xfer.tx_buf = st->tx; + xfer.rx_buf = st->rx; + mutex_lock(&st->lock); + + gpio_set_value(st->sample, 0); + /* delay (6 * AD2S120X_TSCLK + 20) nano seconds */ + udelay(1); + gpio_set_value(st->sample, 1); + gpio_set_value(st->rdvel, 1); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + status = st->rx[1]; + pos = (((u16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4); + len = sprintf(buf, "%d %c%c%c%c ", pos, + (status & 0x8) ? 'P' : 'V', + (status & 0x4) ? 'd' : '_', + (status & 0x2) ? 'l' : '_', + (status & 0x1) ? '1' : '0'); +error_ret: + /* delay (2 * AD2S120X_TSCLK + 20) ns for sample pulse */ + udelay(1); + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +static ssize_t ad2s120x_show_vel(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct spi_message msg; + struct spi_transfer xfer; + int ret = 0; + ssize_t len = 0; + s16 vel; + u8 status; + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s120x_state *st = idev->dev_data; + + xfer.len = 1; + xfer.tx_buf = st->tx; + xfer.rx_buf = st->rx; + mutex_lock(&st->lock); + + gpio_set_value(st->sample, 0); + /* delay (6 * AD2S120X_TSCLK + 20) nano seconds */ + udelay(1); + gpio_set_value(st->sample, 1); + + gpio_set_value(st->rdvel, 0); + /* ndelay(5);*/ + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + status = st->rx[1]; + vel = (st->rx[0] & 0x80) ? 0xf000 : 0; + vel |= (((s16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4); + len += sprintf(buf + len, "%d %c%c%c%c\n", vel, + (status & 0x8) ? 'P' : 'V', + (status & 0x4) ? 'd' : '_', + (status & 0x2) ? 'l' : '_', + (status & 0x1) ? '1' : '0'); +error_ret: + gpio_set_value(st->rdvel, 1); + /* delay (2 * AD2S120X_TSCLK + 20) ns for sample pulse */ + udelay(1); + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +static IIO_CONST_ATTR(description, + "12-Bit R/D Converter with Reference Oscillator"); +static IIO_DEVICE_ATTR(pos_vel, S_IRUGO, ad2s120x_show_pos_vel, NULL, 0); +static IIO_DEVICE_ATTR(pos, S_IRUGO, ad2s120x_show_pos, NULL, 0); +static IIO_DEVICE_ATTR(vel, S_IRUGO, ad2s120x_show_vel, NULL, 0); + +static struct attribute *ad2s120x_attributes[] = { + &iio_const_attr_description.dev_attr.attr, + &iio_dev_attr_pos_vel.dev_attr.attr, + &iio_dev_attr_pos.dev_attr.attr, + &iio_dev_attr_vel.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad2s120x_attribute_group = { + .name = DRV_NAME, + .attrs = ad2s120x_attributes, +}; + +static int __devinit ad2s120x_probe(struct spi_device *spi) +{ + struct ad2s120x_state *st; + int pn, ret = 0; + unsigned short *pins = spi->dev.platform_data; + + for (pn = 0; pn < AD2S120X_PN; pn++) { + if (gpio_request(pins[pn], DRV_NAME)) { + pr_err("%s: request gpio pin %d failed\n", + DRV_NAME, pins[pn]); + goto error_ret; + } + gpio_direction_output(pins[pn], 1); + } + + st = kzalloc(sizeof(*st), GFP_KERNEL); + if (st == NULL) { + ret = -ENOMEM; + goto error_ret; + } + spi_set_drvdata(spi, st); + + mutex_init(&st->lock); + st->sdev = spi; + st->sample = pins[0]; + st->rdvel = pins[1]; + + st->idev = iio_allocate_device(); + if (st->idev == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->idev->dev.parent = &spi->dev; + st->idev->num_interrupt_lines = 0; + st->idev->event_attrs = NULL; + + st->idev->attrs = &ad2s120x_attribute_group; + st->idev->dev_data = (void *)(st); + st->idev->driver_module = THIS_MODULE; + st->idev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(st->idev); + if (ret) + goto error_free_dev; + + spi->max_speed_hz = AD2S120X_HZ; + spi->mode = SPI_MODE_3; + spi_setup(spi); + + return 0; + +error_free_dev: + iio_free_device(st->idev); +error_free_st: + kfree(st); +error_ret: + for (--pn; pn >= 0; pn--) + gpio_free(pins[pn]); + return ret; +} + +static int __devexit ad2s120x_remove(struct spi_device *spi) +{ + struct ad2s120x_state *st = spi_get_drvdata(spi); + + iio_device_unregister(st->idev); + kfree(st); + + return 0; +} + +static struct spi_driver ad2s120x_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = ad2s120x_probe, + .remove = __devexit_p(ad2s120x_remove), +}; + +static __init int ad2s120x_spi_init(void) +{ + return spi_register_driver(&ad2s120x_driver); +} +module_init(ad2s120x_spi_init); + +static __exit void ad2s120x_spi_exit(void) +{ + spi_unregister_driver(&ad2s120x_driver); +} +module_exit(ad2s120x_spi_exit); + +MODULE_AUTHOR("Graff Yang "); +MODULE_DESCRIPTION("Analog Devices AD2S1200/1205 Resolver to Digital SPI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/resolver/ad2s1210.c b/trunk/drivers/staging/iio/resolver/ad2s1210.c new file mode 100644 index 000000000000..34fb21aa8b07 --- /dev/null +++ b/trunk/drivers/staging/iio/resolver/ad2s1210.c @@ -0,0 +1,872 @@ +/* + * ad2s1210.c support for the ADI Resolver to Digital Converters: AD2S1210 + * + * Copyright (c) 2010-2010 Analog Devices Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +#define DRV_NAME "ad2s1210" + +#define DEF_CONTROL 0x7E + +#define MSB_IS_HIGH 0x80 +#define MSB_IS_LOW 0x7F +#define PHASE_LOCK_RANGE_44 0x20 +#define ENABLE_HYSTERESIS 0x10 +#define SET_ENRES1 0x08 +#define SET_ENRES0 0x04 +#define SET_RES1 0x02 +#define SET_RES0 0x01 + +#define SET_ENRESOLUTION (SET_ENRES1 | SET_ENRES0) +#define SET_RESOLUTION (SET_RES1 | SET_RES0) + +#define REG_POSITION 0x80 +#define REG_VELOCITY 0x82 +#define REG_LOS_THRD 0x88 +#define REG_DOS_OVR_THRD 0x89 +#define REG_DOS_MIS_THRD 0x8A +#define REG_DOS_RST_MAX_THRD 0x8B +#define REG_DOS_RST_MIN_THRD 0x8C +#define REG_LOT_HIGH_THRD 0x8D +#define REG_LOT_LOW_THRD 0x8E +#define REG_EXCIT_FREQ 0x91 +#define REG_CONTROL 0x92 +#define REG_SOFT_RESET 0xF0 +#define REG_FAULT 0xFF + +/* pin SAMPLE, A0, A1, RES0, RES1, is controlled by driver */ +#define AD2S1210_SAA 3 +#if defined(CONFIG_AD2S1210_GPIO_INPUT) || defined(CONFIG_AD2S1210_GPIO_OUTPUT) +# define AD2S1210_RES 2 +#else +# define AD2S1210_RES 0 +#endif +#define AD2S1210_PN (AD2S1210_SAA + AD2S1210_RES) + +#define AD2S1210_MIN_CLKIN 6144000 +#define AD2S1210_MAX_CLKIN 10240000 +#define AD2S1210_MIN_EXCIT 2000 +#define AD2S1210_MAX_EXCIT 20000 +#define AD2S1210_MIN_FCW 0x4 +#define AD2S1210_MAX_FCW 0x50 + +/* default input clock on serial interface */ +#define AD2S1210_DEF_CLKIN 8192000 +/* clock period in nano second */ +#define AD2S1210_DEF_TCK (1000000000/AD2S1210_DEF_CLKIN) +#define AD2S1210_DEF_EXCIT 10000 + +enum ad2s1210_mode { + MOD_POS = 0, + MOD_VEL, + MOD_RESERVED, + MOD_CONFIG, +}; + +enum ad2s1210_res { + RES_10 = 10, + RES_12 = 12, + RES_14 = 14, + RES_16 = 16, +}; + +static unsigned int resolution_value[] = { + RES_10, RES_12, RES_14, RES_16}; + +struct ad2s1210_state { + struct mutex lock; + struct iio_dev *idev; + struct spi_device *sdev; + struct spi_transfer xfer; + unsigned int hysteresis; + unsigned int old_data; + enum ad2s1210_mode mode; + enum ad2s1210_res resolution; + unsigned int fclkin; + unsigned int fexcit; + unsigned short sample; + unsigned short a0; + unsigned short a1; + unsigned short res0; + unsigned short res1; + u8 rx[3]; + u8 tx[3]; +}; + +static inline void start_sample(struct ad2s1210_state *st) +{ + gpio_set_value(st->sample, 0); +} + +static inline void stop_sample(struct ad2s1210_state *st) +{ + gpio_set_value(st->sample, 1); +} + +static inline void set_mode(enum ad2s1210_mode mode, struct ad2s1210_state *st) +{ + switch (mode) { + case MOD_POS: + gpio_set_value(st->a0, 0); + gpio_set_value(st->a1, 0); + break; + case MOD_VEL: + gpio_set_value(st->a0, 0); + gpio_set_value(st->a1, 1); + break; + case MOD_CONFIG: + gpio_set_value(st->a0, 1); + gpio_set_value(st->a1, 1); + break; + default: + /* set to reserved mode */ + gpio_set_value(st->a0, 1); + gpio_set_value(st->a1, 0); + } + st->mode = mode; +} + +/* write 1 bytes (address or data) to the chip */ +static int config_write(struct ad2s1210_state *st, + unsigned char data) +{ + struct spi_message msg; + int ret = 0; + + st->xfer.len = 1; + set_mode(MOD_CONFIG, st); + + spi_message_init(&msg); + spi_message_add_tail(&st->xfer, &msg); + st->tx[0] = data; + ret = spi_sync(st->sdev, &msg); + if (ret) + return ret; + st->old_data = 1; + return ret; +} + +/* read value from one of the registers */ +static int config_read(struct ad2s1210_state *st, + unsigned char address, + unsigned char *data) +{ + struct spi_message msg; + int ret = 0; + + st->xfer.len = 2; + set_mode(MOD_CONFIG, st); + + spi_message_init(&msg); + spi_message_add_tail(&st->xfer, &msg); + st->tx[0] = address | MSB_IS_HIGH; + st->tx[1] = REG_FAULT; + ret = spi_sync(st->sdev, &msg); + if (ret) + return ret; + *data = st->rx[1]; + st->old_data = 1; + return ret; +} + +static inline void update_frequency_control_word(struct ad2s1210_state *st) +{ + unsigned char fcw; + fcw = (unsigned char)(st->fexcit * (1 << 15) / st->fclkin); + if (fcw >= AD2S1210_MIN_FCW && fcw <= AD2S1210_MAX_FCW) { + config_write(st, REG_EXCIT_FREQ); + config_write(st, fcw); + } else + pr_err("ad2s1210: FCW out of range\n"); +} + +#if defined(CONFIG_AD2S1210_GPIO_INPUT) +static inline unsigned char read_resolution_pin(struct ad2s1210_state *st) +{ + unsigned int data; + data = (gpio_get_value(st->res0) << 1) | + gpio_get_value(st->res1); + return resolution_value[data]; +} +#elif defined(CONFIG_AD2S1210_GPIO_OUTPUT) +static inline void set_resolution_pin(struct ad2s1210_state *st) +{ + switch (st->resolution) { + case RES_10: + gpio_set_value(st->res0, 0); + gpio_set_value(st->res1, 0); + break; + case RES_12: + gpio_set_value(st->res0, 0); + gpio_set_value(st->res1, 1); + break; + case RES_14: + gpio_set_value(st->res0, 1); + gpio_set_value(st->res1, 0); + break; + case RES_16: + gpio_set_value(st->res0, 1); + gpio_set_value(st->res1, 1); + break; + } +} +#endif + +static inline void soft_reset(struct ad2s1210_state *st) +{ + config_write(st, REG_SOFT_RESET); + config_write(st, 0x0); +} + + +/* return the OLD DATA since last spi bus write */ +static ssize_t ad2s1210_show_raw(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s1210_state *st = idev->dev_data; + int ret; + + mutex_lock(&st->lock); + if (st->old_data) { + ret = sprintf(buf, "0x%x\n", st->rx[0]); + st->old_data = 0; + } else + ret = 0; + mutex_unlock(&st->lock); + return ret; +} + +static ssize_t ad2s1210_store_raw(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s1210_state *st = idev->dev_data; + unsigned long udata; + unsigned char data; + int ret; + + ret = strict_strtoul(buf, 16, &udata); + if (ret) + return -EINVAL; + data = udata & 0xff; + mutex_lock(&st->lock); + config_write(st, data); + mutex_unlock(&st->lock); + return 1; +} + +static ssize_t ad2s1210_store_softreset(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s1210_state *st = idev->dev_data; + mutex_lock(&st->lock); + soft_reset(st); + mutex_unlock(&st->lock); + return len; +} + +static ssize_t ad2s1210_show_fclkin(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s1210_state *st = idev->dev_data; + return sprintf(buf, "%d\n", st->fclkin); +} + +static ssize_t ad2s1210_store_fclkin(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s1210_state *st = idev->dev_data; + unsigned long fclkin; + int ret; + + ret = strict_strtoul(buf, 10, &fclkin); + if (!ret && fclkin >= AD2S1210_MIN_CLKIN && + fclkin <= AD2S1210_MAX_CLKIN) { + mutex_lock(&st->lock); + st->fclkin = fclkin; + } else { + pr_err("ad2s1210: fclkin out of range\n"); + return -EINVAL; + } + update_frequency_control_word(st); + soft_reset(st); + mutex_unlock(&st->lock); + return len; +} + +static ssize_t ad2s1210_show_fexcit(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s1210_state *st = idev->dev_data; + return sprintf(buf, "%d\n", st->fexcit); +} + +static ssize_t ad2s1210_store_fexcit(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s1210_state *st = idev->dev_data; + unsigned long fexcit; + int ret; + + ret = strict_strtoul(buf, 10, &fexcit); + if (!ret && fexcit >= AD2S1210_MIN_EXCIT && + fexcit <= AD2S1210_MAX_EXCIT) { + mutex_lock(&st->lock); + st->fexcit = fexcit; + } else { + pr_err("ad2s1210: excitation frequency out of range\n"); + return -EINVAL; + } + update_frequency_control_word(st); + soft_reset(st); + mutex_unlock(&st->lock); + return len; +} + +static ssize_t ad2s1210_show_control(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s1210_state *st = idev->dev_data; + unsigned char data; + mutex_lock(&st->lock); + config_read(st, REG_CONTROL, &data); + mutex_unlock(&st->lock); + return sprintf(buf, "0x%x\n", data); +} + +static ssize_t ad2s1210_store_control(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s1210_state *st = idev->dev_data; + unsigned long udata; + unsigned char data; + int ret; + + ret = strict_strtoul(buf, 16, &udata); + if (ret) { + ret = -EINVAL; + goto error_ret; + } + mutex_lock(&st->lock); + config_write(st, REG_CONTROL); + data = udata & MSB_IS_LOW; + config_write(st, data); + config_read(st, REG_CONTROL, &data); + if (data & MSB_IS_HIGH) { + ret = -EIO; + pr_err("ad2s1210: write control register fail\n"); + goto error_ret; + } + st->resolution = resolution_value[data & SET_RESOLUTION]; +#if defined(CONFIG_AD2S1210_GPIO_INPUT) + data = read_resolution_pin(st); + if (data != st->resolution) + pr_warning("ad2s1210: resolution settings not match\n"); +#elif defined(CONFIG_AD2S1210_GPIO_OUTPUT) + set_resolution_pin(st); +#endif + ret = len; + if (data & ENABLE_HYSTERESIS) + st->hysteresis = 1; + else + st->hysteresis = 0; +error_ret: + mutex_unlock(&st->lock); + return ret; +} + +static ssize_t ad2s1210_show_resolution(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s1210_state *st = idev->dev_data; + return sprintf(buf, "%d\n", st->resolution); +} + +static ssize_t ad2s1210_store_resolution(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s1210_state *st = idev->dev_data; + unsigned char data; + unsigned long udata; + int ret; + + ret = strict_strtoul(buf, 10, &udata); + if (ret || udata < RES_10 || udata > RES_16) { + pr_err("ad2s1210: resolution out of range\n"); + return -EINVAL; + } + mutex_lock(&st->lock); + config_read(st, REG_CONTROL, &data); + data &= ~SET_RESOLUTION; + data |= (udata - RES_10) >> 1; + config_write(st, REG_CONTROL); + config_write(st, data & MSB_IS_LOW); + config_read(st, REG_CONTROL, &data); + if (data & MSB_IS_HIGH) { + ret = -EIO; + pr_err("ad2s1210: setting resolution fail\n"); + goto error_ret; + } + st->resolution = resolution_value[data & SET_RESOLUTION]; +#if defined(CONFIG_AD2S1210_GPIO_INPUT) + data = read_resolution_pin(st); + if (data != st->resolution) + pr_warning("ad2s1210: resolution settings not match\n"); +#elif defined(CONFIG_AD2S1210_GPIO_OUTPUT) + set_resolution_pin(st); +#endif + ret = len; +error_ret: + mutex_unlock(&st->lock); + return ret; +} +/* read the fault register since last sample */ +static ssize_t ad2s1210_show_fault(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret = 0; + ssize_t len = 0; + unsigned char data; + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s1210_state *st = idev->dev_data; + + mutex_lock(&st->lock); + ret = config_read(st, REG_FAULT, &data); + + if (ret) + goto error_ret; + len = sprintf(buf, "0x%x\n", data); +error_ret: + mutex_unlock(&st->lock); + return ret ? ret : len; +} + +static ssize_t ad2s1210_clear_fault(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s1210_state *st = idev->dev_data; + unsigned char data; + + mutex_lock(&st->lock); + start_sample(st); + /* delay (2 * tck + 20) nano seconds */ + udelay(1); + stop_sample(st); + config_read(st, REG_FAULT, &data); + start_sample(st); + stop_sample(st); + mutex_unlock(&st->lock); + + return 0; +} + +static ssize_t ad2s1210_show_reg(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s1210_state *st = idev->dev_data; + unsigned char data; + struct iio_dev_attr *iattr = to_iio_dev_attr(attr); + + mutex_lock(&st->lock); + config_read(st, iattr->address, &data); + mutex_unlock(&st->lock); + return sprintf(buf, "%d\n", data); +} + +static ssize_t ad2s1210_store_reg(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s1210_state *st = idev->dev_data; + unsigned long data; + int ret; + struct iio_dev_attr *iattr = to_iio_dev_attr(attr); + + ret = strict_strtoul(buf, 10, &data); + if (ret) + return -EINVAL; + mutex_lock(&st->lock); + config_write(st, iattr->address); + config_write(st, data & MSB_IS_LOW); + mutex_unlock(&st->lock); + return len; +} + +static ssize_t ad2s1210_show_pos(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct spi_message msg; + int ret = 0; + ssize_t len = 0; + u16 pos; + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s1210_state *st = idev->dev_data; + + st->xfer.len = 2; + mutex_lock(&st->lock); + start_sample(st); + /* delay (6 * tck + 20) nano seconds */ + udelay(1); + + set_mode(MOD_POS, st); + + spi_message_init(&msg); + spi_message_add_tail(&st->xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + pos = ((((u16)(st->rx[0])) << 8) | (st->rx[1])); + if (st->hysteresis) + pos >>= 16 - st->resolution; + len = sprintf(buf, "%d\n", pos); +error_ret: + stop_sample(st); + /* delay (2 * tck + 20) nano seconds */ + udelay(1); + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +static ssize_t ad2s1210_show_vel(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct spi_message msg; + unsigned short negative; + int ret = 0; + ssize_t len = 0; + s16 vel; + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s1210_state *st = idev->dev_data; + + st->xfer.len = 2; + mutex_lock(&st->lock); + start_sample(st); + /* delay (6 * tck + 20) nano seconds */ + udelay(1); + + set_mode(MOD_VEL, st); + + spi_message_init(&msg); + spi_message_add_tail(&st->xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + negative = st->rx[0] & 0x80; + vel = ((((s16)(st->rx[0])) << 8) | (st->rx[1])); + vel >>= 16 - st->resolution; + if (negative) { + negative = (0xffff >> st->resolution) << st->resolution; + vel |= negative; + } + len = sprintf(buf, "%d\n", vel); +error_ret: + stop_sample(st); + /* delay (2 * tck + 20) nano seconds */ + udelay(1); + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +static ssize_t ad2s1210_show_pos_vel(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct spi_message msg; + unsigned short negative; + int ret = 0; + ssize_t len = 0; + u16 pos; + s16 vel; + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s1210_state *st = idev->dev_data; + + st->xfer.len = 2; + mutex_lock(&st->lock); + start_sample(st); + /* delay (6 * tck + 20) nano seconds */ + udelay(1); + + set_mode(MOD_POS, st); + + spi_message_init(&msg); + spi_message_add_tail(&st->xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + pos = ((((u16)(st->rx[0])) << 8) | (st->rx[1])); + if (st->hysteresis) + pos >>= 16 - st->resolution; + len = sprintf(buf, "%d ", pos); + + st->xfer.len = 2; + set_mode(MOD_VEL, st); + spi_message_init(&msg); + spi_message_add_tail(&st->xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + negative = st->rx[0] & 0x80; + vel = ((((s16)(st->rx[0])) << 8) | (st->rx[1])); + vel >>= 16 - st->resolution; + if (negative) { + negative = (0xffff >> st->resolution) << st->resolution; + vel |= negative; + } + len += sprintf(buf + len, "%d\n", vel); +error_ret: + stop_sample(st); + /* delay (2 * tck + 20) nano seconds */ + udelay(1); + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +static IIO_CONST_ATTR(description, + "Variable Resolution, 10-Bit to 16Bit R/D\n\ +Converter with Reference Oscillator"); +static IIO_DEVICE_ATTR(raw_io, S_IRUGO | S_IWUGO, + ad2s1210_show_raw, ad2s1210_store_raw, 0); +static IIO_DEVICE_ATTR(reset, S_IWUGO, + NULL, ad2s1210_store_softreset, 0); +static IIO_DEVICE_ATTR(fclkin, S_IRUGO | S_IWUGO, + ad2s1210_show_fclkin, ad2s1210_store_fclkin, 0); +static IIO_DEVICE_ATTR(fexcit, S_IRUGO | S_IWUGO, + ad2s1210_show_fexcit, ad2s1210_store_fexcit, 0); +static IIO_DEVICE_ATTR(control, S_IRUGO | S_IWUGO, + ad2s1210_show_control, ad2s1210_store_control, 0); +static IIO_DEVICE_ATTR(bits, S_IRUGO | S_IWUGO, + ad2s1210_show_resolution, ad2s1210_store_resolution, 0); +static IIO_DEVICE_ATTR(fault, S_IRUGO | S_IWUGO, + ad2s1210_show_fault, ad2s1210_clear_fault, 0); +static IIO_DEVICE_ATTR(pos, S_IRUGO, + ad2s1210_show_pos, NULL, 0); +static IIO_DEVICE_ATTR(vel, S_IRUGO, + ad2s1210_show_vel, NULL, 0); +static IIO_DEVICE_ATTR(pos_vel, S_IRUGO, + ad2s1210_show_pos_vel, NULL, 0); +static IIO_DEVICE_ATTR(los_thrd, S_IRUGO | S_IWUGO, + ad2s1210_show_reg, ad2s1210_store_reg, REG_LOS_THRD); +static IIO_DEVICE_ATTR(dos_ovr_thrd, S_IRUGO | S_IWUGO, + ad2s1210_show_reg, ad2s1210_store_reg, REG_DOS_OVR_THRD); +static IIO_DEVICE_ATTR(dos_mis_thrd, S_IRUGO | S_IWUGO, + ad2s1210_show_reg, ad2s1210_store_reg, REG_DOS_MIS_THRD); +static IIO_DEVICE_ATTR(dos_rst_max_thrd, S_IRUGO | S_IWUGO, + ad2s1210_show_reg, ad2s1210_store_reg, REG_DOS_RST_MAX_THRD); +static IIO_DEVICE_ATTR(dos_rst_min_thrd, S_IRUGO | S_IWUGO, + ad2s1210_show_reg, ad2s1210_store_reg, REG_DOS_RST_MIN_THRD); +static IIO_DEVICE_ATTR(lot_high_thrd, S_IRUGO | S_IWUGO, + ad2s1210_show_reg, ad2s1210_store_reg, REG_LOT_HIGH_THRD); +static IIO_DEVICE_ATTR(lot_low_thrd, S_IRUGO | S_IWUGO, + ad2s1210_show_reg, ad2s1210_store_reg, REG_LOT_LOW_THRD); + +static struct attribute *ad2s1210_attributes[] = { + &iio_const_attr_description.dev_attr.attr, + &iio_dev_attr_raw_io.dev_attr.attr, + &iio_dev_attr_reset.dev_attr.attr, + &iio_dev_attr_fclkin.dev_attr.attr, + &iio_dev_attr_fexcit.dev_attr.attr, + &iio_dev_attr_control.dev_attr.attr, + &iio_dev_attr_bits.dev_attr.attr, + &iio_dev_attr_fault.dev_attr.attr, + &iio_dev_attr_pos.dev_attr.attr, + &iio_dev_attr_vel.dev_attr.attr, + &iio_dev_attr_pos_vel.dev_attr.attr, + &iio_dev_attr_los_thrd.dev_attr.attr, + &iio_dev_attr_dos_ovr_thrd.dev_attr.attr, + &iio_dev_attr_dos_mis_thrd.dev_attr.attr, + &iio_dev_attr_dos_rst_max_thrd.dev_attr.attr, + &iio_dev_attr_dos_rst_min_thrd.dev_attr.attr, + &iio_dev_attr_lot_high_thrd.dev_attr.attr, + &iio_dev_attr_lot_low_thrd.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad2s1210_attribute_group = { + .name = DRV_NAME, + .attrs = ad2s1210_attributes, +}; + +static int __devinit ad2s1210_initial(struct ad2s1210_state *st) +{ + unsigned char data; + int ret; + + mutex_lock(&st->lock); +#if defined(CONFIG_AD2S1210_GPIO_INPUT) + st->resolution = read_resolution_pin(st); +#elif defined(CONFIG_AD2S1210_GPIO_OUTPUT) + set_resolution_pin(st); +#endif + + config_write(st, REG_CONTROL); + data = DEF_CONTROL & ~(SET_RESOLUTION); + data |= (st->resolution - RES_10) >> 1; + config_write(st, data); + ret = config_read(st, REG_CONTROL, &data); + if (ret) + goto error_ret; + + if (data & MSB_IS_HIGH) { + ret = -EIO; + goto error_ret; + } + + update_frequency_control_word(st); + soft_reset(st); +error_ret: + mutex_unlock(&st->lock); + return ret; +} + +static int __devinit ad2s1210_probe(struct spi_device *spi) +{ + struct ad2s1210_state *st; + int pn, ret = 0; + unsigned short *pins = spi->dev.platform_data; + + for (pn = 0; pn < AD2S1210_PN; pn++) { + if (gpio_request(pins[pn], DRV_NAME)) { + pr_err("%s: request gpio pin %d failed\n", + DRV_NAME, pins[pn]); + goto error_ret; + } + if (pn < AD2S1210_SAA) + gpio_direction_output(pins[pn], 1); + else { +#if defined(CONFIG_AD2S1210_GPIO_INPUT) + gpio_direction_input(pins[pn]); +#elif defined(CONFIG_AD2S1210_GPIO_OUTPUT) + gpio_direction_output(pins[pn], 1); +#endif + } + } + + st = kzalloc(sizeof(*st), GFP_KERNEL); + if (st == NULL) { + ret = -ENOMEM; + goto error_ret; + } + spi_set_drvdata(spi, st); + + mutex_init(&st->lock); + st->sdev = spi; + st->xfer.tx_buf = st->tx; + st->xfer.rx_buf = st->rx; + st->hysteresis = 1; + st->mode = MOD_CONFIG; + st->resolution = RES_12; + st->fclkin = AD2S1210_DEF_CLKIN; + st->fexcit = AD2S1210_DEF_EXCIT; + st->sample = pins[0]; + st->a0 = pins[1]; + st->a1 = pins[2]; + st->res0 = pins[3]; + st->res1 = pins[4]; + + st->idev = iio_allocate_device(); + if (st->idev == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->idev->dev.parent = &spi->dev; + st->idev->num_interrupt_lines = 0; + st->idev->event_attrs = NULL; + + st->idev->attrs = &ad2s1210_attribute_group; + st->idev->dev_data = (void *)(st); + st->idev->driver_module = THIS_MODULE; + st->idev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(st->idev); + if (ret) + goto error_free_dev; + + if (spi->max_speed_hz != AD2S1210_DEF_CLKIN) + st->fclkin = spi->max_speed_hz; + spi->mode = SPI_MODE_3; + spi_setup(spi); + + ad2s1210_initial(st); + return 0; + +error_free_dev: + iio_free_device(st->idev); +error_free_st: + kfree(st); +error_ret: + for (--pn; pn >= 0; pn--) + gpio_free(pins[pn]); + return ret; +} + +static int __devexit ad2s1210_remove(struct spi_device *spi) +{ + struct ad2s1210_state *st = spi_get_drvdata(spi); + + iio_device_unregister(st->idev); + kfree(st); + + return 0; +} + +static struct spi_driver ad2s1210_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = ad2s1210_probe, + .remove = __devexit_p(ad2s1210_remove), +}; + +static __init int ad2s1210_spi_init(void) +{ + return spi_register_driver(&ad2s1210_driver); +} +module_init(ad2s1210_spi_init); + +static __exit void ad2s1210_spi_exit(void) +{ + spi_unregister_driver(&ad2s1210_driver); +} +module_exit(ad2s1210_spi_exit); + +MODULE_AUTHOR("Graff Yang "); +MODULE_DESCRIPTION("Analog Devices AD2S1210 Resolver to Digital SPI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/resolver/ad2s90.c b/trunk/drivers/staging/iio/resolver/ad2s90.c new file mode 100644 index 000000000000..4143535242d9 --- /dev/null +++ b/trunk/drivers/staging/iio/resolver/ad2s90.c @@ -0,0 +1,159 @@ +/* + * ad2s90.c simple support for the ADI Resolver to Digital Converters: AD2S90 + * + * Copyright (c) 2010-2010 Analog Devices Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" + +#define DRV_NAME "ad2s90" + +struct ad2s90_state { + struct mutex lock; + struct iio_dev *idev; + struct spi_device *sdev; + u8 rx[2]; + u8 tx[2]; +}; + +static ssize_t ad2s90_show_angular(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct spi_message msg; + struct spi_transfer xfer; + int ret; + ssize_t len = 0; + u16 val; + struct iio_dev *idev = dev_get_drvdata(dev); + struct ad2s90_state *st = idev->dev_data; + + xfer.len = 1; + xfer.tx_buf = st->tx; + xfer.rx_buf = st->rx; + mutex_lock(&st->lock); + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + ret = spi_sync(st->sdev, &msg); + if (ret) + goto error_ret; + val = (((u16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4); + len = sprintf(buf, "%d\n", val); +error_ret: + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +#define IIO_DEV_ATTR_SIMPLE_RESOLVER(_show) \ + IIO_DEVICE_ATTR(angular, S_IRUGO, _show, NULL, 0) + +static IIO_CONST_ATTR(description, + "Low Cost, Complete 12-Bit Resolver-to-Digital Converter"); +static IIO_DEV_ATTR_SIMPLE_RESOLVER(ad2s90_show_angular); + +static struct attribute *ad2s90_attributes[] = { + &iio_const_attr_description.dev_attr.attr, + &iio_dev_attr_angular.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad2s90_attribute_group = { + .name = DRV_NAME, + .attrs = ad2s90_attributes, +}; + +static int __devinit ad2s90_probe(struct spi_device *spi) +{ + struct ad2s90_state *st; + int ret = 0; + + st = kzalloc(sizeof(*st), GFP_KERNEL); + if (st == NULL) { + ret = -ENOMEM; + goto error_ret; + } + spi_set_drvdata(spi, st); + + mutex_init(&st->lock); + st->sdev = spi; + + st->idev = iio_allocate_device(); + if (st->idev == NULL) { + ret = -ENOMEM; + goto error_free_st; + } + st->idev->dev.parent = &spi->dev; + st->idev->num_interrupt_lines = 0; + st->idev->event_attrs = NULL; + + st->idev->attrs = &ad2s90_attribute_group; + st->idev->dev_data = (void *)(st); + st->idev->driver_module = THIS_MODULE; + st->idev->modes = INDIO_DIRECT_MODE; + + ret = iio_device_register(st->idev); + if (ret) + goto error_free_dev; + + /* need 600ns between CS and the first falling edge of SCLK */ + spi->max_speed_hz = 830000; + spi->mode = SPI_MODE_3; + spi_setup(spi); + + return 0; + +error_free_dev: + iio_free_device(st->idev); +error_free_st: + kfree(st); +error_ret: + return ret; +} + +static int __devexit ad2s90_remove(struct spi_device *spi) +{ + struct ad2s90_state *st = spi_get_drvdata(spi); + + iio_device_unregister(st->idev); + kfree(st); + + return 0; +} + +static struct spi_driver ad2s90_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = ad2s90_probe, + .remove = __devexit_p(ad2s90_remove), +}; + +static __init int ad2s90_spi_init(void) +{ + return spi_register_driver(&ad2s90_driver); +} +module_init(ad2s90_spi_init); + +static __exit void ad2s90_spi_exit(void) +{ + spi_unregister_driver(&ad2s90_driver); +} +module_exit(ad2s90_spi_exit); + +MODULE_AUTHOR("Graff Yang "); +MODULE_DESCRIPTION("Analog Devices AD2S90 Resolver to Digital SPI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/staging/iio/sysfs.h b/trunk/drivers/staging/iio/sysfs.h index ee91a95a8b95..18bdaac2509d 100644 --- a/trunk/drivers/staging/iio/sysfs.h +++ b/trunk/drivers/staging/iio/sysfs.h @@ -107,6 +107,12 @@ struct iio_const_attr { #define IIO_DEV_ATTR_NAME(_show) \ IIO_DEVICE_ATTR(name, S_IRUGO, _show, NULL, 0) +/** + * IIO_DEV_ATTR_RESET: resets the device + **/ +#define IIO_DEV_ATTR_RESET(_store) \ + IIO_DEVICE_ATTR(reset, S_IWUGO, NULL, _store, 0) + /** * IIO_CONST_ATTR_NAME - constant identifier * @_string: the name diff --git a/trunk/drivers/staging/intel_sst/intel_sst.c b/trunk/drivers/staging/intel_sst/intel_sst.c index 24d3928e7071..0ba6742d9236 100644 --- a/trunk/drivers/staging/intel_sst/intel_sst.c +++ b/trunk/drivers/staging/intel_sst/intel_sst.c @@ -29,6 +29,8 @@ * This file contains all init functions */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -169,17 +171,17 @@ static int __devinit intel_sst_probe(struct pci_dev *pci, { int i, ret = 0; - pr_debug("sst: Probe for DID %x\n", pci->device); + pr_debug("Probe for DID %x\n", pci->device); mutex_lock(&drv_ctx_lock); if (sst_drv_ctx) { - pr_err("sst: Only one sst handle is supported\n"); + pr_err("Only one sst handle is supported\n"); mutex_unlock(&drv_ctx_lock); return -EBUSY; } sst_drv_ctx = kzalloc(sizeof(*sst_drv_ctx), GFP_KERNEL); if (!sst_drv_ctx) { - pr_err("sst: intel_sst malloc fail\n"); + pr_err("malloc fail\n"); mutex_unlock(&drv_ctx_lock); return -ENOMEM; } @@ -226,7 +228,7 @@ static int __devinit intel_sst_probe(struct pci_dev *pci, spin_lock_init(&sst_drv_ctx->list_spin_lock); sst_drv_ctx->max_streams = pci_id->driver_data; - pr_debug("sst: Got drv data max stream %d\n", + pr_debug("Got drv data max stream %d\n", sst_drv_ctx->max_streams); for (i = 1; i <= sst_drv_ctx->max_streams; i++) { struct stream_info *stream = &sst_drv_ctx->streams[i]; @@ -241,18 +243,18 @@ static int __devinit intel_sst_probe(struct pci_dev *pci, sst_drv_ctx->mmap_mem = kzalloc(sst_drv_ctx->mmap_len, GFP_KERNEL); if (sst_drv_ctx->mmap_mem) { - pr_debug("sst: Got memory %p size 0x%x\n", + pr_debug("Got memory %p size 0x%x\n", sst_drv_ctx->mmap_mem, sst_drv_ctx->mmap_len); break; } if (sst_drv_ctx->mmap_len < (SST_MMAP_STEP*PAGE_SIZE)) { - pr_err("sst: mem alloc fail...abort!!\n"); + pr_err("mem alloc fail...abort!!\n"); ret = -ENOMEM; goto free_process_reply_wq; } sst_drv_ctx->mmap_len -= (SST_MMAP_STEP * PAGE_SIZE); - pr_debug("sst:mem alloc failed...trying %d\n", + pr_debug("mem alloc failed...trying %d\n", sst_drv_ctx->mmap_len); } } @@ -260,7 +262,7 @@ static int __devinit intel_sst_probe(struct pci_dev *pci, /* Init the device */ ret = pci_enable_device(pci); if (ret) { - pr_err("sst: device cant be enabled\n"); + pr_err("device cant be enabled\n"); goto do_free_mem; } sst_drv_ctx->pci = pci_dev_get(pci); @@ -273,25 +275,25 @@ static int __devinit intel_sst_probe(struct pci_dev *pci, sst_drv_ctx->shim = pci_ioremap_bar(pci, 1); if (!sst_drv_ctx->shim) goto do_release_regions; - pr_debug("sst: SST Shim Ptr %p\n", sst_drv_ctx->shim); + pr_debug("SST Shim Ptr %p\n", sst_drv_ctx->shim); /* Shared SRAM */ sst_drv_ctx->mailbox = pci_ioremap_bar(pci, 2); if (!sst_drv_ctx->mailbox) goto do_unmap_shim; - pr_debug("sst: SRAM Ptr %p\n", sst_drv_ctx->mailbox); + pr_debug("SRAM Ptr %p\n", sst_drv_ctx->mailbox); /* IRAM */ sst_drv_ctx->iram = pci_ioremap_bar(pci, 3); if (!sst_drv_ctx->iram) goto do_unmap_sram; - pr_debug("sst:IRAM Ptr %p\n", sst_drv_ctx->iram); + pr_debug("IRAM Ptr %p\n", sst_drv_ctx->iram); /* DRAM */ sst_drv_ctx->dram = pci_ioremap_bar(pci, 4); if (!sst_drv_ctx->dram) goto do_unmap_iram; - pr_debug("sst: DRAM Ptr %p\n", sst_drv_ctx->dram); + pr_debug("DRAM Ptr %p\n", sst_drv_ctx->dram); mutex_lock(&sst_drv_ctx->sst_lock); sst_drv_ctx->sst_state = SST_UN_INIT; @@ -301,24 +303,24 @@ static int __devinit intel_sst_probe(struct pci_dev *pci, IRQF_SHARED, SST_DRV_NAME, sst_drv_ctx); if (ret) goto do_unmap_dram; - pr_debug("sst: Registered IRQ 0x%x\n", pci->irq); + pr_debug("Registered IRQ 0x%x\n", pci->irq); if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) { ret = misc_register(&lpe_dev); if (ret) { - pr_err("sst: couldn't register LPE device\n"); + pr_err("couldn't register LPE device\n"); goto do_free_irq; } /*Register LPE Control as misc driver*/ ret = misc_register(&lpe_ctrl); if (ret) { - pr_err("sst: couldn't register misc driver\n"); + pr_err("couldn't register misc driver\n"); goto do_free_irq; } } sst_drv_ctx->lpe_stalled = 0; - pr_debug("sst: ...successfully done!!!\n"); + pr_debug("...successfully done!!!\n"); return ret; do_free_irq: @@ -347,7 +349,7 @@ static int __devinit intel_sst_probe(struct pci_dev *pci, destroy_workqueue(sst_drv_ctx->mad_wq); do_free_drv_ctx: kfree(sst_drv_ctx); - pr_err("sst: Probe failed with 0x%x\n", ret); + pr_err("Probe failed with 0x%x\n", ret); return ret; } @@ -404,7 +406,7 @@ int intel_sst_suspend(struct pci_dev *pci, pm_message_t state) { union config_status_reg csr; - pr_debug("sst: intel_sst_suspend called\n"); + pr_debug("intel_sst_suspend called\n"); if (sst_drv_ctx->pb_streams != 0 || sst_drv_ctx->cp_streams != 0) return -EPERM; @@ -434,9 +436,9 @@ int intel_sst_resume(struct pci_dev *pci) { int ret = 0; - pr_debug("sst: intel_sst_resume called\n"); + pr_debug("intel_sst_resume called\n"); if (sst_drv_ctx->sst_state != SST_SUSPENDED) { - pr_err("sst: SST is not in suspended state\n"); + pr_err("SST is not in suspended state\n"); return -EPERM; } sst_drv_ctx = pci_get_drvdata(pci); @@ -444,7 +446,7 @@ int intel_sst_resume(struct pci_dev *pci) pci_restore_state(pci); ret = pci_enable_device(pci); if (ret) - pr_err("sst: device cant be enabled\n"); + pr_err("device cant be enabled\n"); mutex_lock(&sst_drv_ctx->sst_lock); sst_drv_ctx->sst_state = SST_UN_INIT; @@ -482,14 +484,14 @@ static int __init intel_sst_init(void) { /* Init all variables, data structure etc....*/ int ret = 0; - pr_debug("sst: INFO: ******** SST DRIVER loading.. Ver: %s\n", + pr_debug("INFO: ******** SST DRIVER loading.. Ver: %s\n", SST_DRIVER_VERSION); mutex_init(&drv_ctx_lock); /* Register with PCI */ ret = pci_register_driver(&driver); if (ret) - pr_err("sst: PCI register failed\n"); + pr_err("PCI register failed\n"); return ret; } @@ -504,7 +506,7 @@ static void __exit intel_sst_exit(void) { pci_unregister_driver(&driver); - pr_debug("sst: driver unloaded\n"); + pr_debug("driver unloaded\n"); return; } diff --git a/trunk/drivers/staging/intel_sst/intel_sst_app_interface.c b/trunk/drivers/staging/intel_sst/intel_sst_app_interface.c index 463e5cba8307..fb718d47f54b 100644 --- a/trunk/drivers/staging/intel_sst/intel_sst_app_interface.c +++ b/trunk/drivers/staging/intel_sst/intel_sst_app_interface.c @@ -27,6 +27,8 @@ * Upper layer interfaces (MAD driver, MMF) to SST driver */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -59,14 +61,14 @@ static int intel_sst_check_device(void) { int retval = 0; if (sst_drv_ctx->pmic_state != SND_MAD_INIT_DONE) { - pr_warn("sst: Sound card not availble\n "); + pr_warn("Sound card not available\n"); return -EIO; } if (sst_drv_ctx->sst_state == SST_SUSPENDED) { - pr_debug("sst: Resuming from Suspended state\n"); + pr_debug("Resuming from Suspended state\n"); retval = intel_sst_resume(sst_drv_ctx->pci); if (retval) { - pr_debug("sst: Resume Failed= %#x,abort\n", retval); + pr_debug("Resume Failed= %#x,abort\n", retval); return retval; } } @@ -116,7 +118,7 @@ int intel_sst_open(struct inode *i_node, struct file *file_ptr) data->pvt_id = sst_assign_pvt_id(sst_drv_ctx); data->str_id = 0; file_ptr->private_data = (void *)data; - pr_debug("sst: pvt_id handle = %d!\n", data->pvt_id); + pr_debug("pvt_id handle = %d!\n", data->pvt_id); } else { retval = -EUSERS; mutex_unlock(&sst_drv_ctx->stream_lock); @@ -145,7 +147,7 @@ int intel_sst_open_cntrl(struct inode *i_node, struct file *file_ptr) mutex_lock(&sst_drv_ctx->stream_lock); if (sst_drv_ctx->am_cnt < MAX_AM_HANDLES) { sst_drv_ctx->am_cnt++; - pr_debug("sst: AM handle opened...\n"); + pr_debug("AM handle opened...\n"); file_ptr->private_data = NULL; } else retval = -EACCES; @@ -167,7 +169,7 @@ int intel_sst_release(struct inode *i_node, struct file *file_ptr) { struct ioctl_pvt_data *data = file_ptr->private_data; - pr_debug("sst: Release called, closing app handle\n"); + pr_debug("Release called, closing app handle\n"); mutex_lock(&sst_drv_ctx->stream_lock); sst_drv_ctx->encoded_cnt--; sst_drv_ctx->stream_cnt--; @@ -183,7 +185,7 @@ int intel_sst_release_cntrl(struct inode *i_node, struct file *file_ptr) mutex_lock(&sst_drv_ctx->stream_lock); sst_drv_ctx->am_cnt--; mutex_unlock(&sst_drv_ctx->stream_lock); - pr_debug("sst: AM handle closed\n"); + pr_debug("AM handle closed\n"); return 0; } @@ -209,7 +211,7 @@ int intel_sst_mmap(struct file *file_ptr, struct vm_area_struct *vma) return -EINVAL; length = vma->vm_end - vma->vm_start; - pr_debug("sst: called for stream %d length 0x%x\n", str_id, length); + pr_debug("called for stream %d length 0x%x\n", str_id, length); if (length > sst_drv_ctx->mmap_len) return -ENOMEM; @@ -232,7 +234,7 @@ int intel_sst_mmap(struct file *file_ptr, struct vm_area_struct *vma) else sst_drv_ctx->streams[str_id].mmapped = true; - pr_debug("sst: mmap ret 0x%x\n", retval); + pr_debug("mmap ret 0x%x\n", retval); return retval; } @@ -245,7 +247,7 @@ static int intel_sst_mmap_play_capture(u32 str_id, struct stream_info *stream; struct snd_sst_mmap_buff_entry *buf_entry; - pr_debug("sst:called for str_id %d\n", str_id); + pr_debug("called for str_id %d\n", str_id); retval = sst_validate_strid(str_id); if (retval) return -EINVAL; @@ -262,7 +264,7 @@ static int intel_sst_mmap_play_capture(u32 str_id, stream->curr_bytes = 0; stream->cumm_bytes = 0; - pr_debug("sst:new buffers count %d status %d\n", + pr_debug("new buffers count %d status %d\n", mmap_buf->entries, stream->status); buf_entry = mmap_buf->buff; for (i = 0; i < mmap_buf->entries; i++) { @@ -291,13 +293,13 @@ static int intel_sst_mmap_play_capture(u32 str_id, stream->status = STREAM_RUNNING; if (stream->ops == STREAM_OPS_PLAYBACK) { if (sst_play_frame(str_id) < 0) { - pr_warn("sst: play frames fail\n"); + pr_warn("play frames fail\n"); mutex_unlock(&stream->lock); return -EIO; } } else if (stream->ops == STREAM_OPS_CAPTURE) { if (sst_capture_frame(str_id) < 0) { - pr_warn("sst: capture frame fail\n"); + pr_warn("capture frame fail\n"); mutex_unlock(&stream->lock); return -EIO; } @@ -313,7 +315,7 @@ static int intel_sst_mmap_play_capture(u32 str_id, if (retval >= 0) retval = stream->cumm_bytes; - pr_debug("sst:end of play/rec ioctl bytes = %d!!\n", retval); + pr_debug("end of play/rec ioctl bytes = %d!!\n", retval); return retval; } @@ -335,7 +337,7 @@ static int intel_sst_play_capture(struct stream_info *stream, int str_id) if (stream->status == STREAM_INIT && stream->prev == STREAM_UN_INIT) { /* stream is not started yet */ - pr_debug("sst: Stream isn't in started state %d, prev %d\n", + pr_debug("Stream isn't in started state %d, prev %d\n", stream->status, stream->prev); } else if ((stream->status == STREAM_RUNNING || stream->status == STREAM_PAUSED) && @@ -344,13 +346,13 @@ static int intel_sst_play_capture(struct stream_info *stream, int str_id) if (stream->ops == STREAM_OPS_PLAYBACK || stream->ops == STREAM_OPS_PLAYBACK_DRM) { if (sst_play_frame(str_id) < 0) { - pr_warn("sst: play frames failed\n"); + pr_warn("play frames failed\n"); mutex_unlock(&stream->lock); return -EIO; } } else if (stream->ops == STREAM_OPS_CAPTURE) { if (sst_capture_frame(str_id) < 0) { - pr_warn("sst: capture frames failed\n "); + pr_warn("capture frames failed\n"); mutex_unlock(&stream->lock); return -EIO; } @@ -365,7 +367,7 @@ static int intel_sst_play_capture(struct stream_info *stream, int str_id) retval = sst_wait_interruptible(sst_drv_ctx, &stream->data_blk); if (retval) { stream->status = STREAM_INIT; - pr_debug("sst: wait returned error...\n"); + pr_debug("wait returned error...\n"); } return retval; } @@ -463,7 +465,7 @@ static int snd_sst_fill_kernel_list(struct stream_info *stream, if (((unsigned long)iovec[index].iov_base + iovec[index].iov_len) < ((unsigned long)iovec[index].iov_base)) { - pr_debug("sst: Buffer overflows"); + pr_debug("Buffer overflows\n"); kfree(stream_bufs); return -EINVAL; } @@ -476,7 +478,7 @@ static int snd_sst_fill_kernel_list(struct stream_info *stream, } copied_size += size; - pr_debug("sst: copied_size - %lx\n", copied_size); + pr_debug("copied_size - %lx\n", copied_size); if ((copied_size >= mmap_len) || (stream->sg_index == nr_segs)) { add_to_list = 1; @@ -506,7 +508,7 @@ static int snd_sst_copy_userbuf_capture(struct stream_info *stream, int retval = 0; /* copy sent buffers */ - pr_debug("sst: capture stream copying to user now...\n"); + pr_debug("capture stream copying to user now...\n"); list_for_each_entry_safe(kbufs, _kbufs, &stream->bufs, node) { if (kbufs->in_use == true) { /* copy to user */ @@ -526,7 +528,7 @@ static int snd_sst_copy_userbuf_capture(struct stream_info *stream, } } } - pr_debug("sst: end of cap copy\n"); + pr_debug("end of cap copy\n"); return retval; } @@ -578,7 +580,7 @@ static int intel_sst_read_write(unsigned int str_id, char __user *buf, return -EINVAL; stream = &sst_drv_ctx->streams[str_id]; if (stream->mmapped == true) { - pr_warn("sst: user write and stream is mapped"); + pr_warn("user write and stream is mapped\n"); return -EIO; } if (!count) @@ -586,7 +588,7 @@ static int intel_sst_read_write(unsigned int str_id, char __user *buf, stream->curr_bytes = 0; stream->cumm_bytes = 0; /* copy user buf details */ - pr_debug("sst: new buffers %p, copy size %d, status %d\n" , + pr_debug("new buffers %p, copy size %d, status %d\n" , buf, (int) count, (int) stream->status); stream->buf_type = SST_BUF_USER_STATIC; @@ -606,7 +608,7 @@ static int intel_sst_read_write(unsigned int str_id, char __user *buf, stream->cur_ptr = NULL; if (retval >= 0) retval = stream->cumm_bytes; - pr_debug("sst: end of play/rec bytes = %d!!\n", retval); + pr_debug("end of play/rec bytes = %d!!\n", retval); return retval; } @@ -627,7 +629,7 @@ int intel_sst_write(struct file *file_ptr, const char __user *buf, int str_id = data->str_id; struct stream_info *stream = &sst_drv_ctx->streams[str_id]; - pr_debug("sst: called for %d\n", str_id); + pr_debug("called for %d\n", str_id); if (stream->status == STREAM_UN_INIT || stream->status == STREAM_DECODE) { return -EBADRQC; @@ -653,12 +655,12 @@ ssize_t intel_sst_aio_write(struct kiocb *kiocb, const struct iovec *iov, int str_id = data->str_id; struct stream_info *stream; - pr_debug("sst: entry - %ld\n", nr_segs); + pr_debug("entry - %ld\n", nr_segs); if (is_sync_kiocb(kiocb) == false) return -EINVAL; - pr_debug("sst: called for str_id %d\n", str_id); + pr_debug("called for str_id %d\n", str_id); retval = sst_validate_strid(str_id); if (retval) return -EINVAL; @@ -671,7 +673,7 @@ ssize_t intel_sst_aio_write(struct kiocb *kiocb, const struct iovec *iov, } stream->curr_bytes = 0; stream->cumm_bytes = 0; - pr_debug("sst: new segs %ld, offset %d, status %d\n" , + pr_debug("new segs %ld, offset %d, status %d\n" , nr_segs, (int) offset, (int) stream->status); stream->buf_type = SST_BUF_USER_STATIC; do { @@ -686,7 +688,7 @@ ssize_t intel_sst_aio_write(struct kiocb *kiocb, const struct iovec *iov, stream->cur_ptr = NULL; if (retval >= 0) retval = stream->cumm_bytes; - pr_debug("sst: end of play/rec bytes = %d!!\n", retval); + pr_debug("end of play/rec bytes = %d!!\n", retval); return retval; } @@ -707,7 +709,7 @@ int intel_sst_read(struct file *file_ptr, char __user *buf, int str_id = data->str_id; struct stream_info *stream = &sst_drv_ctx->streams[str_id]; - pr_debug("sst: called for %d\n", str_id); + pr_debug("called for %d\n", str_id); if (stream->status == STREAM_UN_INIT || stream->status == STREAM_DECODE) return -EBADRQC; @@ -732,14 +734,14 @@ ssize_t intel_sst_aio_read(struct kiocb *kiocb, const struct iovec *iov, int str_id = data->str_id; struct stream_info *stream; - pr_debug("sst: entry - %ld\n", nr_segs); + pr_debug("entry - %ld\n", nr_segs); if (is_sync_kiocb(kiocb) == false) { - pr_debug("sst: aio_read from user space is not allowed\n"); + pr_debug("aio_read from user space is not allowed\n"); return -EINVAL; } - pr_debug("sst: called for str_id %d\n", str_id); + pr_debug("called for str_id %d\n", str_id); retval = sst_validate_strid(str_id); if (retval) return -EINVAL; @@ -752,7 +754,7 @@ ssize_t intel_sst_aio_read(struct kiocb *kiocb, const struct iovec *iov, stream->curr_bytes = 0; stream->cumm_bytes = 0; - pr_debug("sst: new segs %ld, offset %d, status %d\n" , + pr_debug("new segs %ld, offset %d, status %d\n" , nr_segs, (int) offset, (int) stream->status); stream->buf_type = SST_BUF_USER_STATIC; do { @@ -767,34 +769,34 @@ ssize_t intel_sst_aio_read(struct kiocb *kiocb, const struct iovec *iov, stream->cur_ptr = NULL; if (retval >= 0) retval = stream->cumm_bytes; - pr_debug("sst: end of play/rec bytes = %d!!\n", retval); + pr_debug("end of play/rec bytes = %d!!\n", retval); return retval; } /* sst_print_stream_params - prints the stream parameters (debug fn)*/ static void sst_print_stream_params(struct snd_sst_get_stream_params *get_prm) { - pr_debug("sst: codec params:result =%d\n", + pr_debug("codec params:result = %d\n", get_prm->codec_params.result); - pr_debug("sst: codec params:stream = %d\n", + pr_debug("codec params:stream = %d\n", get_prm->codec_params.stream_id); - pr_debug("sst: codec params:codec = %d\n", + pr_debug("codec params:codec = %d\n", get_prm->codec_params.codec); - pr_debug("sst: codec params:ops = %d\n", + pr_debug("codec params:ops = %d\n", get_prm->codec_params.ops); - pr_debug("sst: codec params:stream_type= %d\n", + pr_debug("codec params:stream_type = %d\n", get_prm->codec_params.stream_type); - pr_debug("sst: pcmparams:sfreq= %d\n", + pr_debug("pcmparams:sfreq = %d\n", get_prm->pcm_params.sfreq); - pr_debug("sst: pcmparams:num_chan= %d\n", + pr_debug("pcmparams:num_chan = %d\n", get_prm->pcm_params.num_chan); - pr_debug("sst: pcmparams:pcm_wd_sz= %d\n", + pr_debug("pcmparams:pcm_wd_sz = %d\n", get_prm->pcm_params.pcm_wd_sz); return; } /** - * intel_sst_ioctl - recieves the device ioctl's + * intel_sst_ioctl - receives the device ioctl's * @file_ptr:pointer to file * @cmd:Ioctl cmd * @arg:data @@ -820,7 +822,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) switch (_IOC_NR(cmd)) { case _IOC_NR(SNDRV_SST_STREAM_PAUSE): - pr_debug("sst: IOCTL_PAUSE recieved for %d!\n", str_id); + pr_debug("IOCTL_PAUSE received for %d!\n", str_id); if (minor != STREAM_MODULE) { retval = -EBADRQC; break; @@ -829,7 +831,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) break; case _IOC_NR(SNDRV_SST_STREAM_RESUME): - pr_debug("sst: SNDRV_SST_IOCTL_RESUME recieved!\n"); + pr_debug("SNDRV_SST_IOCTL_RESUME received!\n"); if (minor != STREAM_MODULE) { retval = -EBADRQC; break; @@ -840,7 +842,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) case _IOC_NR(SNDRV_SST_STREAM_SET_PARAMS): { struct snd_sst_params *str_param = (struct snd_sst_params *)arg; - pr_debug("sst: IOCTL_SET_PARAMS recieved!\n"); + pr_debug("IOCTL_SET_PARAMS received!\n"); if (minor != STREAM_MODULE) { retval = -EBADRQC; break; @@ -864,7 +866,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) retval = -EINVAL; } } else { - pr_debug("sst: SET_STREAM_PARAMS recieved!\n"); + pr_debug("SET_STREAM_PARAMS received!\n"); /* allocated set params only */ retval = sst_set_stream_param(str_id, str_param); /* Block the call for reply */ @@ -887,21 +889,21 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) case _IOC_NR(SNDRV_SST_SET_VOL): { struct snd_sst_vol *set_vol; struct snd_sst_vol *rec_vol = (struct snd_sst_vol *)arg; - pr_debug("sst: SET_VOLUME recieved for %d!\n", + pr_debug("SET_VOLUME received for %d!\n", rec_vol->stream_id); if (minor == STREAM_MODULE && rec_vol->stream_id == 0) { - pr_debug("sst: invalid operation!\n"); + pr_debug("invalid operation!\n"); retval = -EPERM; break; } set_vol = kzalloc(sizeof(*set_vol), GFP_ATOMIC); if (!set_vol) { - pr_debug("sst: mem allocation failed\n"); + pr_debug("mem allocation failed\n"); retval = -ENOMEM; break; } if (copy_from_user(set_vol, rec_vol, sizeof(*set_vol))) { - pr_debug("sst: copy failed\n"); + pr_debug("copy failed\n"); retval = -EFAULT; break; } @@ -912,10 +914,10 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) case _IOC_NR(SNDRV_SST_GET_VOL): { struct snd_sst_vol *rec_vol = (struct snd_sst_vol *)arg; struct snd_sst_vol get_vol; - pr_debug("sst: IOCTL_GET_VOLUME recieved for stream = %d!\n", + pr_debug("IOCTL_GET_VOLUME received for stream = %d!\n", rec_vol->stream_id); if (minor == STREAM_MODULE && rec_vol->stream_id == 0) { - pr_debug("sst: invalid operation!\n"); + pr_debug("invalid operation!\n"); retval = -EPERM; break; } @@ -925,7 +927,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) retval = -EIO; break; } - pr_debug("sst: id:%d\n, vol:%d, ramp_dur:%d, ramp_type:%d\n", + pr_debug("id:%d\n, vol:%d, ramp_dur:%d, ramp_type:%d\n", get_vol.stream_id, get_vol.volume, get_vol.ramp_duration, get_vol.ramp_type); if (copy_to_user((struct snd_sst_vol *)arg, @@ -940,7 +942,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) case _IOC_NR(SNDRV_SST_MUTE): { struct snd_sst_mute *set_mute; struct snd_sst_vol *rec_mute = (struct snd_sst_vol *)arg; - pr_debug("sst: SNDRV_SST_SET_VOLUME recieved for %d!\n", + pr_debug("SNDRV_SST_SET_VOLUME received for %d!\n", rec_mute->stream_id); if (minor == STREAM_MODULE && rec_mute->stream_id == 0) { retval = -EPERM; @@ -962,7 +964,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) case _IOC_NR(SNDRV_SST_STREAM_GET_PARAMS): { struct snd_sst_get_stream_params get_params; - pr_debug("sst: IOCTL_GET_PARAMS recieved!\n"); + pr_debug("IOCTL_GET_PARAMS received!\n"); if (minor != 0) { retval = -EBADRQC; break; @@ -984,7 +986,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) case _IOC_NR(SNDRV_SST_MMAP_PLAY): case _IOC_NR(SNDRV_SST_MMAP_CAPTURE): - pr_debug("sst: SNDRV_SST_MMAP_PLAY/CAPTURE recieved!\n"); + pr_debug("SNDRV_SST_MMAP_PLAY/CAPTURE received!\n"); if (minor != STREAM_MODULE) { retval = -EBADRQC; break; @@ -994,7 +996,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) break; case _IOC_NR(SNDRV_SST_STREAM_DROP): - pr_debug("sst: SNDRV_SST_IOCTL_DROP recieved!\n"); + pr_debug("SNDRV_SST_IOCTL_DROP received!\n"); if (minor != STREAM_MODULE) { retval = -EINVAL; break; @@ -1007,7 +1009,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) struct snd_sst_tstamp tstamp = {0}; unsigned long long time, freq, mod; - pr_debug("sst: SNDRV_SST_STREAM_GET_TSTAMP recieved!\n"); + pr_debug("SNDRV_SST_STREAM_GET_TSTAMP received!\n"); if (minor != STREAM_MODULE) { retval = -EBADRQC; break; @@ -1028,7 +1030,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) case _IOC_NR(SNDRV_SST_STREAM_START):{ struct stream_info *stream; - pr_debug("sst: SNDRV_SST_STREAM_START recieved!\n"); + pr_debug("SNDRV_SST_STREAM_START received!\n"); if (minor != STREAM_MODULE) { retval = -EINVAL; break; @@ -1067,7 +1069,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) case _IOC_NR(SNDRV_SST_SET_TARGET_DEVICE): { struct snd_sst_target_device *target_device; - pr_debug("sst: SET_TARGET_DEVICE recieved!\n"); + pr_debug("SET_TARGET_DEVICE received!\n"); target_device = (struct snd_sst_target_device *)arg; BUG_ON(!target_device); if (minor != AM_MODULE) { @@ -1082,7 +1084,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) struct snd_sst_driver_info *info = (struct snd_sst_driver_info *)arg; - pr_debug("sst: SNDRV_SST_DRIVER_INFO recived\n"); + pr_debug("SNDRV_SST_DRIVER_INFO received\n"); info->version = SST_VERSION_NUM; /* hard coding, shud get sumhow later */ info->active_pcm_streams = sst_drv_ctx->stream_cnt - @@ -1102,7 +1104,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) struct snd_sst_buff_entry ibuf_temp[param->ibufs->entries], obuf_temp[param->obufs->entries]; - pr_debug("sst: SNDRV_SST_STREAM_DECODE recived\n"); + pr_debug("SNDRV_SST_STREAM_DECODE received\n"); if (minor != STREAM_MODULE) { retval = -EBADRQC; break; @@ -1155,7 +1157,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) } case _IOC_NR(SNDRV_SST_STREAM_DRAIN): - pr_debug("sst: SNDRV_SST_STREAM_DRAIN recived\n"); + pr_debug("SNDRV_SST_STREAM_DRAIN received\n"); if (minor != STREAM_MODULE) { retval = -EINVAL; break; @@ -1167,7 +1169,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) unsigned long long *bytes = (unsigned long long *)arg; struct snd_sst_tstamp tstamp = {0}; - pr_debug("sst: STREAM_BYTES_DECODED recieved!\n"); + pr_debug("STREAM_BYTES_DECODED received!\n"); if (minor != STREAM_MODULE) { retval = -EINVAL; break; @@ -1184,7 +1186,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) case _IOC_NR(SNDRV_SST_FW_INFO): { struct snd_sst_fw_info *fw_info; - pr_debug("sst: SNDRV_SST_FW_INFO recived\n"); + pr_debug("SNDRV_SST_FW_INFO received\n"); fw_info = kzalloc(sizeof(*fw_info), GFP_ATOMIC); if (!fw_info) { @@ -1210,7 +1212,7 @@ long intel_sst_ioctl(struct file *file_ptr, unsigned int cmd, unsigned long arg) default: retval = -EINVAL; } - pr_debug("sst: intel_sst_ioctl:complete ret code = %d\n", retval); + pr_debug("intel_sst_ioctl:complete ret code = %d\n", retval); return retval; } diff --git a/trunk/drivers/staging/intel_sst/intel_sst_drv_interface.c b/trunk/drivers/staging/intel_sst/intel_sst_drv_interface.c index 669e298016f2..5b10ddf60092 100644 --- a/trunk/drivers/staging/intel_sst/intel_sst_drv_interface.c +++ b/trunk/drivers/staging/intel_sst/intel_sst_drv_interface.c @@ -26,6 +26,8 @@ * Upper layer interfaces (MAD driver, MMF) to SST driver */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -52,10 +54,10 @@ int sst_download_fw(void) name = SST_FW_FILENAME_MRST; else name = SST_FW_FILENAME_MFLD; - pr_debug("sst: Downloading %s FW now...\n", name); + pr_debug("Downloading %s FW now...\n", name); retval = request_firmware(&fw_sst, name, &sst_drv_ctx->pci->dev); if (retval) { - pr_err("sst: request fw failed %d\n", retval); + pr_err("request fw failed %d\n", retval); return retval; } sst_drv_ctx->alloc_block[0].sst_id = FW_DWNL_ID; @@ -66,7 +68,7 @@ int sst_download_fw(void) retval = sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[0]); if (retval) - pr_err("sst: fw download failed %d\n" , retval); + pr_err("fw download failed %d\n" , retval); end_restore: release_firmware(fw_sst); sst_drv_ctx->alloc_block[0].sst_id = BLOCK_UNINIT; @@ -90,7 +92,7 @@ int sst_stalled(void) retry--; } - pr_debug("sst: in Stalled State\n"); + pr_debug("in Stalled State\n"); return retval; } @@ -138,23 +140,23 @@ int sst_get_stream_allocated(struct snd_sst_params *str_param, retval = sst_alloc_stream((char *) &str_param->sparams, str_param->ops, str_param->codec, str_param->device_type); if (retval < 0) { - pr_err("sst: sst_alloc_stream failed %d\n", retval); + pr_err("sst_alloc_stream failed %d\n", retval); return retval; } - pr_debug("sst: Stream allocated %d\n", retval); + pr_debug("Stream allocated %d\n", retval); str_id = retval; str_info = &sst_drv_ctx->streams[str_id]; /* Block the call for reply */ retval = sst_wait_interruptible_timeout(sst_drv_ctx, &str_info->ctrl_blk, SST_BLOCK_TIMEOUT); if ((retval != 0) || (str_info->ctrl_blk.ret_code != 0)) { - pr_debug("sst: FW alloc failed retval %d, ret_code %d\n", + pr_debug("FW alloc failed retval %d, ret_code %d\n", retval, str_info->ctrl_blk.ret_code); str_id = -str_info->ctrl_blk.ret_code; /*return error*/ *lib_dnld = str_info->ctrl_blk.data; sst_clean_stream(str_info); } else - pr_debug("sst: FW Stream allocated sucess\n"); + pr_debug("FW Stream allocated success\n"); return str_id; /*will ret either error (in above if) or correct str id*/ } @@ -196,14 +198,14 @@ int sst_get_stream(struct snd_sst_params *str_param) /* codec download is required */ struct snd_sst_alloc_response *response; - pr_debug("sst: Codec is required.... trying that\n"); + pr_debug("Codec is required.... trying that\n"); if (lib_dnld == NULL) { - pr_err("sst: lib download null!!! abort\n"); + pr_err("lib download null!!! abort\n"); return -EIO; } i = sst_get_block_stream(sst_drv_ctx); response = sst_drv_ctx->alloc_block[i].ops_block.data; - pr_debug("sst: alloc block allocated = %d\n", i); + pr_debug("alloc block allocated = %d\n", i); if (i < 0) { kfree(lib_dnld); return -ENOMEM; @@ -213,15 +215,15 @@ int sst_get_stream(struct snd_sst_params *str_param) sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT; if (!retval) { - pr_debug("sst: codec was downloaded sucesfully\n"); + pr_debug("codec was downloaded successfully\n"); retval = sst_get_stream_allocated(str_param, &lib_dnld); if (retval <= 0) goto err; - pr_debug("sst: Alloc done stream id %d\n", retval); + pr_debug("Alloc done stream id %d\n", retval); } else { - pr_debug("sst: codec download failed\n"); + pr_debug("codec download failed\n"); retval = -EIO; goto err; } @@ -279,10 +281,10 @@ void sst_process_mad_ops(struct work_struct *work) retval = sst_start_stream(mad_ops->stream_id); break; case SST_SND_STREAM_PROCESS: - pr_debug("sst: play/capt frames...\n"); + pr_debug("play/capt frames...\n"); break; default: - pr_err("sst: wrong control_ops reported\n"); + pr_err(" wrong control_ops reported\n"); } return; } @@ -301,19 +303,19 @@ int sst_control_set(int control_element, void *value) if (sst_drv_ctx->sst_state == SST_SUSPENDED) { /*LPE is suspended, resume it before proceding*/ - pr_debug("sst: Resuming from Suspended state\n"); + pr_debug("Resuming from Suspended state\n"); retval = intel_sst_resume(sst_drv_ctx->pci); if (retval) { - pr_err("sst: Resume Failed = %#x, abort\n", retval); + pr_err("Resume Failed = %#x, abort\n", retval); return retval; } } if (sst_drv_ctx->sst_state == SST_UN_INIT) { /* FW is not downloaded */ - pr_debug("sst: DSP Downloading FW now...\n"); + pr_debug("DSP Downloading FW now...\n"); retval = sst_download_fw(); if (retval) { - pr_err("sst: FW download fail %x, abort\n", retval); + pr_err("FW download fail %x, abort\n", retval); return retval; } if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID && @@ -361,7 +363,7 @@ int sst_control_set(int control_element, void *value) struct pcm_stream_info *str_info; struct stream_info *stream; - pr_debug("sst: stream init called\n"); + pr_debug("stream init called\n"); str_info = (struct pcm_stream_info *)value; str_id = str_info->str_id; retval = sst_validate_strid(str_id); @@ -369,7 +371,7 @@ int sst_control_set(int control_element, void *value) break; stream = &sst_drv_ctx->streams[str_id]; - pr_debug("sst: setting the period ptrs\n"); + pr_debug("setting the period ptrs\n"); stream->pcm_substream = str_info->mad_substream; stream->period_elapsed = str_info->period_elapsed; stream->sfreq = str_info->sfreq; @@ -398,14 +400,14 @@ int sst_control_set(int control_element, void *value) +(str_id * sizeof(fw_tstamp))), sizeof(fw_tstamp)); - pr_debug("sst: Pointer Query on strid = %d ops %d\n", + pr_debug("Pointer Query on strid = %d ops %d\n", str_id, stream->ops); if (stream->ops == STREAM_OPS_PLAYBACK) stream_info->buffer_ptr = fw_tstamp.samples_rendered; else stream_info->buffer_ptr = fw_tstamp.samples_processed; - pr_debug("sst: Samples rendered = %llu, buffer ptr %llu\n", + pr_debug("Samples rendered = %llu, buffer ptr %llu\n", fw_tstamp.samples_rendered, stream_info->buffer_ptr); break; } @@ -417,7 +419,7 @@ int sst_control_set(int control_element, void *value) } default: /* Illegal case */ - pr_warn("sst: illegal req\n"); + pr_warn("illegal req\n"); return -EINVAL; } @@ -439,12 +441,12 @@ struct intel_sst_card_ops sst_pmic_ops = { int register_sst_card(struct intel_sst_card_ops *card) { if (!sst_drv_ctx) { - pr_err("sst: No SST driver register card reject\n"); + pr_err("No SST driver register card reject\n"); return -ENODEV; } if (!card || !card->module_name) { - pr_err("sst: Null Pointer Passed\n"); + pr_err("Null Pointer Passed\n"); return -EINVAL; } if (sst_drv_ctx->pmic_state == SND_MAD_UN_INIT) { @@ -460,13 +462,13 @@ int register_sst_card(struct intel_sst_card_ops *card) sst_drv_ctx->scard_ops->card_status = SND_CARD_UN_INIT; return 0; } else { - pr_err("sst: strcmp fail %s\n", card->module_name); + pr_err("strcmp fail %s\n", card->module_name); return -EINVAL; } } else { /* already registered a driver */ - pr_err("sst: Repeat for registeration..denied\n"); + pr_err("Repeat for registration..denied\n"); return -EBADRQC; } return 0; @@ -486,7 +488,7 @@ void unregister_sst_card(struct intel_sst_card_ops *card) /* unreg */ sst_pmic_ops.module_name = ""; sst_drv_ctx->pmic_state = SND_MAD_UN_INIT; - pr_debug("sst: Unregistered %s\n", card->module_name); + pr_debug("Unregistered %s\n", card->module_name); } return; } diff --git a/trunk/drivers/staging/intel_sst/intel_sst_dsp.c b/trunk/drivers/staging/intel_sst/intel_sst_dsp.c index d80a6ee2deb8..d1b0537cf4b8 100644 --- a/trunk/drivers/staging/intel_sst/intel_sst_dsp.c +++ b/trunk/drivers/staging/intel_sst/intel_sst_dsp.c @@ -29,6 +29,9 @@ * This file contains all dsp controlling functions like firmware download, * setting/resetting dsp cores, etc */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -47,7 +50,7 @@ static int intel_sst_reset_dsp_mrst(void) { union config_status_reg csr; - pr_debug("sst: Resetting the DSP in mrst\n"); + pr_debug("Resetting the DSP in mrst\n"); csr.full = 0x3a2; sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full); csr.full = sst_shim_read(sst_drv_ctx->shim, SST_CSR); @@ -68,7 +71,7 @@ static int intel_sst_reset_dsp_medfield(void) { union config_status_reg csr; - pr_debug("sst: Resetting the DSP in medfield\n"); + pr_debug("Resetting the DSP in medfield\n"); csr.full = 0x048303E2; sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full); @@ -90,7 +93,7 @@ static int sst_start_mrst(void) csr.part.run_stall = 0; csr.part.sst_reset = 0; csr.part.strb_cntr_rst = 1; - pr_debug("sst: Setting SST to execute_mrst 0x%x\n", csr.full); + pr_debug("Setting SST to execute_mrst 0x%x\n", csr.full); sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full); return 0; @@ -111,7 +114,7 @@ static int sst_start_medfield(void) sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full); csr.full = 0x04830061; sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full); - pr_debug("sst: Starting the DSP_medfld\n"); + pr_debug("Starting the DSP_medfld\n"); return 0; } @@ -130,16 +133,16 @@ static int sst_parse_module(struct fw_module_header *module) u32 count; void __iomem *ram; - pr_debug("sst: module sign %s size %x blocks %x type %x\n", + pr_debug("module sign %s size %x blocks %x type %x\n", module->signature, module->mod_size, module->blocks, module->type); - pr_debug("sst: module entrypoint 0x%x\n", module->entry_point); + pr_debug("module entrypoint 0x%x\n", module->entry_point); block = (void *)module + sizeof(*module); for (count = 0; count < module->blocks; count++) { if (block->size <= 0) { - pr_err("sst: block size invalid\n"); + pr_err("block size invalid\n"); return -EINVAL; } switch (block->type) { @@ -150,7 +153,7 @@ static int sst_parse_module(struct fw_module_header *module) ram = sst_drv_ctx->dram; break; default: - pr_err("sst: wrong ram type0x%x in block0x%x\n", + pr_err("wrong ram type0x%x in block0x%x\n", block->type, count); return -EINVAL; } @@ -184,10 +187,10 @@ static int sst_parse_fw_image(const struct firmware *sst_fw) if ((strncmp(header->signature, SST_FW_SIGN, 4) != 0) || (sst_fw->size != header->file_size + sizeof(*header))) { /* Invalid FW signature */ - pr_err("sst: InvalidFW sign/filesize mismatch\n"); + pr_err("Invalid FW sign/filesize mismatch\n"); return -EINVAL; } - pr_debug("sst: header sign=%s size=%x modules=%x fmt=%x size=%x\n", + pr_debug("header sign=%s size=%x modules=%x fmt=%x size=%x\n", header->signature, header->file_size, header->modules, header->file_format, sizeof(*header)); module = (void *)sst_fw->data + sizeof(*header); @@ -214,7 +217,7 @@ int sst_load_fw(const struct firmware *fw, void *context) { int ret_val; - pr_debug("sst: load_fw called\n"); + pr_debug("load_fw called\n"); BUG_ON(!fw); if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) @@ -239,7 +242,7 @@ int sst_load_fw(const struct firmware *fw, void *context) if (ret_val) return ret_val; - pr_debug("sst: fw loaded successful!!!\n"); + pr_debug("fw loaded successful!!!\n"); return ret_val; } @@ -261,7 +264,7 @@ static int sst_download_library(const struct firmware *fw_lib, pvt_id = sst_assign_pvt_id(sst_drv_ctx); i = sst_get_block_stream(sst_drv_ctx); - pr_debug("sst: alloc block allocated = %d, pvt_id %d\n", i, pvt_id); + pr_debug("alloc block allocated = %d, pvt_id %d\n", i, pvt_id); if (i < 0) { kfree(msg); return -ENOMEM; @@ -281,11 +284,11 @@ static int sst_download_library(const struct firmware *fw_lib, if (retval) { /* error */ sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT; - pr_err("sst: Prep codec downloaded failed %d\n", + pr_err("Prep codec downloaded failed %d\n", retval); return -EIO; } - pr_debug("sst: FW responded, ready for download now...\n"); + pr_debug("FW responded, ready for download now...\n"); /* downloading on success */ mutex_lock(&sst_drv_ctx->sst_lock); sst_drv_ctx->sst_state = SST_FW_LOADED; @@ -325,7 +328,7 @@ static int sst_download_library(const struct firmware *fw_lib, list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list); spin_unlock(&sst_drv_ctx->list_spin_lock); sst_post_message(&sst_drv_ctx->ipc_post_msg_wq); - pr_debug("sst: Waiting for FW response Download complete\n"); + pr_debug("Waiting for FW response Download complete\n"); sst_drv_ctx->alloc_block[i].ops_block.condition = false; retval = sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[i]); if (retval) { @@ -337,7 +340,7 @@ static int sst_download_library(const struct firmware *fw_lib, return -EIO; } - pr_debug("sst: FW sucess on Download complete\n"); + pr_debug("FW success on Download complete\n"); sst_drv_ctx->alloc_block[i].sst_id = BLOCK_UNINIT; mutex_lock(&sst_drv_ctx->sst_lock); sst_drv_ctx->sst_state = SST_FW_RUNNING; @@ -360,14 +363,14 @@ static int sst_validate_library(const struct firmware *fw_lib, header = (struct fw_header *)fw_lib->data; if (header->modules != 1) { - pr_err("sst: Module no mismatch found\n "); + pr_err("Module no mismatch found\n"); err = -EINVAL; goto exit; } module = (void *)fw_lib->data + sizeof(*header); *entry_point = module->entry_point; - pr_debug("sst: Module entry point 0x%x\n", *entry_point); - pr_debug("sst: Module Sign %s, Size 0x%x, Blocks 0x%x Type 0x%x\n", + pr_debug("Module entry point 0x%x\n", *entry_point); + pr_debug("Module Sign %s, Size 0x%x, Blocks 0x%x Type 0x%x\n", module->signature, module->mod_size, module->blocks, module->type); @@ -381,20 +384,20 @@ static int sst_validate_library(const struct firmware *fw_lib, dsize += block->size; break; default: - pr_err("sst: Invalid block type for 0x%x\n", n_blk); + pr_err("Invalid block type for 0x%x\n", n_blk); err = -EINVAL; goto exit; } block = (void *)block + sizeof(*block) + block->size; } if (isize > slot->iram_size || dsize > slot->dram_size) { - pr_err("sst: library exceeds size allocated\n"); + pr_err("library exceeds size allocated\n"); err = -EINVAL; goto exit; } else - pr_debug("sst: Library is safe for download...\n"); + pr_debug("Library is safe for download...\n"); - pr_debug("sst: iram 0x%x, dram 0x%x, iram 0x%x, dram 0x%x\n", + pr_debug("iram 0x%x, dram 0x%x, iram 0x%x, dram 0x%x\n", isize, dsize, slot->iram_size, slot->dram_size); exit: return err; @@ -414,15 +417,15 @@ int sst_load_library(struct snd_sst_lib_download *lib, u8 ops) memset(buf, 0, sizeof(buf)); - pr_debug("sst: Lib Type 0x%x, Slot 0x%x, ops 0x%x\n", + pr_debug("Lib Type 0x%x, Slot 0x%x, ops 0x%x\n", lib->lib_info.lib_type, lib->slot_info.slot_num, ops); - pr_debug("sst: Version 0x%x, name %s, caps 0x%x media type 0x%x\n", + pr_debug("Version 0x%x, name %s, caps 0x%x media type 0x%x\n", lib->lib_info.lib_version, lib->lib_info.lib_name, lib->lib_info.lib_caps, lib->lib_info.media_type); - pr_debug("sst: IRAM Size 0x%x, offset 0x%x\n", + pr_debug("IRAM Size 0x%x, offset 0x%x\n", lib->slot_info.iram_size, lib->slot_info.iram_offset); - pr_debug("sst: DRAM Size 0x%x, offset 0x%x\n", + pr_debug("DRAM Size 0x%x, offset 0x%x\n", lib->slot_info.dram_size, lib->slot_info.dram_offset); switch (lib->lib_info.lib_type) { @@ -442,7 +445,7 @@ int sst_load_library(struct snd_sst_lib_download *lib, u8 ops) type = "wma9_"; break; default: - pr_err("sst: Invalid codec type\n"); + pr_err("Invalid codec type\n"); error = -EINVAL; goto wake; } @@ -458,11 +461,11 @@ int sst_load_library(struct snd_sst_lib_download *lib, u8 ops) lib->slot_info.slot_num); len += snprintf(buf + len, sizeof(buf) - len, ".bin"); - pr_debug("sst: Requesting %s\n", buf); + pr_debug("Requesting %s\n", buf); error = request_firmware(&fw_lib, buf, &sst_drv_ctx->pci->dev); if (error) { - pr_err("sst: library load failed %d\n", error); + pr_err("library load failed %d\n", error); goto wake; } error = sst_validate_library(fw_lib, &lib->slot_info, &entry_point); @@ -476,7 +479,7 @@ int sst_load_library(struct snd_sst_lib_download *lib, u8 ops) goto wake_free; /* lib is downloaded and init send alloc again */ - pr_debug("sst: Library is downloaded now...\n"); + pr_debug("Library is downloaded now...\n"); wake_free: /* sst_wake_up_alloc_block(sst_drv_ctx, pvt_id, error, NULL); */ release_firmware(fw_lib); diff --git a/trunk/drivers/staging/intel_sst/intel_sst_ipc.c b/trunk/drivers/staging/intel_sst/intel_sst_ipc.c index 39c67fa0bd0c..993c5333e906 100644 --- a/trunk/drivers/staging/intel_sst/intel_sst_ipc.c +++ b/trunk/drivers/staging/intel_sst/intel_sst_ipc.c @@ -26,6 +26,8 @@ * This file defines all ipc functions */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -75,16 +77,16 @@ void sst_post_message(struct work_struct *work) /*To check if LPE is in stalled state.*/ retval = sst_stalled(); if (retval < 0) { - pr_err("sst: in stalled state\n"); + pr_err("in stalled state\n"); return; } - pr_debug("sst: post message called\n"); + pr_debug("post message called\n"); spin_lock(&sst_drv_ctx->list_spin_lock); /* check list */ if (list_empty(&sst_drv_ctx->ipc_dispatch_list)) { /* list is empty, mask imr */ - pr_debug("sst: Empty msg queue... masking\n"); + pr_debug("Empty msg queue... masking\n"); imr.full = readl(sst_drv_ctx->shim + SST_IMRX); imr.part.done_interrupt = 1; /* dummy register for shim workaround */ @@ -97,7 +99,7 @@ void sst_post_message(struct work_struct *work) header.full = sst_shim_read(sst_drv_ctx->shim, SST_IPCX); if (header.part.busy) { /* busy, unmask */ - pr_debug("sst: Busy not free... unmasking\n"); + pr_debug("Busy not free... unmasking\n"); imr.full = readl(sst_drv_ctx->shim + SST_IMRX); imr.part.done_interrupt = 0; /* dummy register for shim workaround */ @@ -109,8 +111,8 @@ void sst_post_message(struct work_struct *work) msg = list_entry(sst_drv_ctx->ipc_dispatch_list.next, struct ipc_post, node); list_del(&msg->node); - pr_debug("sst: Post message: header = %x\n", msg->header.full); - pr_debug("sst: size: = %x\n", msg->header.part.data); + pr_debug("Post message: header = %x\n", msg->header.full); + pr_debug("size: = %x\n", msg->header.part.data); if (msg->header.part.large) memcpy_toio(sst_drv_ctx->mailbox + SST_MAILBOX_SEND, msg->mailbox_data, msg->header.part.data); @@ -166,13 +168,13 @@ int process_fw_init(struct sst_ipc_msg_wq *msg) (struct ipc_header_fw_init *)msg->mailbox; int retval = 0; - pr_debug("sst: *** FW Init msg came***\n"); + pr_debug("*** FW Init msg came***\n"); if (init->result) { mutex_lock(&sst_drv_ctx->sst_lock); sst_drv_ctx->sst_state = SST_ERROR; mutex_unlock(&sst_drv_ctx->sst_lock); - pr_debug("sst: FW Init failed, Error %x\n", init->result); - pr_err("sst: FW Init failed, Error %x\n", init->result); + pr_debug("FW Init failed, Error %x\n", init->result); + pr_err("FW Init failed, Error %x\n", init->result); retval = -init->result; return retval; } @@ -181,11 +183,11 @@ int process_fw_init(struct sst_ipc_msg_wq *msg) mutex_lock(&sst_drv_ctx->sst_lock); sst_drv_ctx->sst_state = SST_FW_RUNNING; mutex_unlock(&sst_drv_ctx->sst_lock); - pr_debug("sst: FW Version %x.%x\n", + pr_debug("FW Version %x.%x\n", init->fw_version.major, init->fw_version.minor); - pr_debug("sst: Build No %x Type %x\n", + pr_debug("Build No %x Type %x\n", init->fw_version.build, init->fw_version.type); - pr_debug("sst: Build date %s Time %s\n", + pr_debug(" Build date %s Time %s\n", init->build_info.date, init->build_info.time); sst_wake_up_alloc_block(sst_drv_ctx, FW_DWNL_ID, retval, NULL); return retval; @@ -204,19 +206,19 @@ void sst_process_message(struct work_struct *work) container_of(work, struct sst_ipc_msg_wq, wq); int str_id = msg->header.part.str_id; - pr_debug("sst: IPC process for %x\n", msg->header.full); + pr_debug("IPC process for %x\n", msg->header.full); /* based on msg in list call respective handler */ switch (msg->header.part.msg_id) { case IPC_SST_BUF_UNDER_RUN: case IPC_SST_BUF_OVER_RUN: if (sst_validate_strid(str_id)) { - pr_err("sst: stream id %d invalid\n", str_id); + pr_err("stream id %d invalid\n", str_id); break; } - pr_err("sst: Buffer under/overrun for%d\n", + pr_err("Buffer under/overrun for %d\n", msg->header.part.str_id); - pr_err("sst: Got Underrun & not to send data...ignore\n"); + pr_err("Got Underrun & not to send data...ignore\n"); break; case IPC_SST_GET_PLAY_FRAMES: @@ -224,35 +226,35 @@ void sst_process_message(struct work_struct *work) struct stream_info *stream ; if (sst_validate_strid(str_id)) { - pr_err("sst: strid %d invalid\n", str_id); + pr_err("strid %d invalid\n", str_id); break; } /* call sst_play_frame */ stream = &sst_drv_ctx->streams[str_id]; - pr_debug("sst: sst_play_frames for %d\n", + pr_debug("sst_play_frames for %d\n", msg->header.part.str_id); mutex_lock(&sst_drv_ctx->streams[str_id].lock); sst_play_frame(msg->header.part.str_id); mutex_unlock(&sst_drv_ctx->streams[str_id].lock); break; } else - pr_err("sst: sst_play_frames for Penwell!!\n"); + pr_err("sst_play_frames for Penwell!!\n"); case IPC_SST_GET_CAPT_FRAMES: if (sst_drv_ctx->pci_id == SST_MRST_PCI_ID) { struct stream_info *stream; /* call sst_capture_frame */ if (sst_validate_strid(str_id)) { - pr_err("sst: str id %d invalid\n", str_id); + pr_err("str id %d invalid\n", str_id); break; } stream = &sst_drv_ctx->streams[str_id]; - pr_debug("sst: sst_capture_frames for %d\n", + pr_debug("sst_capture_frames for %d\n", msg->header.part.str_id); mutex_lock(&stream->lock); if (stream->mmapped == false && stream->src == SST_DRV) { - pr_debug("sst: waking up block for copy.\n"); + pr_debug("waking up block for copy.\n"); stream->data_blk.ret_code = 0; stream->data_blk.condition = true; stream->data_blk.on = false; @@ -261,11 +263,11 @@ void sst_process_message(struct work_struct *work) sst_capture_frame(msg->header.part.str_id); mutex_unlock(&stream->lock); } else - pr_err("sst: sst_play_frames for Penwell!!\n"); + pr_err("sst_play_frames for Penwell!!\n"); break; case IPC_IA_PRINT_STRING: - pr_debug("sst: been asked to print something by fw\n"); + pr_debug("been asked to print something by fw\n"); /* TBD */ break; @@ -277,12 +279,12 @@ void sst_process_message(struct work_struct *work) case IPC_SST_STREAM_PROCESS_FATAL_ERR: if (sst_validate_strid(str_id)) { - pr_err("sst: stream id %d invalid\n", str_id); + pr_err("stream id %d invalid\n", str_id); break; } - pr_err("sst: codec fatal error %x stream %d...\n", + pr_err("codec fatal error %x stream %d...\n", msg->header.full, msg->header.part.str_id); - pr_err("sst: Dropping the stream\n"); + pr_err("Dropping the stream\n"); sst_drop_stream(msg->header.part.str_id); break; case IPC_IA_LPE_GETTING_STALLED: @@ -293,7 +295,7 @@ void sst_process_message(struct work_struct *work) break; default: /* Illegal case */ - pr_err("sst: Unhandled msg %x header %x\n", + pr_err("Unhandled msg %x header %x\n", msg->header.part.msg_id, msg->header.full); } sst_clear_interrupt(); @@ -322,7 +324,7 @@ void sst_process_reply(struct work_struct *work) if (!msg->header.part.data) { sst_drv_ctx->tgt_dev_blk.ret_code = 0; } else { - pr_err("sst: Msg %x reply error %x\n", + pr_err(" Msg %x reply error %x\n", msg->header.part.msg_id, msg->header.part.data); sst_drv_ctx->tgt_dev_blk.ret_code = -msg->header.part.data; @@ -340,7 +342,7 @@ void sst_process_reply(struct work_struct *work) int major = fw_info->fw_version.major; int minor = fw_info->fw_version.minor; int build = fw_info->fw_version.build; - pr_debug("sst: Msg succedded %x\n", + pr_debug("Msg succeeded %x\n", msg->header.part.msg_id); pr_debug("INFO: ***FW*** = %02d.%02d.%02d\n", major, minor, build); @@ -349,13 +351,13 @@ void sst_process_reply(struct work_struct *work) sizeof(struct snd_sst_fw_info)); sst_drv_ctx->fw_info_blk.ret_code = 0; } else { - pr_err("sst: Msg %x reply error %x\n", + pr_err(" Msg %x reply error %x\n", msg->header.part.msg_id, msg->header.part.data); sst_drv_ctx->fw_info_blk.ret_code = -msg->header.part.data; } if (sst_drv_ctx->fw_info_blk.on == true) { - pr_debug("sst: Memcopy succedded\n"); + pr_debug("Memcopy succeeded\n"); sst_drv_ctx->fw_info_blk.on = false; sst_drv_ctx->fw_info_blk.condition = true; wake_up(&sst_drv_ctx->wait_queue); @@ -364,11 +366,11 @@ void sst_process_reply(struct work_struct *work) } case IPC_IA_SET_STREAM_MUTE: if (!msg->header.part.data) { - pr_debug("sst: Msg succedded %x\n", + pr_debug("Msg succeeded %x\n", msg->header.part.msg_id); sst_drv_ctx->mute_info_blk.ret_code = 0; } else { - pr_err("sst: Msg %x reply error %x\n", + pr_err(" Msg %x reply error %x\n", msg->header.part.msg_id, msg->header.part.data); sst_drv_ctx->mute_info_blk.ret_code = -msg->header.part.data; @@ -382,11 +384,11 @@ void sst_process_reply(struct work_struct *work) break; case IPC_IA_SET_STREAM_VOL: if (!msg->header.part.data) { - pr_debug("sst: Msg succedded %x\n", + pr_debug("Msg succeeded %x\n", msg->header.part.msg_id); sst_drv_ctx->vol_info_blk.ret_code = 0; } else { - pr_err("sst: Msg %x reply error %x\n", + pr_err(" Msg %x reply error %x\n", msg->header.part.msg_id, msg->header.part.data); sst_drv_ctx->vol_info_blk.ret_code = @@ -402,15 +404,15 @@ void sst_process_reply(struct work_struct *work) break; case IPC_IA_GET_STREAM_VOL: if (msg->header.part.large) { - pr_debug("sst: Large Msg Received Successfully\n"); - pr_debug("sst: Msg succedded %x\n", + pr_debug("Large Msg Received Successfully\n"); + pr_debug("Msg succeeded %x\n", msg->header.part.msg_id); memcpy_fromio(sst_drv_ctx->vol_info_blk.data, (void *) msg->mailbox, sizeof(struct snd_sst_vol)); sst_drv_ctx->vol_info_blk.ret_code = 0; } else { - pr_err("sst: Msg %x reply error %x\n", + pr_err("Msg %x reply error %x\n", msg->header.part.msg_id, msg->header.part.data); sst_drv_ctx->vol_info_blk.ret_code = -msg->header.part.data; @@ -424,18 +426,18 @@ void sst_process_reply(struct work_struct *work) case IPC_IA_GET_STREAM_PARAMS: if (sst_validate_strid(str_id)) { - pr_err("sst: stream id %d invalid\n", str_id); + pr_err("stream id %d invalid\n", str_id); break; } str_info = &sst_drv_ctx->streams[str_id]; if (msg->header.part.large) { - pr_debug("sst: Get stream large success\n"); + pr_debug("Get stream large success\n"); memcpy_fromio(str_info->ctrl_blk.data, ((void *)(msg->mailbox)), sizeof(struct snd_sst_fw_get_stream_params)); str_info->ctrl_blk.ret_code = 0; } else { - pr_err("sst: Msg %x reply error %x\n", + pr_err("Msg %x reply error %x\n", msg->header.part.msg_id, msg->header.part.data); str_info->ctrl_blk.ret_code = -msg->header.part.data; } @@ -447,19 +449,19 @@ void sst_process_reply(struct work_struct *work) break; case IPC_IA_DECODE_FRAMES: if (sst_validate_strid(str_id)) { - pr_err("sst: stream id %d invalid\n", str_id); + pr_err("stream id %d invalid\n", str_id); break; } str_info = &sst_drv_ctx->streams[str_id]; if (msg->header.part.large) { - pr_debug("sst: Msg succedded %x\n", + pr_debug("Msg succeeded %x\n", msg->header.part.msg_id); memcpy_fromio(str_info->data_blk.data, ((void *)(msg->mailbox)), sizeof(struct snd_sst_decode_info)); str_info->data_blk.ret_code = 0; } else { - pr_err("sst: Msg %x reply error %x\n", + pr_err("Msg %x reply error %x\n", msg->header.part.msg_id, msg->header.part.data); str_info->data_blk.ret_code = -msg->header.part.data; } @@ -471,17 +473,17 @@ void sst_process_reply(struct work_struct *work) break; case IPC_IA_DRAIN_STREAM: if (sst_validate_strid(str_id)) { - pr_err("sst: stream id %d invalid\n", str_id); + pr_err("stream id %d invalid\n", str_id); break; } str_info = &sst_drv_ctx->streams[str_id]; if (!msg->header.part.data) { - pr_debug("sst: Msg succedded %x\n", + pr_debug("Msg succeeded %x\n", msg->header.part.msg_id); str_info->ctrl_blk.ret_code = 0; } else { - pr_err("sst: Msg %x reply error %x\n", + pr_err(" Msg %x reply error %x\n", msg->header.part.msg_id, msg->header.part.data); str_info->ctrl_blk.ret_code = -msg->header.part.data; @@ -496,7 +498,7 @@ void sst_process_reply(struct work_struct *work) case IPC_IA_DROP_STREAM: if (sst_validate_strid(str_id)) { - pr_err("sst: str id %d invalid\n", str_id); + pr_err("str id %d invalid\n", str_id); break; } str_info = &sst_drv_ctx->streams[str_id]; @@ -504,12 +506,12 @@ void sst_process_reply(struct work_struct *work) struct snd_sst_drop_response *drop_resp = (struct snd_sst_drop_response *)msg->mailbox; - pr_debug("sst: Drop ret bytes %x\n", drop_resp->bytes); + pr_debug("Drop ret bytes %x\n", drop_resp->bytes); str_info->curr_bytes = drop_resp->bytes; str_info->ctrl_blk.ret_code = 0; } else { - pr_err("sst: Msg %x reply error %x\n", + pr_err(" Msg %x reply error %x\n", msg->header.part.msg_id, msg->header.part.data); str_info->ctrl_blk.ret_code = -msg->header.part.data; } @@ -521,10 +523,10 @@ void sst_process_reply(struct work_struct *work) break; case IPC_IA_ENABLE_RX_TIME_SLOT: if (!msg->header.part.data) { - pr_debug("sst: RX_TIME_SLOT success\n"); + pr_debug("RX_TIME_SLOT success\n"); sst_drv_ctx->hs_info_blk.ret_code = 0; } else { - pr_err("sst: Msg %x reply error %x\n", + pr_err(" Msg %x reply error %x\n", msg->header.part.msg_id, msg->header.part.data); sst_drv_ctx->hs_info_blk.ret_code = @@ -541,17 +543,17 @@ void sst_process_reply(struct work_struct *work) case IPC_IA_SET_STREAM_PARAMS: str_info = &sst_drv_ctx->streams[str_id]; if (!msg->header.part.data) { - pr_debug("sst: Msg succedded %x\n", + pr_debug("Msg succeeded %x\n", msg->header.part.msg_id); str_info->ctrl_blk.ret_code = 0; } else { - pr_err("sst: Msg %x reply error %x\n", + pr_err(" Msg %x reply error %x\n", msg->header.part.msg_id, msg->header.part.data); str_info->ctrl_blk.ret_code = -msg->header.part.data; } if (sst_validate_strid(str_id)) { - pr_err("sst: stream id %d invalid\n", str_id); + pr_err(" stream id %d invalid\n", str_id); break; } @@ -564,9 +566,9 @@ void sst_process_reply(struct work_struct *work) case IPC_IA_FREE_STREAM: if (!msg->header.part.data) { - pr_debug("sst: Stream %d freed\n", str_id); + pr_debug("Stream %d freed\n", str_id); } else { - pr_err("sst: Free for %d ret error %x\n", + pr_err("Free for %d ret error %x\n", str_id, msg->header.part.data); } break; @@ -575,7 +577,7 @@ void sst_process_reply(struct work_struct *work) struct snd_sst_alloc_response *resp = (struct snd_sst_alloc_response *)msg->mailbox; if (resp->str_type.result) - pr_err("sst: error alloc stream = %x\n", + pr_err("error alloc stream = %x\n", resp->str_type.result); sst_alloc_stream_response(str_id, resp); break; @@ -584,21 +586,21 @@ void sst_process_reply(struct work_struct *work) case IPC_IA_PLAY_FRAMES: case IPC_IA_CAPT_FRAMES: if (sst_validate_strid(str_id)) { - pr_err("sst: stream id %d invalid\n" , str_id); + pr_err("stream id %d invalid\n", str_id); break; } - pr_debug("sst: Ack for play/capt frames recived\n"); + pr_debug("Ack for play/capt frames received\n"); break; case IPC_IA_PREP_LIB_DNLD: { struct snd_sst_str_type *str_type = (struct snd_sst_str_type *)msg->mailbox; - pr_debug("sst: Prep Lib download %x\n", + pr_debug("Prep Lib download %x\n", msg->header.part.msg_id); if (str_type->result) - pr_err("sst: Prep lib download %x\n", str_type->result); + pr_err("Prep lib download %x\n", str_type->result); else - pr_debug("sst: Can download codec now...\n"); + pr_debug("Can download codec now...\n"); sst_wake_up_alloc_block(sst_drv_ctx, str_id, str_type->result, NULL); break; @@ -609,12 +611,12 @@ void sst_process_reply(struct work_struct *work) (struct snd_sst_lib_download_info *)msg->mailbox; int retval = resp->result; - pr_debug("sst: Lib downloaded %x\n", msg->header.part.msg_id); + pr_debug("Lib downloaded %x\n", msg->header.part.msg_id); if (resp->result) { - pr_err("sst: err in lib dload %x\n", resp->result); + pr_err("err in lib dload %x\n", resp->result); } else { - pr_debug("sst: Codec download complete...\n"); - pr_debug("sst: codec Type %d Ver %d Built %s: %s\n", + pr_debug("Codec download complete...\n"); + pr_debug("codec Type %d Ver %d Built %s: %s\n", resp->dload_lib.lib_info.lib_type, resp->dload_lib.lib_info.lib_version, resp->dload_lib.lib_info.b_date, @@ -639,17 +641,17 @@ void sst_process_reply(struct work_struct *work) case IPC_IA_GET_FW_BUILD_INF: { struct sst_fw_build_info *build = (struct sst_fw_build_info *)msg->mailbox; - pr_debug("sst: Build date:%sTime:%s", build->date, build->time); + pr_debug("Build date:%sTime:%s", build->date, build->time); break; } case IPC_IA_SET_PMIC_TYPE: break; case IPC_IA_START_STREAM: - pr_debug("sst: reply for START STREAM %x\n", msg->header.full); + pr_debug("reply for START STREAM %x\n", msg->header.full); break; default: /* Illegal case */ - pr_err("sst: process reply:default = %x\n", msg->header.full); + pr_err("process reply:default = %x\n", msg->header.full); } sst_clear_interrupt(); return; diff --git a/trunk/drivers/staging/intel_sst/intel_sst_pvt.c b/trunk/drivers/staging/intel_sst/intel_sst_pvt.c index 6487e192bf93..01f8c3b1cf74 100644 --- a/trunk/drivers/staging/intel_sst/intel_sst_pvt.c +++ b/trunk/drivers/staging/intel_sst/intel_sst_pvt.c @@ -29,6 +29,8 @@ * This file contains all private functions */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -60,7 +62,7 @@ int sst_get_block_stream(struct intel_sst_drv *sst_drv_ctx) } } if (i == MAX_ACTIVE_STREAM) { - pr_err("sst: max alloc_stream reached"); + pr_err("max alloc_stream reached\n"); i = -EBUSY; /* active stream limit reached */ } return i; @@ -84,14 +86,14 @@ int sst_wait_interruptible(struct intel_sst_drv *sst_drv_ctx, block->condition)) { /* event wake */ if (block->ret_code < 0) { - pr_err("sst: stream failed %d\n", block->ret_code); + pr_err("stream failed %d\n", block->ret_code); retval = -EBUSY; } else { - pr_debug("sst: event up\n"); + pr_debug("event up\n"); retval = 0; } } else { - pr_err("sst: signal interrupted\n"); + pr_err("signal interrupted\n"); retval = -EINTR; } return retval; @@ -115,18 +117,18 @@ int sst_wait_interruptible_timeout( { int retval = 0; - pr_debug("sst: sst_wait_interruptible_timeout - waiting....\n"); + pr_debug("sst_wait_interruptible_timeout - waiting....\n"); if (wait_event_interruptible_timeout(sst_drv_ctx->wait_queue, block->condition, msecs_to_jiffies(timeout))) { if (block->ret_code < 0) - pr_err("sst: stream failed %d\n", block->ret_code); + pr_err("stream failed %d\n", block->ret_code); else - pr_debug("sst: event up\n"); + pr_debug("event up\n"); retval = block->ret_code; } else { block->on = false; - pr_err("sst: timeout occured...\n"); + pr_err("timeout occurred...\n"); /*setting firmware state as uninit so that the firmware will get re-downloaded on next request this is because firmare not responding for 5 sec @@ -156,18 +158,18 @@ int sst_wait_timeout(struct intel_sst_drv *sst_drv_ctx, /* NOTE: Observed that FW processes the alloc msg and replies even before the alloc thread has finished execution */ - pr_debug("sst: waiting for %x, condition %x\n", + pr_debug("waiting for %x, condition %x\n", block->sst_id, block->ops_block.condition); if (wait_event_interruptible_timeout(sst_drv_ctx->wait_queue, block->ops_block.condition, msecs_to_jiffies(SST_BLOCK_TIMEOUT))) { /* event wake */ - pr_debug("sst: Event wake %x\n", block->ops_block.condition); - pr_debug("sst: message ret: %d\n", block->ops_block.ret_code); + pr_debug("Event wake %x\n", block->ops_block.condition); + pr_debug("message ret: %d\n", block->ops_block.ret_code); retval = block->ops_block.ret_code; } else { block->ops_block.on = false; - pr_err("sst: Wait timed-out %x\n", block->ops_block.condition); + pr_err("Wait timed-out %x\n", block->ops_block.condition); /* settign firmware state as uninit so that the firmware will get redownloaded on next request this is because firmare not responding for 5 sec @@ -192,14 +194,14 @@ int sst_create_large_msg(struct ipc_post **arg) msg = kzalloc(sizeof(struct ipc_post), GFP_ATOMIC); if (!msg) { - pr_err("sst: kzalloc msg failed\n"); + pr_err("kzalloc msg failed\n"); return -ENOMEM; } msg->mailbox_data = kzalloc(SST_MAILBOX_SIZE, GFP_ATOMIC); if (!msg->mailbox_data) { kfree(msg); - pr_err("sst: kzalloc mailbox_data failed"); + pr_err("kzalloc mailbox_data failed"); return -ENOMEM; }; *arg = msg; @@ -219,7 +221,7 @@ int sst_create_short_msg(struct ipc_post **arg) msg = kzalloc(sizeof(*msg), GFP_ATOMIC); if (!msg) { - pr_err("sst: kzalloc msg failed\n"); + pr_err("kzalloc msg failed\n"); return -ENOMEM; } msg->mailbox_data = NULL; @@ -290,10 +292,10 @@ int sst_enable_rx_timeslot(int status) struct ipc_post *msg = NULL; if (sst_create_short_msg(&msg)) { - pr_err("sst: mem allocation failed\n"); + pr_err("mem allocation failed\n"); return -ENOMEM; } - pr_debug("sst: ipc message sending: ENABLE_RX_TIME_SLOT\n"); + pr_debug("ipc message sending: ENABLE_RX_TIME_SLOT\n"); sst_fill_header(&msg->header, IPC_IA_ENABLE_RX_TIME_SLOT, 0, 0); msg->header.part.data = status; sst_drv_ctx->hs_info_blk.condition = false; diff --git a/trunk/drivers/staging/intel_sst/intel_sst_stream.c b/trunk/drivers/staging/intel_sst/intel_sst_stream.c index b2c4b7067da0..8f6e1005371d 100644 --- a/trunk/drivers/staging/intel_sst/intel_sst_stream.c +++ b/trunk/drivers/staging/intel_sst/intel_sst_stream.c @@ -26,6 +26,8 @@ * This file contains the stream operations of SST driver */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -46,7 +48,7 @@ int sst_check_device_type(u32 device, u32 num_chan, u32 *pcm_slot) { if (device >= MAX_NUM_STREAMS) { - pr_debug("sst: device type invalid %d\n", device); + pr_debug("device type invalid %d\n", device); return -EINVAL; } if (sst_drv_ctx->streams[device].status == STREAM_UN_INIT) { @@ -71,15 +73,15 @@ int sst_check_device_type(u32 device, u32 num_chan, u32 *pcm_slot) else if (device == SND_SST_DEVICE_CAPTURE && num_chan == 4) *pcm_slot = 0x0F; else { - pr_debug("sst: No condition satisfied.. ret err\n"); + pr_debug("No condition satisfied.. ret err\n"); return -EINVAL; } } else { - pr_debug("sst: this stream state is not uni-init, is %d\n", + pr_debug("this stream state is not uni-init, is %d\n", sst_drv_ctx->streams[device].status); return -EBADRQC; } - pr_debug("sst: returning slot %x\n", *pcm_slot); + pr_debug("returning slot %x\n", *pcm_slot); return 0; } /** @@ -96,7 +98,7 @@ static unsigned int get_mrst_stream_id(void) if (sst_drv_ctx->streams[i].status == STREAM_UN_INIT) return i; } - pr_debug("sst: Didnt find empty stream for mrst\n"); + pr_debug("Didnt find empty stream for mrst\n"); return -EBUSY; } @@ -305,7 +307,7 @@ int sst_pause_stream(int str_id) if (str_info->prev == STREAM_UN_INIT) return -EBADRQC; if (str_info->ctrl_blk.on == true) { - pr_err("SST ERR: control path is in use\n "); + pr_err("SST ERR: control path is in use\n"); return -EINVAL; } if (sst_create_short_msg(&msg)) @@ -333,7 +335,7 @@ int sst_pause_stream(int str_id) } } else { retval = -EBADRQC; - pr_err("SST ERR:BADQRC for stream\n "); + pr_err("SST ERR: BADQRC for stream\n"); } return retval; @@ -468,7 +470,7 @@ int sst_drop_stream(int str_id) } } else { retval = -EBADRQC; - pr_err("SST ERR:BADQRC for stream\n"); + pr_err("SST ERR: BADQRC for stream\n"); } return retval; } diff --git a/trunk/drivers/staging/intel_sst/intel_sst_stream_encoded.c b/trunk/drivers/staging/intel_sst/intel_sst_stream_encoded.c index fbae39fda5c0..d4e94f1ec830 100644 --- a/trunk/drivers/staging/intel_sst/intel_sst_stream_encoded.c +++ b/trunk/drivers/staging/intel_sst/intel_sst_stream_encoded.c @@ -26,6 +26,8 @@ * This file contains the stream operations of SST driver */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -53,7 +55,7 @@ int sst_get_stream_params(int str_id, struct stream_info *str_info; struct snd_sst_fw_get_stream_params *fw_params; - pr_debug("sst: get_stream for %d\n", str_id); + pr_debug("get_stream for %d\n", str_id); retval = sst_validate_strid(str_id); if (retval) return retval; @@ -61,16 +63,16 @@ int sst_get_stream_params(int str_id, str_info = &sst_drv_ctx->streams[str_id]; if (str_info->status != STREAM_UN_INIT) { if (str_info->ctrl_blk.on == true) { - pr_err("sst: control path in use\n"); + pr_err("control path in use\n"); return -EINVAL; } if (sst_create_short_msg(&msg)) { - pr_err("sst: message creation failed\n"); + pr_err("message creation failed\n"); return -ENOMEM; } fw_params = kzalloc(sizeof(*fw_params), GFP_ATOMIC); if (!fw_params) { - pr_err("sst: mem allcoation failed\n "); + pr_err("mem allocation failed\n"); kfree(msg); return -ENOMEM; } @@ -104,7 +106,7 @@ int sst_get_stream_params(int str_id, get_params->codec_params.stream_type = str_info->str_type; kfree(fw_params); } else { - pr_debug("sst: Stream is not in the init state\n"); + pr_debug("Stream is not in the init state\n"); } return retval; } @@ -125,17 +127,17 @@ int sst_set_stream_param(int str_id, struct snd_sst_params *str_param) BUG_ON(!str_param); if (sst_drv_ctx->streams[str_id].ops != str_param->ops) { - pr_err("sst: Invalid operation\n"); + pr_err("Invalid operation\n"); return -EINVAL; } retval = sst_validate_strid(str_id); if (retval) return retval; - pr_debug("sst: set_stream for %d\n", str_id); + pr_debug("set_stream for %d\n", str_id); str_info = &sst_drv_ctx->streams[str_id]; if (sst_drv_ctx->streams[str_id].status == STREAM_INIT) { if (str_info->ctrl_blk.on == true) { - pr_err("sst: control path in use\n"); + pr_err("control path in use\n"); return -EAGAIN; } if (sst_create_large_msg(&msg)) @@ -163,7 +165,7 @@ int sst_set_stream_param(int str_id, struct snd_sst_params *str_param) } } else { retval = -EBADRQC; - pr_err("sst: BADQRC for stream\n"); + pr_err("BADQRC for stream\n"); } return retval; } @@ -183,7 +185,7 @@ int sst_get_vol(struct snd_sst_vol *get_vol) struct snd_sst_vol *fw_get_vol; int str_id = get_vol->stream_id; - pr_debug("sst: get vol called\n"); + pr_debug("get vol called\n"); if (sst_create_short_msg(&msg)) return -ENOMEM; @@ -195,7 +197,7 @@ int sst_get_vol(struct snd_sst_vol *get_vol) sst_drv_ctx->vol_info_blk.on = true; fw_get_vol = kzalloc(sizeof(*fw_get_vol), GFP_ATOMIC); if (!fw_get_vol) { - pr_err("sst: mem allocation failed\n"); + pr_err("mem allocation failed\n"); kfree(msg); return -ENOMEM; } @@ -209,10 +211,10 @@ int sst_get_vol(struct snd_sst_vol *get_vol) if (retval) retval = -EIO; else { - pr_debug("sst: stream id %d\n", fw_get_vol->stream_id); - pr_debug("sst: volume %d\n", fw_get_vol->volume); - pr_debug("sst: ramp duration %d\n", fw_get_vol->ramp_duration); - pr_debug("sst: ramp_type %d\n", fw_get_vol->ramp_type); + pr_debug("stream id %d\n", fw_get_vol->stream_id); + pr_debug("volume %d\n", fw_get_vol->volume); + pr_debug("ramp duration %d\n", fw_get_vol->ramp_duration); + pr_debug("ramp_type %d\n", fw_get_vol->ramp_type); memcpy(get_vol, fw_get_vol, sizeof(*fw_get_vol)); } return retval; @@ -231,10 +233,10 @@ int sst_set_vol(struct snd_sst_vol *set_vol) int retval = 0; struct ipc_post *msg = NULL; - pr_debug("sst: set vol called\n"); + pr_debug("set vol called\n"); if (sst_create_large_msg(&msg)) { - pr_err("sst: message creation failed\n"); + pr_err("message creation failed\n"); return -ENOMEM; } sst_fill_header(&msg->header, IPC_IA_SET_STREAM_VOL, 1, @@ -254,7 +256,7 @@ int sst_set_vol(struct snd_sst_vol *set_vol) retval = sst_wait_interruptible_timeout(sst_drv_ctx, &sst_drv_ctx->vol_info_blk, SST_BLOCK_TIMEOUT); if (retval) { - pr_err("sst: error in set_vol = %d\n", retval); + pr_err("error in set_vol = %d\n", retval); retval = -EIO; } return retval; @@ -273,10 +275,10 @@ int sst_set_mute(struct snd_sst_mute *set_mute) int retval = 0; struct ipc_post *msg = NULL; - pr_debug("sst: set mute called\n"); + pr_debug("set mute called\n"); if (sst_create_large_msg(&msg)) { - pr_err("sst: message creation failed\n"); + pr_err("message creation failed\n"); return -ENOMEM; } sst_fill_header(&msg->header, IPC_IA_SET_STREAM_MUTE, 1, @@ -297,7 +299,7 @@ int sst_set_mute(struct snd_sst_mute *set_mute) retval = sst_wait_interruptible_timeout(sst_drv_ctx, &sst_drv_ctx->mute_info_blk, SST_BLOCK_TIMEOUT); if (retval) { - pr_err("sst: error in set_mute = %d\n", retval); + pr_err("error in set_mute = %d\n", retval); retval = -EIO; } return retval; @@ -358,20 +360,20 @@ int sst_parse_target(struct snd_sst_slot_info *slot) slot->device_type == SND_SST_DEVICE_PCM) { retval = sst_activate_target(slot); if (retval) - pr_err("sst: SST_Activate_target_fail\n"); + pr_err("SST_Activate_target_fail\n"); else - pr_err("sst: SST_Activate_target_pass\n"); + pr_err("SST_Activate_target_pass\n"); return retval; } else if (slot->action == SND_SST_PORT_PREPARE && slot->device_type == SND_SST_DEVICE_PCM) { retval = sst_prepare_target(slot); if (retval) - pr_err("sst: SST_prepare_target_fail\n"); + pr_err("SST_prepare_target_fail\n"); else - pr_err("sst: SST_prepare_target_pass\n"); + pr_err("SST_prepare_target_pass\n"); return retval; } else { - pr_err("sst: slot_action : %d, device_type: %d\n", + pr_err("slot_action : %d, device_type: %d\n", slot->action, slot->device_type); return retval; } @@ -383,7 +385,7 @@ int sst_send_target(struct snd_sst_target_device *target) struct ipc_post *msg; if (sst_create_large_msg(&msg)) { - pr_err("sst: message creation failed\n"); + pr_err("message creation failed\n"); return -ENOMEM; } sst_fill_header(&msg->header, IPC_IA_TARGET_DEV_SELECT, 1, 0); @@ -399,11 +401,11 @@ int sst_send_target(struct snd_sst_target_device *target) list_add_tail(&msg->node, &sst_drv_ctx->ipc_dispatch_list); spin_unlock(&sst_drv_ctx->list_spin_lock); sst_post_message(&sst_drv_ctx->ipc_post_msg_wq); - pr_debug("sst: message sent- waiting\n"); + pr_debug("message sent- waiting\n"); retval = sst_wait_interruptible_timeout(sst_drv_ctx, &sst_drv_ctx->tgt_dev_blk, TARGET_DEV_BLOCK_TIMEOUT); if (retval) - pr_err("sst: target device ipc failed = 0x%x\n", retval); + pr_err("target device ipc failed = 0x%x\n", retval); return retval; } @@ -439,7 +441,7 @@ int sst_target_device_validate(struct snd_sst_target_device *target) goto err; } else { err: - pr_err("sst: i/p params incorrect\n"); + pr_err("i/p params incorrect\n"); return -EINVAL; } } @@ -460,15 +462,15 @@ int sst_target_device_select(struct snd_sst_target_device *target) { int retval, i, prepare_count = 0; - pr_debug("sst: Target Device Select\n"); + pr_debug("Target Device Select\n"); if (target->device_route < 0 || target->device_route > 2) { - pr_err("sst: device route is invalid\n"); + pr_err("device route is invalid\n"); return -EINVAL; } if (target->device_route != 0) { - pr_err("sst: Unsupported config\n"); + pr_err("Unsupported config\n"); return -EIO; } retval = sst_target_device_validate(target); @@ -480,18 +482,18 @@ int sst_target_device_select(struct snd_sst_target_device *target) return retval; for (i = 0; i < SST_MAX_TARGET_DEVICES; i++) { if (target->devices[i].action == SND_SST_PORT_ACTIVATE) { - pr_debug("sst: activate called in %d\n", i); + pr_debug("activate called in %d\n", i); retval = sst_parse_target(&target->devices[i]); if (retval) return retval; } else if (target->devices[i].action == SND_SST_PORT_PREPARE) { - pr_debug("sst: PREPARE in %d, Forwading\n", i); + pr_debug("PREPARE in %d, Forwarding\n", i); retval = sst_parse_target(&target->devices[i]); if (retval) { - pr_err("sst: Parse Target fail %d", retval); + pr_err("Parse Target fail %d\n", retval); return retval; } - pr_debug("sst: Parse Target successful %d", retval); + pr_debug("Parse Target successful %d\n", retval); if (target->devices[i].device_type == SND_SST_DEVICE_PCM) prepare_count++; @@ -512,11 +514,11 @@ static inline int sst_get_RAR(struct RAR_buffer *buffers, int count) rar_status = rar_handle_to_bus(buffers, count); if (count != rar_status) { - pr_err("sst: The rar CALL Failed"); + pr_err("The rar CALL Failed"); retval = -EIO; } if (buffers->info.type != RAR_TYPE_AUDIO) { - pr_err("sst: Invalid RAR type\n"); + pr_err("Invalid RAR type\n"); return -EINVAL; } return retval; @@ -539,10 +541,10 @@ static int sst_create_sg_list(struct stream_info *stream, if (kbufs->in_use == false) { #ifdef CONFIG_MRST_RAR_HANDLER if (stream->ops == STREAM_OPS_PLAYBACK_DRM) { - pr_debug("sst: DRM playback handling\n"); + pr_debug("DRM playback handling\n"); rar_buffers.info.handle = (__u32)kbufs->addr; rar_buffers.info.size = kbufs->size; - pr_debug("sst: rar handle 0x%x size=0x%x", + pr_debug("rar handle 0x%x size=0x%x\n", rar_buffers.info.handle, rar_buffers.info.size); retval = sst_get_RAR(&rar_buffers, 1); @@ -552,7 +554,7 @@ static int sst_create_sg_list(struct stream_info *stream, sg_list->addr[i].addr = rar_buffers.bus_address; /* rar_buffers.info.size; */ sg_list->addr[i].size = (__u32)kbufs->size; - pr_debug("sst: phyaddr[%d] 0x%x Size:0x%x\n" + pr_debug("phyaddr[%d] 0x%x Size:0x%x\n" , i, sg_list->addr[i].addr, sg_list->addr[i].size); } @@ -562,7 +564,7 @@ static int sst_create_sg_list(struct stream_info *stream, virt_to_phys((void *) kbufs->addr + kbufs->offset); sg_list->addr[i].size = kbufs->size; - pr_debug("sst: phyaddr[%d]:0x%x Size:0x%x\n" + pr_debug("phyaddr[%d]:0x%x Size:0x%x\n" , i , sg_list->addr[i].addr, kbufs->size); } stream->curr_bytes += sg_list->addr[i].size; @@ -574,7 +576,7 @@ static int sst_create_sg_list(struct stream_info *stream, } sg_list->num_entries = i; - pr_debug("sst:sg list entries = %d\n", sg_list->num_entries); + pr_debug("sg list entries = %d\n", sg_list->num_entries); return i; } @@ -595,7 +597,7 @@ int sst_play_frame(int str_id) struct sst_stream_bufs *kbufs = NULL, *_kbufs; struct stream_info *stream; - pr_debug("sst: play frame for %d\n", str_id); + pr_debug("play frame for %d\n", str_id); retval = sst_validate_strid(str_id); if (retval) return retval; @@ -615,14 +617,14 @@ int sst_play_frame(int str_id) stream->curr_bytes = 0; if (list_empty(&stream->bufs)) { /* no user buffer available */ - pr_debug("sst: Null buffer stream status %d\n", stream->status); + pr_debug("Null buffer stream status %d\n", stream->status); stream->prev = stream->status; stream->status = STREAM_INIT; - pr_debug("sst:new stream status = %d\n", stream->status); + pr_debug("new stream status = %d\n", stream->status); if (stream->need_draining == true) { - pr_debug("sst:draining stream\n"); + pr_debug("draining stream\n"); if (sst_create_short_msg(&msg)) { - pr_err("sst: mem alloc failed\n"); + pr_err("mem allocation failed\n"); return -ENOMEM; } sst_fill_header(&msg->header, IPC_IA_DRAIN_STREAM, @@ -633,7 +635,7 @@ int sst_play_frame(int str_id) spin_unlock(&sst_drv_ctx->list_spin_lock); sst_post_message(&sst_drv_ctx->ipc_post_msg_wq); } else if (stream->data_blk.on == true) { - pr_debug("sst:user list empty.. wake\n"); + pr_debug("user list empty.. wake\n"); /* unblock */ stream->data_blk.ret_code = 0; stream->data_blk.condition = true; @@ -678,7 +680,7 @@ int sst_capture_frame(int str_id) struct stream_info *stream; - pr_debug("sst:capture frame for %d\n", str_id); + pr_debug("capture frame for %d\n", str_id); retval = sst_validate_strid(str_id); if (retval) return retval; @@ -688,19 +690,19 @@ int sst_capture_frame(int str_id) if (kbufs->in_use == true) { list_del(&kbufs->node); kfree(kbufs); - pr_debug("sst:del node\n"); + pr_debug("del node\n"); } } if (list_empty(&stream->bufs)) { /* no user buffer available */ - pr_debug("sst:Null buffer!!!!stream status %d\n", + pr_debug("Null buffer!!!!stream status %d\n", stream->status); stream->prev = stream->status; stream->status = STREAM_INIT; - pr_debug("sst:new stream status = %d\n", + pr_debug("new stream status = %d\n", stream->status); if (stream->data_blk.on == true) { - pr_debug("sst:user list empty.. wake\n"); + pr_debug("user list empty.. wake\n"); /* unblock */ stream->data_blk.ret_code = 0; stream->data_blk.condition = true; @@ -731,7 +733,7 @@ int sst_capture_frame(int str_id) stream->cumm_bytes += stream->curr_bytes; stream->curr_bytes = 0; - pr_debug("sst:Cum bytes = %d\n", stream->cumm_bytes); + pr_debug("Cum bytes = %d\n", stream->cumm_bytes); return 0; } @@ -743,7 +745,7 @@ static unsigned int calculate_min_size(struct snd_sst_buffs *bufs) if (bufs->buff_entry[i].size < min_val) min_val = bufs->buff_entry[i].size; } - pr_debug("sst:min_val = %d\n", min_val); + pr_debug("min_val = %d\n", min_val); return min_val; } @@ -754,7 +756,7 @@ static unsigned int calculate_max_size(struct snd_sst_buffs *bufs) if (bufs->buff_entry[i].size > max_val) max_val = bufs->buff_entry[i].size; } - pr_debug("sst:max_val = %d\n", max_val); + pr_debug("max_val = %d\n", max_val); return max_val; } @@ -773,7 +775,7 @@ static int sst_allocate_decode_buf(struct stream_info *str_info, if (dbufs->ibufs->entries == dbufs->obufs->entries) return 0; else { - pr_err("sst: RAR entries dont match\n"); + pr_err("RAR entries dont match\n"); return -EINVAL; } } else @@ -783,26 +785,26 @@ static int sst_allocate_decode_buf(struct stream_info *str_info, } #endif if (!str_info->decode_ibuf) { - pr_debug("sst:no i/p buffers, trying full size\n"); + pr_debug("no i/p buffers, trying full size\n"); str_info->decode_isize = cum_input_given; str_info->decode_ibuf = kzalloc(str_info->decode_isize, GFP_KERNEL); str_info->idecode_alloc = str_info->decode_isize; } if (!str_info->decode_ibuf) { - pr_debug("sst:buff alloc failed, try max size\n"); + pr_debug("buff alloc failed, try max size\n"); str_info->decode_isize = calculate_max_size(dbufs->ibufs); str_info->decode_ibuf = kzalloc( str_info->decode_isize, GFP_KERNEL); str_info->idecode_alloc = str_info->decode_isize; } if (!str_info->decode_ibuf) { - pr_debug("sst:buff alloc failed, try min size\n"); + pr_debug("buff alloc failed, try min size\n"); str_info->decode_isize = calculate_min_size(dbufs->ibufs); str_info->decode_ibuf = kzalloc(str_info->decode_isize, GFP_KERNEL); if (!str_info->decode_ibuf) { - pr_err("sst: mem allocation failed\n"); + pr_err("mem allocation failed\n"); return -ENOMEM; } str_info->idecode_alloc = str_info->decode_isize; @@ -820,7 +822,7 @@ static int sst_send_decode_mess(int str_id, struct stream_info *str_info, struct ipc_post *msg = NULL; int retval = 0; - pr_debug("SST DBGsst_set_mute:called\n"); + pr_debug("SST DBG:sst_set_mute:called\n"); if (str_info->decode_ibuf_type == SST_BUF_RAR) { #ifdef CONFIG_MRST_RAR_HANDLER @@ -857,7 +859,7 @@ static int sst_send_decode_mess(int str_id, struct stream_info *str_info, dec_info->input_bytes_consumed = 0; dec_info->output_bytes_produced = 0; if (sst_create_large_msg(&msg)) { - pr_err("sst: message creation failed\n"); + pr_err("message creation failed\n"); return -ENOMEM; } @@ -894,7 +896,7 @@ static int sst_prepare_input_buffers_rar(struct stream_info *str_info, dbufs->ibufs->buff_entry[i].buffer, sizeof(__u32)); if (retval) { - pr_err("sst:cpy from user fail\n"); + pr_err("cpy from user fail\n"); return -EAGAIN; } rar_buffers.info.type = dbufs->ibufs->type; @@ -931,7 +933,7 @@ static int sst_prepare_input_buffers(struct stream_info *str_info, { int i, cpy_size, retval = 0; - pr_debug("sst:input_index = %d, input entries = %d\n", + pr_debug("input_index = %d, input entries = %d\n", *input_index, dbufs->ibufs->entries); for (i = *input_index; i < dbufs->ibufs->entries; i++) { #ifdef CONFIG_MRST_RAR_HANDLER @@ -939,7 +941,7 @@ static int sst_prepare_input_buffers(struct stream_info *str_info, dbufs, input_index, in_copied, input_index_valid_size, new_entry_flag); if (retval) { - pr_err("sst: In prepare input buffers for RAR\n"); + pr_err("In prepare input buffers for RAR\n"); return -EIO; } #endif @@ -947,10 +949,10 @@ static int sst_prepare_input_buffers(struct stream_info *str_info, if (*input_index_valid_size == 0) *input_index_valid_size = dbufs->ibufs->buff_entry[i].size; - pr_debug("sst:inout addr = %p, size = %d\n", + pr_debug("inout addr = %p, size = %d\n", dbufs->ibufs->buff_entry[i].buffer, *input_index_valid_size); - pr_debug("sst:decode_isize = %d, in_copied %d\n", + pr_debug("decode_isize = %d, in_copied %d\n", str_info->decode_isize, *in_copied); if (*input_index_valid_size <= (str_info->decode_isize - *in_copied)) @@ -958,12 +960,12 @@ static int sst_prepare_input_buffers(struct stream_info *str_info, else cpy_size = str_info->decode_isize - *in_copied; - pr_debug("sst:cpy size = %d\n", cpy_size); + pr_debug("cpy size = %d\n", cpy_size); if (!dbufs->ibufs->buff_entry[i].buffer) { - pr_err("sst: i/p buffer is null\n"); + pr_err("i/p buffer is null\n"); return -EINVAL; } - pr_debug("sst:Try copy To %p, From %p, size %d\n", + pr_debug("Try copy To %p, From %p, size %d\n", str_info->decode_ibuf + *in_copied, dbufs->ibufs->buff_entry[i].buffer, cpy_size); @@ -972,22 +974,22 @@ static int sst_prepare_input_buffers(struct stream_info *str_info, (void *) dbufs->ibufs->buff_entry[i].buffer, cpy_size); if (retval) { - pr_err("sst: copy from user failed\n"); + pr_err("copy from user failed\n"); return -EIO; } *in_copied += cpy_size; *input_index_valid_size -= cpy_size; - pr_debug("sst:in buff size = %d, in_copied = %d\n", + pr_debug("in buff size = %d, in_copied = %d\n", *input_index_valid_size, *in_copied); if (*input_index_valid_size != 0) { - pr_debug("sst:more input buffers left\n"); + pr_debug("more input buffers left\n"); dbufs->ibufs->buff_entry[i].buffer += cpy_size; break; } if (*in_copied == str_info->decode_isize && *input_index_valid_size == 0 && (i+1) <= dbufs->ibufs->entries) { - pr_debug("sst:all input buffers copied\n"); + pr_debug("all input buffers copied\n"); *new_entry_flag = true; *input_index = i + 1; break; @@ -1005,23 +1007,23 @@ static int sst_prepare_output_buffers(struct stream_info *str_info, { int i, cpy_size, retval = 0; - pr_debug("sst:output_index = %d, output entries = %d\n", + pr_debug("output_index = %d, output entries = %d\n", *output_index, dbufs->obufs->entries); for (i = *output_index; i < dbufs->obufs->entries; i++) { *output_index = i; - pr_debug("sst:output addr = %p, size = %d\n", + pr_debug("output addr = %p, size = %d\n", dbufs->obufs->buff_entry[i].buffer, dbufs->obufs->buff_entry[i].size); - pr_debug("sst:output_size = %d, out_copied = %d\n", + pr_debug("output_size = %d, out_copied = %d\n", output_size, *out_copied); if (dbufs->obufs->buff_entry[i].size < (output_size - *out_copied)) cpy_size = dbufs->obufs->buff_entry[i].size; else cpy_size = output_size - *out_copied; - pr_debug("sst:cpy size = %d\n", cpy_size); - pr_debug("sst:Try copy To: %p, From %p, size %d\n", + pr_debug("cpy size = %d\n", cpy_size); + pr_debug("Try copy To: %p, From %p, size %d\n", dbufs->obufs->buff_entry[i].buffer, sst_drv_ctx->mmap_mem + *out_copied, cpy_size); @@ -1029,13 +1031,13 @@ static int sst_prepare_output_buffers(struct stream_info *str_info, sst_drv_ctx->mmap_mem + *out_copied, cpy_size); if (retval) { - pr_err("sst: copy to user failed\n"); + pr_err("copy to user failed\n"); return -EIO; } else - pr_debug("sst:copy to user passed\n"); + pr_debug("copy to user passed\n"); *out_copied += cpy_size; dbufs->obufs->buff_entry[i].size -= cpy_size; - pr_debug("sst:o/p buff size %d, out_copied %d\n", + pr_debug("o/p buff size %d, out_copied %d\n", dbufs->obufs->buff_entry[i].size, *out_copied); if (dbufs->obufs->buff_entry[i].size != 0) { *output_index = i; @@ -1073,7 +1075,7 @@ int sst_decode(int str_id, struct snd_sst_dbufs *dbufs) unsigned long long input_bytes, output_bytes; sst_drv_ctx->scard_ops->power_down_pmic(); - pr_debug("sst: Powering_down_PMIC...\n"); + pr_debug("Powering_down_PMIC...\n"); retval = sst_validate_strid(str_id); if (retval) @@ -1081,7 +1083,7 @@ int sst_decode(int str_id, struct snd_sst_dbufs *dbufs) str_info = &sst_drv_ctx->streams[str_id]; if (str_info->status != STREAM_INIT) { - pr_err("sst: invalid stream state = %d\n", + pr_err("invalid stream state = %d\n", str_info->status); return -EINVAL; } @@ -1098,7 +1100,7 @@ int sst_decode(int str_id, struct snd_sst_dbufs *dbufs) retval = sst_allocate_decode_buf(str_info, dbufs, cum_input_given, cum_output_given); if (retval) { - pr_err("sst: mem allocation failed, abort!!!\n"); + pr_err("mem allocation failed, abort!!!\n"); retval = -ENOMEM; goto finish; } @@ -1114,7 +1116,7 @@ int sst_decode(int str_id, struct snd_sst_dbufs *dbufs) dbufs, &input_index, &in_copied, &input_index_valid_size, &new_entry_flag); if (retval) { - pr_err("sst: prepare in buffers failed\n"); + pr_err("prepare in buffers failed\n"); goto finish; } @@ -1145,8 +1147,8 @@ int sst_decode(int str_id, struct snd_sst_dbufs *dbufs) str_info->decode_osize = dbufs->obufs-> buff_entry[output_index].size; str_info->decode_obuf_type = dbufs->obufs->type; - pr_debug("sst:DRM handling\n"); - pr_debug("o/p_add=0x%lu Size=0x%x", + pr_debug("DRM handling\n"); + pr_debug("o/p_add=0x%lu Size=0x%x\n", (unsigned long) str_info->decode_obuf, str_info->decode_osize); } else { @@ -1160,7 +1162,7 @@ int sst_decode(int str_id, struct snd_sst_dbufs *dbufs) if (str_info->ops != STREAM_OPS_PLAYBACK_DRM) { if (str_info->decode_isize > in_copied) { str_info->decode_isize = in_copied; - pr_debug("sst:i/p size = %d\n", + pr_debug("i/p size = %d\n", str_info->decode_isize); } } @@ -1168,20 +1170,19 @@ int sst_decode(int str_id, struct snd_sst_dbufs *dbufs) retval = sst_send_decode_mess(str_id, str_info, &dec_info); if (retval || dec_info.input_bytes_consumed == 0) { - pr_err( - "SST ERR: mess failed or no input consumed\n"); + pr_err("SST ERR: mess failed or no input consumed\n"); goto finish; } input_bytes = dec_info.input_bytes_consumed; output_bytes = dec_info.output_bytes_produced; - pr_debug("sst:in_copied=%d, con=%lld, prod=%lld\n", + pr_debug("in_copied=%d, con=%lld, prod=%lld\n", in_copied, input_bytes, output_bytes); if (dbufs->obufs->type == SST_BUF_RAR) { output_index += 1; if (output_index == dbufs->obufs->entries) { copy_in_done = true; - pr_debug("sst:all i/p cpy done\n"); + pr_debug("all i/p cpy done\n"); } total_output += output_bytes; } else { @@ -1190,14 +1191,14 @@ int sst_decode(int str_id, struct snd_sst_dbufs *dbufs) retval = sst_prepare_output_buffers(str_info, dbufs, &output_index, output_size, &out_copied); if (retval) { - pr_err("sst:prep out buff fail\n"); + pr_err("prep out buff fail\n"); goto finish; } if (str_info->ops != STREAM_OPS_PLAYBACK_DRM) { if (in_copied != input_bytes) { int bytes_left = in_copied - input_bytes; - pr_debug("sst:bytes %d\n", + pr_debug("bytes %d\n", bytes_left); if (new_entry_flag == true) input_index--; @@ -1237,7 +1238,7 @@ int sst_decode(int str_id, struct snd_sst_dbufs *dbufs) total_output += out_copied; if (str_info->decode_osize != out_copied) { str_info->decode_osize -= out_copied; - pr_debug("sst:output size modified = %d\n", + pr_debug("output size modified = %d\n", str_info->decode_osize); } } @@ -1251,16 +1252,16 @@ int sst_decode(int str_id, struct snd_sst_dbufs *dbufs) } else { if (total_output == cum_output_given) { copy_out_done = true; - pr_debug("sst:all o/p cpy done\n"); + pr_debug("all o/p cpy done\n"); } if (total_input == cum_input_given) { copy_in_done = true; - pr_debug("sst:all i/p cpy done\n"); + pr_debug("all i/p cpy done\n"); } } - pr_debug("sst:copy_out = %d, copy_in = %d\n", + pr_debug("copy_out = %d, copy_in = %d\n", copy_out_done, copy_in_done); } diff --git a/trunk/drivers/staging/intel_sst/intelmid.c b/trunk/drivers/staging/intel_sst/intelmid.c index 4c0264ceaa88..47b91e500c3c 100644 --- a/trunk/drivers/staging/intel_sst/intelmid.c +++ b/trunk/drivers/staging/intel_sst/intelmid.c @@ -24,6 +24,9 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ALSA driver for Intel MID sound card chipset */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -118,7 +121,7 @@ static int snd_intelmad_pcm_trigger(struct snd_pcm_substream *substream, switch (cmd) { case SNDRV_PCM_TRIGGER_START: - pr_debug("sst: Trigger Start\n"); + pr_debug("Trigger Start\n"); ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_START, &stream->stream_info.str_id); if (ret_val) @@ -128,7 +131,7 @@ static int snd_intelmad_pcm_trigger(struct snd_pcm_substream *substream, stream->stream_status = RUNNING; break; case SNDRV_PCM_TRIGGER_STOP: - pr_debug("sst: in stop\n"); + pr_debug("in stop\n"); ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_DROP, &stream->stream_info.str_id); if (ret_val) @@ -136,7 +139,7 @@ static int snd_intelmad_pcm_trigger(struct snd_pcm_substream *substream, stream->stream_status = DROPPED; break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - pr_debug("sst: in pause\n"); + pr_debug("in pause\n"); ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_PAUSE, &stream->stream_info.str_id); if (ret_val) @@ -144,7 +147,7 @@ static int snd_intelmad_pcm_trigger(struct snd_pcm_substream *substream, stream->stream_status = PAUSED; break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - pr_debug("sst: in pause release\n"); + pr_debug("in pause release\n"); ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_RESUME, &stream->stream_info.str_id); if (ret_val) @@ -170,17 +173,17 @@ static int snd_intelmad_pcm_prepare(struct snd_pcm_substream *substream) int ret_val = 0; struct snd_intelmad *intelmaddata; - pr_debug("sst: pcm_prepare called\n"); + pr_debug("pcm_prepare called\n"); WARN_ON(!substream); stream = substream->runtime->private_data; intelmaddata = snd_pcm_substream_chip(substream); - pr_debug("sst: pb cnt = %d cap cnt = %d\n",\ + pr_debug("pb cnt = %d cap cnt = %d\n",\ intelmaddata->playback_cnt, intelmaddata->capture_cnt); if (stream->stream_info.str_id) { - pr_debug("sst: Prepare called for already set stream\n"); + pr_debug("Prepare called for already set stream\n"); ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_DROP, &stream->stream_info.str_id); return ret_val; @@ -197,7 +200,7 @@ static int snd_intelmad_pcm_prepare(struct snd_pcm_substream *substream) /* return back the stream id */ snprintf(substream->pcm->id, sizeof(substream->pcm->id), "%d", stream->stream_info.str_id); - pr_debug("sst: stream id to user = %s\n", + pr_debug("stream id to user = %s\n", substream->pcm->id); ret_val = snd_intelmad_init_stream(substream); @@ -212,7 +215,7 @@ static int snd_intelmad_hw_params(struct snd_pcm_substream *substream, { int ret_val; - pr_debug("sst: snd_intelmad_hw_params called\n"); + pr_debug("snd_intelmad_hw_params called\n"); ret_val = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); memset(substream->runtime->dma_area, 0, @@ -223,7 +226,7 @@ static int snd_intelmad_hw_params(struct snd_pcm_substream *substream, static int snd_intelmad_hw_free(struct snd_pcm_substream *substream) { - pr_debug("sst: snd_intelmad_hw_free called\n"); + pr_debug("snd_intelmad_hw_free called\n"); return snd_pcm_lib_free_pages(substream); } @@ -253,12 +256,12 @@ static snd_pcm_uframes_t snd_intelmad_pcm_pointer ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_BUFFER_POINTER, &stream->stream_info); if (ret_val) { - pr_err("sst: error code = 0x%x\n", ret_val); + pr_err("error code = 0x%x\n", ret_val); return ret_val; } - pr_debug("sst: samples reported out 0x%llx\n", + pr_debug("samples reported out 0x%llx\n", stream->stream_info.buffer_ptr); - pr_debug("sst: Frame bits:: %d period_count :: %d\n", + pr_debug("Frame bits:: %d period_count :: %d\n", (int)substream->runtime->frame_bits, (int)substream->runtime->period_size); @@ -283,10 +286,10 @@ static int snd_intelmad_close(struct snd_pcm_substream *substream) stream = substream->runtime->private_data; - pr_debug("sst: snd_intelmad_close called\n"); + pr_debug("snd_intelmad_close called\n"); intelmaddata = snd_pcm_substream_chip(substream); - pr_debug("sst: str id = %d\n", stream->stream_info.str_id); + pr_debug("str id = %d\n", stream->stream_info.str_id); if (stream->stream_info.str_id) { /* SST API to actually stop/free the stream */ ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_FREE, @@ -296,7 +299,7 @@ static int snd_intelmad_close(struct snd_pcm_substream *substream) else intelmaddata->capture_cnt--; } - pr_debug("sst: snd_intelmad_close : pb cnt = %d cap cnt = %d\n", + pr_debug("snd_intelmad_close : pb cnt = %d cap cnt = %d\n", intelmaddata->playback_cnt, intelmaddata->capture_cnt); kfree(substream->runtime->private_data); return ret_val; @@ -319,7 +322,7 @@ static int snd_intelmad_open(struct snd_pcm_substream *substream, WARN_ON(!substream); - pr_debug("sst: snd_intelmad_open called\n"); + pr_debug("snd_intelmad_open called\n"); intelmaddata = snd_pcm_substream_chip(substream); runtime = substream->runtime; @@ -456,17 +459,17 @@ void sst_mad_send_jack_report(struct snd_jack *jack, { if (!jack) { - pr_debug("sst: MAD error jack empty\n"); + pr_debug("MAD error jack empty\n"); } else { - pr_debug("sst: MAD send jack report for = %d!!!\n", status); - pr_debug("sst: MAD send jack report %d\n", jack->type); + pr_debug("MAD send jack report for = %d!!!\n", status); + pr_debug("MAD send jack report %d\n", jack->type); snd_jack_report(jack, status); /*button pressed and released */ if (buttonpressevent) snd_jack_report(jack, 0); - pr_debug("sst: MAD sending jack report Done !!!\n"); + pr_debug("MAD sending jack report Done !!!\n"); } @@ -490,7 +493,7 @@ void sst_mad_jackdetection_fs(u8 intsts , struct snd_intelmad *intelmaddata) if (intsts & 0x4) { if (!(intelmid_audio_interrupt_enable)) { - pr_debug("sst: Audio interrupt enable\n"); + pr_debug("Audio interrupt enable\n"); sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3); sst_sc_reg_access(sc_access_write, PMIC_WRITE, 1); @@ -500,7 +503,7 @@ void sst_mad_jackdetection_fs(u8 intsts , struct snd_intelmad *intelmaddata) } /* send headphone detect */ - pr_debug("sst: MAD headphone %d\n", intsts & 0x4); + pr_debug("MAD headphone %d\n", intsts & 0x4); jack = &intelmaddata->jack[0].jack; present = !(intelmaddata->jack[0].jack_status); intelmaddata->jack[0].jack_status = present; @@ -510,7 +513,7 @@ void sst_mad_jackdetection_fs(u8 intsts , struct snd_intelmad *intelmaddata) if (intsts & 0x2) { /* send short push */ - pr_debug("sst: MAD short push %d\n", intsts & 0x2); + pr_debug("MAD short push %d\n", intsts & 0x2); jack = &intelmaddata->jack[2].jack; present = 1; jack_event_flag = 1; @@ -518,7 +521,7 @@ void sst_mad_jackdetection_fs(u8 intsts , struct snd_intelmad *intelmaddata) } if (intsts & 0x1) { /* send long push */ - pr_debug("sst: MAD long push %d\n", intsts & 0x1); + pr_debug("MAD long push %d\n", intsts & 0x1); jack = &intelmaddata->jack[3].jack; present = 1; jack_event_flag = 1; @@ -526,7 +529,7 @@ void sst_mad_jackdetection_fs(u8 intsts , struct snd_intelmad *intelmaddata) } if (intsts & 0x8) { if (!(intelmid_audio_interrupt_enable)) { - pr_debug("sst: Audio interrupt enable\n"); + pr_debug("Audio interrupt enable\n"); sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3); sst_sc_reg_access(sc_access_write, PMIC_WRITE, 1); @@ -535,7 +538,7 @@ void sst_mad_jackdetection_fs(u8 intsts , struct snd_intelmad *intelmaddata) intelmaddata->jack[1].jack_status = 0; } /* send headset detect */ - pr_debug("sst: MAD headset = %d\n", intsts & 0x8); + pr_debug("MAD headset = %d\n", intsts & 0x8); jack = &intelmaddata->jack[1].jack; present = !(intelmaddata->jack[1].jack_status); intelmaddata->jack[1].jack_status = present; @@ -558,10 +561,10 @@ void sst_mad_jackdetection_mx(u8 intsts, struct snd_intelmad *intelmaddata) scard_ops = intelmaddata->sstdrv_ops->scard_ops; - pr_debug("sst: previous value: %x\n", intelmaddata->jack_prev_state); + pr_debug("previous value: %x\n", intelmaddata->jack_prev_state); if (!(intelmid_audio_interrupt_enable)) { - pr_debug("sst: Audio interrupt enable\n"); + pr_debug("Audio interrupt enable\n"); intelmaddata->jack_prev_state = 0xC0; intelmid_audio_interrupt_enable = 1; } @@ -572,12 +575,12 @@ void sst_mad_jackdetection_mx(u8 intsts, struct snd_intelmad *intelmaddata) sc_access_read.reg_addr = 0x201; sst_sc_reg_access(&sc_access_read, PMIC_READ, 1); value = (sc_access_read.value); - pr_debug("sst: value returned = 0x%x\n", value); + pr_debug("value returned = 0x%x\n", value); } if (jack_prev_state == 0xc0 && value == 0x40) { /*headset detected. */ - pr_debug("sst: MAD headset inserted\n"); + pr_debug("MAD headset inserted\n"); jack = &intelmaddata->jack[1].jack; present = 1; jack_event_flag = 1; @@ -587,7 +590,7 @@ void sst_mad_jackdetection_mx(u8 intsts, struct snd_intelmad *intelmaddata) if (jack_prev_state == 0xc0 && value == 0x00) { /* headphone detected. */ - pr_debug("sst: MAD headphone inserted\n"); + pr_debug("MAD headphone inserted\n"); jack = &intelmaddata->jack[0].jack; present = 1; jack_event_flag = 1; @@ -596,9 +599,9 @@ void sst_mad_jackdetection_mx(u8 intsts, struct snd_intelmad *intelmaddata) if (jack_prev_state == 0x40 && value == 0xc0) { /*headset removed*/ - pr_debug("sst: Jack headset status %d\n", + pr_debug("Jack headset status %d\n", intelmaddata->jack[1].jack_status); - pr_debug("sst: MAD headset removed\n"); + pr_debug("MAD headset removed\n"); jack = &intelmaddata->jack[1].jack; present = 0; jack_event_flag = 1; @@ -607,9 +610,9 @@ void sst_mad_jackdetection_mx(u8 intsts, struct snd_intelmad *intelmaddata) if (jack_prev_state == 0x00 && value == 0xc0) { /* headphone detected. */ - pr_debug("sst: Jack headphone status %d\n", + pr_debug("Jack headphone status %d\n", intelmaddata->jack[0].jack_status); - pr_debug("sst: headphone removed\n"); + pr_debug("headphone removed\n"); jack = &intelmaddata->jack[0].jack; present = 0; jack_event_flag = 1; @@ -618,7 +621,7 @@ void sst_mad_jackdetection_mx(u8 intsts, struct snd_intelmad *intelmaddata) if (jack_prev_state == 0x40 && value == 0x00) { /*button pressed*/ do_gettimeofday(&intelmaddata->jack[1].buttonpressed); - pr_debug("sst: MAD button press detected n"); + pr_debug("MAD button press detected\n"); } @@ -628,19 +631,19 @@ void sst_mad_jackdetection_mx(u8 intsts, struct snd_intelmad *intelmaddata) do_gettimeofday( &intelmaddata->jack[1].buttonreleased); /*button pressed */ - pr_debug("sst: Button Released detected\n"); + pr_debug("Button Released detected\n"); timediff = intelmaddata->jack[1]. buttonreleased.tv_sec - intelmaddata-> jack[1].buttonpressed.tv_sec; buttonpressflag = 1; if (timediff > 1) { - pr_debug("sst: long press detected\n"); + pr_debug("long press detected\n"); /* send headphone detect/undetect */ jack = &intelmaddata->jack[3].jack; present = 1; jack_event_flag = 1; } else { - pr_debug("sst: short press detected\n"); + pr_debug("short press detected\n"); /* send headphone detect/undetect */ jack = &intelmaddata->jack[2].jack; present = 1; @@ -667,24 +670,24 @@ void sst_mad_jackdetection_nec(u8 intsts, struct snd_intelmad *intelmaddata) sc_access_read.reg_addr = 0x132; sst_sc_reg_access(&sc_access_read, PMIC_READ, 1); value = (sc_access_read.value); - pr_debug("sst: value returned = 0x%x\n", value); + pr_debug("value returned = 0x%x\n", value); } if (intsts & 0x1) { - pr_debug("sst: headset detected\n"); + pr_debug("headset detected\n"); /* send headset detect/undetect */ jack = &intelmaddata->jack[1].jack; present = (value == 0x1) ? 1 : 0; jack_event_flag = 1; } if (intsts & 0x2) { - pr_debug("sst: headphone detected\n"); + pr_debug("headphone detected\n"); /* send headphone detect/undetect */ jack = &intelmaddata->jack[0].jack; present = (value == 0x2) ? 1 : 0; jack_event_flag = 1; } if (intsts & 0x4) { - pr_debug("sst: short push detected\n"); + pr_debug("short push detected\n"); /* send short push */ jack = &intelmaddata->jack[2].jack; present = 1; @@ -692,7 +695,7 @@ void sst_mad_jackdetection_nec(u8 intsts, struct snd_intelmad *intelmaddata) buttonpressflag = 1; } if (intsts & 0x8) { - pr_debug("sst: long push detected\n"); + pr_debug("long push detected\n"); /* send long push */ jack = &intelmaddata->jack[3].jack; present = 1; @@ -738,12 +741,12 @@ static int __devinit snd_intelmad_register_irq( u32 regbase = AUDINT_BASE, regsize = 8; char *drv_name; - pr_debug("sst: irq reg done, regbase 0x%x, regsize 0x%x\n", + pr_debug("irq reg done, regbase 0x%x, regsize 0x%x\n", regbase, regsize); intelmaddata->int_base = ioremap_nocache(regbase, regsize); if (!intelmaddata->int_base) - pr_err("sst: Mapping of cache failed\n"); - pr_debug("sst: irq = 0x%x\n", intelmaddata->irq); + pr_err("Mapping of cache failed\n"); + pr_debug("irq = 0x%x\n", intelmaddata->irq); if (intelmaddata->cpu_id == CPU_CHIP_PENWELL) drv_name = DRIVER_NAME_MFLD; else @@ -753,7 +756,7 @@ static int __devinit snd_intelmad_register_irq( IRQF_SHARED, drv_name, intelmaddata); if (ret_val) - pr_err("sst: cannot register IRQ\n"); + pr_err("cannot register IRQ\n"); return ret_val; } @@ -775,10 +778,10 @@ static int __devinit snd_intelmad_sst_register( if (ret_val) return ret_val; sst_card_vendor_id = (vendor_addr.value & (MASK2|MASK1|MASK0)); - pr_debug("sst: orginal n extrated vendor id = 0x%x %d\n", + pr_debug("orginal n extrated vendor id = 0x%x %d\n", vendor_addr.value, sst_card_vendor_id); if (sst_card_vendor_id < 0 || sst_card_vendor_id > 2) { - pr_err("sst: vendor card not supported!!\n"); + pr_err("vendor card not supported!!\n"); return -EIO; } } else @@ -801,7 +804,7 @@ static int __devinit snd_intelmad_sst_register( /* registering with SST driver to get access to SST APIs to use */ ret_val = register_sst_card(intelmaddata->sstdrv_ops); if (ret_val) { - pr_err("sst: sst card registration failed\n"); + pr_err("sst card registration failed\n"); return ret_val; } @@ -832,7 +835,7 @@ static int __devinit snd_intelmad_pcm_new(struct snd_card *card, char name[32] = INTEL_MAD; struct snd_pcm_ops *pb_ops = NULL, *cap_ops = NULL; - pr_debug("sst: called for pb %d, cp %d, idx %d\n", pb, cap, index); + pr_debug("called for pb %d, cp %d, idx %d\n", pb, cap, index); ret_val = snd_pcm_new(card, name, index, pb, cap, &pcm); if (ret_val) return ret_val; @@ -878,7 +881,7 @@ static int __devinit snd_intelmad_pcm(struct snd_card *card, WARN_ON(!card); WARN_ON(!intelmaddata); - pr_debug("sst: snd_intelmad_pcm called\n"); + pr_debug("snd_intelmad_pcm called\n"); ret_val = snd_intelmad_pcm_new(card, intelmaddata, 1, 1, 0); if (intelmaddata->cpu_id == CPU_CHIP_LINCROFT) return ret_val; @@ -903,7 +906,7 @@ static int snd_intelmad_jack(struct snd_intelmad *intelmaddata) struct snd_jack *jack; int retval; - pr_debug("sst: snd_intelmad_jack called\n"); + pr_debug("snd_intelmad_jack called\n"); jack = &intelmaddata->jack[0].jack; retval = snd_jack_new(intelmaddata->card, "Headphone", SND_JACK_HEADPHONE, &jack); @@ -982,9 +985,9 @@ static int __devinit snd_intelmad_mixer(struct snd_intelmad *intelmaddata) ret_val = snd_ctl_add(card, snd_ctl_new1(&controls[idx], intelmaddata)); - pr_debug("sst: mixer[idx]=%d added\n", idx); + pr_debug("mixer[idx]=%d added\n", idx); if (ret_val) { - pr_err("sst: in adding of control index = %d\n", idx); + pr_err("in adding of control index = %d\n", idx); break; } } @@ -999,7 +1002,7 @@ static int snd_intelmad_dev_free(struct snd_device *device) intelmaddata = device->device_data; - pr_debug("sst: snd_intelmad_dev_free called\n"); + pr_debug("snd_intelmad_dev_free called\n"); snd_card_free(intelmaddata->card); /*genl_unregister_family(&audio_event_genl_family);*/ unregister_sst_card(intelmaddata->sstdrv_ops); @@ -1040,23 +1043,23 @@ int __devinit snd_intelmad_probe(struct platform_device *pdev) const struct platform_device_id *id = platform_get_device_id(pdev); unsigned int cpu_id = (unsigned int)id->driver_data; - pr_debug("sst: probe for %s cpu_id %d\n", pdev->name, cpu_id); + pr_debug("probe for %s cpu_id %d\n", pdev->name, cpu_id); if (!strcmp(pdev->name, DRIVER_NAME_MRST)) - pr_debug("sst: detected MRST\n"); + pr_debug("detected MRST\n"); else if (!strcmp(pdev->name, DRIVER_NAME_MFLD)) - pr_debug("sst: detected MFLD\n"); + pr_debug("detected MFLD\n"); else { - pr_err("sst: detected unknown device abort!!\n"); + pr_err("detected unknown device abort!!\n"); return -EIO; } if ((cpu_id < CPU_CHIP_LINCROFT) || (cpu_id > CPU_CHIP_PENWELL)) { - pr_err("sst: detected unknown cpu_id abort!!\n"); + pr_err("detected unknown cpu_id abort!!\n"); return -EIO; } /* allocate memory for saving internal context and working */ intelmaddata = kzalloc(sizeof(*intelmaddata), GFP_KERNEL); if (!intelmaddata) { - pr_debug("sst: mem alloctn fail\n"); + pr_debug("mem alloctn fail\n"); return -ENOMEM; } @@ -1064,7 +1067,7 @@ int __devinit snd_intelmad_probe(struct platform_device *pdev) intelmaddata->sstdrv_ops = kzalloc(sizeof(struct intel_sst_card_ops), GFP_KERNEL); if (!intelmaddata->sstdrv_ops) { - pr_err("sst: mem allocation for ops fail\n"); + pr_err("mem allocation for ops fail\n"); kfree(intelmaddata); return -ENOMEM; } @@ -1073,7 +1076,7 @@ int __devinit snd_intelmad_probe(struct platform_device *pdev) /* create a card instance with ALSA framework */ ret_val = snd_card_create(card_index, card_id, THIS_MODULE, 0, &card); if (ret_val) { - pr_err("sst: snd_card_create fail\n"); + pr_err("snd_card_create fail\n"); goto free_allocs; } @@ -1092,7 +1095,7 @@ int __devinit snd_intelmad_probe(struct platform_device *pdev) /* registering with LPE driver to get access to SST APIs to use */ ret_val = snd_intelmad_sst_register(intelmaddata); if (ret_val) { - pr_err("sst: snd_intelmad_sst_register failed\n"); + pr_err("snd_intelmad_sst_register failed\n"); goto free_allocs; } @@ -1100,19 +1103,19 @@ int __devinit snd_intelmad_probe(struct platform_device *pdev) ret_val = snd_intelmad_pcm(card, intelmaddata); if (ret_val) { - pr_err("sst: snd_intelmad_pcm failed\n"); + pr_err("snd_intelmad_pcm failed\n"); goto free_allocs; } ret_val = snd_intelmad_mixer(intelmaddata); if (ret_val) { - pr_err("sst: snd_intelmad_mixer failed\n"); + pr_err("snd_intelmad_mixer failed\n"); goto free_allocs; } ret_val = snd_intelmad_jack(intelmaddata); if (ret_val) { - pr_err("sst: snd_intelmad_jack failed\n"); + pr_err("snd_intelmad_jack failed\n"); goto free_allocs; } @@ -1126,31 +1129,31 @@ int __devinit snd_intelmad_probe(struct platform_device *pdev) ret_val = snd_intelmad_register_irq(intelmaddata); if (ret_val) { - pr_err("sst: snd_intelmad_register_irq fail\n"); + pr_err("snd_intelmad_register_irq fail\n"); goto free_allocs; } /* internal function call to register device with ALSA */ ret_val = snd_intelmad_create(intelmaddata, card); if (ret_val) { - pr_err("sst: snd_intelmad_create failed\n"); + pr_err("snd_intelmad_create failed\n"); goto free_allocs; } card->private_data = &intelmaddata; snd_card_set_dev(card, &pdev->dev); ret_val = snd_card_register(card); if (ret_val) { - pr_err("sst: snd_card_register failed\n"); + pr_err("snd_card_register failed\n"); goto free_allocs; } - pr_debug("sst:snd_intelmad_probe complete\n"); + pr_debug("snd_intelmad_probe complete\n"); return ret_val; free_mad_jack_wq: destroy_workqueue(intelmaddata->mad_jack_wq); free_allocs: - pr_err("sst: probe failed\n"); + pr_err("probe failed\n"); snd_card_free(card); kfree(intelmaddata->sstdrv_ops); kfree(intelmaddata); @@ -1200,7 +1203,7 @@ static struct platform_driver snd_intelmad_driver = { */ static int __init alsa_card_intelmad_init(void) { - pr_debug("sst: mad_init called\n"); + pr_debug("mad_init called\n"); return platform_driver_register(&snd_intelmad_driver); } @@ -1211,7 +1214,7 @@ static int __init alsa_card_intelmad_init(void) */ static void __exit alsa_card_intelmad_exit(void) { - pr_debug("sst:mad_exit called\n"); + pr_debug("mad_exit called\n"); return platform_driver_unregister(&snd_intelmad_driver); } diff --git a/trunk/drivers/staging/intel_sst/intelmid_ctrl.c b/trunk/drivers/staging/intel_sst/intelmid_ctrl.c index 03b4ece02f91..0d9135715c74 100644 --- a/trunk/drivers/staging/intel_sst/intelmid_ctrl.c +++ b/trunk/drivers/staging/intel_sst/intelmid_ctrl.c @@ -24,6 +24,9 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ALSA driver handling mixer controls for Intel MAD chipset */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include "jack.h" @@ -216,7 +219,7 @@ static int snd_intelmad_volume_get(struct snd_kcontrol *kcontrol, struct snd_intelmad *intelmaddata; struct snd_pmic_ops *scard_ops; - pr_debug("sst: snd_intelmad_volume_get called\n"); + pr_debug("snd_intelmad_volume_get called\n"); WARN_ON(!uval); WARN_ON(!kcontrol); @@ -273,7 +276,7 @@ static int snd_intelmad_mute_get(struct snd_kcontrol *kcontrol, struct snd_intelmad *intelmaddata; struct snd_pmic_ops *scard_ops; - pr_debug("sst: Mute_get called\n"); + pr_debug("Mute_get called\n"); WARN_ON(!uval); WARN_ON(!kcontrol); @@ -332,7 +335,7 @@ static int snd_intelmad_volume_set(struct snd_kcontrol *kcontrol, struct snd_intelmad *intelmaddata; struct snd_pmic_ops *scard_ops; - pr_debug("sst: volume set called:%ld %ld\n", + pr_debug("volume set called:%ld %ld\n", uval->value.integer.value[0], uval->value.integer.value[1]); @@ -387,7 +390,7 @@ static int snd_intelmad_mute_set(struct snd_kcontrol *kcontrol, struct snd_intelmad *intelmaddata; struct snd_pmic_ops *scard_ops; - pr_debug("sst: snd_intelmad_mute_set called\n"); + pr_debug("snd_intelmad_mute_set called\n"); WARN_ON(!uval); WARN_ON(!kcontrol); @@ -455,7 +458,7 @@ static int snd_intelmad_device_get(struct snd_kcontrol *kcontrol, { struct snd_intelmad *intelmaddata; struct snd_pmic_ops *scard_ops; - pr_debug("sst: device_get called\n"); + pr_debug("device_get called\n"); WARN_ON(!uval); WARN_ON(!kcontrol); @@ -492,7 +495,7 @@ static int snd_intelmad_device_set(struct snd_kcontrol *kcontrol, struct snd_pmic_ops *scard_ops; int ret_val = 0, vendor, status; - pr_debug("sst: snd_intelmad_device_set called\n"); + pr_debug("snd_intelmad_device_set called\n"); WARN_ON(!uval); WARN_ON(!kcontrol); diff --git a/trunk/drivers/staging/intel_sst/intelmid_msic_control.c b/trunk/drivers/staging/intel_sst/intelmid_msic_control.c index 4d1755efceef..da093ed0cd88 100644 --- a/trunk/drivers/staging/intel_sst/intelmid_msic_control.c +++ b/trunk/drivers/staging/intel_sst/intelmid_msic_control.c @@ -24,6 +24,8 @@ * This file contains the control operations of msic vendors */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include "intel_sst.h" @@ -83,7 +85,7 @@ static int msic_init_card(void) snd_msic_ops.cap_on = 0; snd_msic_ops.input_dev_id = DMIC; /*def dev*/ snd_msic_ops.output_dev_id = STEREO_HEADPHONE; - pr_debug("sst: msic init complete!!\n"); + pr_debug("msic init complete!!\n"); return 0; } @@ -173,7 +175,7 @@ static int msic_power_up_pb(unsigned int device) return retval; } - pr_debug("sst: powering up pb.... Device %d\n", device); + pr_debug("powering up pb.... Device %d\n", device); sst_sc_reg_access(sc_access1, PMIC_WRITE, 4); switch (device) { case SND_SST_DEVICE_HEADSET: @@ -205,7 +207,7 @@ static int msic_power_up_pb(unsigned int device) break; default: - pr_warn("sst: Wrong Device %d, selected %d\n", + pr_warn("Wrong Device %d, selected %d\n", device, snd_msic_ops.output_dev_id); } return sst_sc_reg_access(sc_access_pcm2, PMIC_READ_MODIFY, 1); @@ -268,7 +270,7 @@ static int msic_power_up_cp(unsigned int device) return retval; } - pr_debug("sst: powering up cp....%d\n", snd_msic_ops.input_dev_id); + pr_debug("powering up cp....%d\n", snd_msic_ops.input_dev_id); sst_sc_reg_access(sc_access2, PMIC_READ_MODIFY, 1); snd_msic_ops.cap_on = 1; if (snd_msic_ops.input_dev_id == AMIC) @@ -283,7 +285,7 @@ static int msic_power_down(void) { int retval = 0; - pr_debug("sst: powering dn msic\n"); + pr_debug("powering dn msic\n"); snd_msic_ops.pb_on = 0; snd_msic_ops.cap_on = 0; return retval; @@ -293,7 +295,7 @@ static int msic_power_down_pb(void) { int retval = 0; - pr_debug("sst: powering dn pb....\n"); + pr_debug("powering dn pb....\n"); snd_msic_ops.pb_on = 0; return retval; } @@ -302,7 +304,7 @@ static int msic_power_down_cp(void) { int retval = 0; - pr_debug("sst: powering dn cp....\n"); + pr_debug("powering dn cp....\n"); snd_msic_ops.cap_on = 0; return retval; } @@ -311,7 +313,7 @@ static int msic_set_selected_output_dev(u8 value) { int retval = 0; - pr_debug("sst: msic set selected output:%d\n", value); + pr_debug("msic set selected output:%d\n", value); snd_msic_ops.output_dev_id = value; if (snd_msic_ops.pb_on) msic_power_up_pb(SND_SST_DEVICE_HEADSET); @@ -330,15 +332,15 @@ static int msic_set_selected_input_dev(u8 value) }; int retval = 0; - pr_debug("sst: msic_set_selected_input_dev:%d\n", value); + pr_debug("msic_set_selected_input_dev:%d\n", value); snd_msic_ops.input_dev_id = value; switch (value) { case AMIC: - pr_debug("sst: Selecting AMIC1\n"); + pr_debug("Selecting AMIC1\n"); retval = sst_sc_reg_access(sc_access_amic, PMIC_WRITE, 1); break; case DMIC: - pr_debug("sst: Selecting DMIC1\n"); + pr_debug("Selecting DMIC1\n"); retval = sst_sc_reg_access(sc_access_dmic, PMIC_WRITE, 1); break; default: diff --git a/trunk/drivers/staging/intel_sst/intelmid_pvt.c b/trunk/drivers/staging/intel_sst/intelmid_pvt.c index 9ed9475ccc7b..4f9bdf364dca 100644 --- a/trunk/drivers/staging/intel_sst/intelmid_pvt.c +++ b/trunk/drivers/staging/intel_sst/intelmid_pvt.c @@ -23,6 +23,9 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ALSA driver for Intel MID sound card chipset - holding private functions */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -50,7 +53,7 @@ void period_elapsed(void *mad_substream) if (stream->stream_status != RUNNING) return; - pr_debug("sst: calling period elapsed\n"); + pr_debug("calling period elapsed\n"); snd_pcm_period_elapsed(substream); return; } @@ -76,8 +79,8 @@ int snd_intelmad_alloc_stream(struct snd_pcm_substream *substream) param.uc.pcm_params.period_count = substream->runtime->period_size; param.uc.pcm_params.ring_buffer_addr = virt_to_phys(substream->runtime->dma_area); - pr_debug("sst: period_cnt = %d\n", param.uc.pcm_params.period_count); - pr_debug("sst: sfreq= %d, wd_sz = %d\n", + pr_debug("period_cnt = %d\n", param.uc.pcm_params.period_count); + pr_debug("sfreq= %d, wd_sz = %d\n", param.uc.pcm_params.sfreq, param.uc.pcm_params.pcm_wd_sz); str_params.sparams = param; @@ -85,16 +88,16 @@ int snd_intelmad_alloc_stream(struct snd_pcm_substream *substream) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { str_params.ops = STREAM_OPS_PLAYBACK; - pr_debug("sst: Playbck stream,Device %d\n", stream->device); + pr_debug("Playbck stream,Device %d\n", stream->device); } else { str_params.ops = STREAM_OPS_CAPTURE; stream->device = SND_SST_DEVICE_CAPTURE; - pr_debug("sst: Capture stream,Device %d\n", stream->device); + pr_debug("Capture stream,Device %d\n", stream->device); } str_params.device_type = stream->device; ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_ALLOC, &str_params); - pr_debug("sst: SST_SND_PLAY/CAPTURE ret_val = %x\n", + pr_debug("SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val); if (ret_val < 0) return ret_val; @@ -102,7 +105,7 @@ int snd_intelmad_alloc_stream(struct snd_pcm_substream *substream) stream->stream_info.str_id = ret_val; stream->stream_status = INIT; stream->stream_info.buffer_ptr = 0; - pr_debug("sst: str id : %d\n", stream->stream_info.str_id); + pr_debug("str id : %d\n", stream->stream_info.str_id); return ret_val; } @@ -113,7 +116,7 @@ int snd_intelmad_init_stream(struct snd_pcm_substream *substream) struct snd_intelmad *intelmaddata = snd_pcm_substream_chip(substream); int ret_val; - pr_debug("sst: setting buffer ptr param\n"); + pr_debug("setting buffer ptr param\n"); stream->stream_info.period_elapsed = period_elapsed; stream->stream_info.mad_substream = substream; stream->stream_info.buffer_ptr = 0; @@ -121,7 +124,7 @@ int snd_intelmad_init_stream(struct snd_pcm_substream *substream) ret_val = intelmaddata->sstdrv_ops->control_set(SST_SND_STREAM_INIT, &stream->stream_info); if (ret_val) - pr_err("sst: control_set ret error %d\n", ret_val); + pr_err("control_set ret error %d\n", ret_val); return ret_val; } @@ -146,7 +149,7 @@ int sst_sc_reg_access(struct sc_reg_access *sc_access, retval = intel_scu_ipc_iowrite8(sc_access[i].reg_addr, sc_access[i].value); if (retval) { - pr_err("sst: IPC write failed!!! %d\n", retval); + pr_err("IPC write failed!!! %d\n", retval); return retval; } } @@ -155,7 +158,7 @@ int sst_sc_reg_access(struct sc_reg_access *sc_access, retval = intel_scu_ipc_ioread8(sc_access[i].reg_addr, &(sc_access[i].value)); if (retval) { - pr_err("sst: IPC read failed!!!!!%d\n", retval); + pr_err("IPC read failed!!!!!%d\n", retval); return retval; } } @@ -165,7 +168,7 @@ int sst_sc_reg_access(struct sc_reg_access *sc_access, sc_access[i].reg_addr, sc_access[i].value, sc_access[i].mask); if (retval) { - pr_err("sst: IPC Modify failed!!!%d\n", retval); + pr_err("IPC Modify failed!!!%d\n", retval); return retval; } } diff --git a/trunk/drivers/staging/intel_sst/intelmid_v0_control.c b/trunk/drivers/staging/intel_sst/intelmid_v0_control.c index f586d62ac9af..7859225e3d60 100644 --- a/trunk/drivers/staging/intel_sst/intelmid_v0_control.c +++ b/trunk/drivers/staging/intel_sst/intelmid_v0_control.c @@ -26,6 +26,8 @@ * This file contains the control operations of vendor 1 */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include "intel_sst.h" @@ -151,7 +153,7 @@ static int fs_power_up_pb(unsigned int port) if (retval) return retval; - pr_debug("sst: in fs power up pb\n"); + pr_debug("in fs power up pb\n"); return fs_enable_audiodac(UNMUTE); } @@ -173,7 +175,7 @@ static int fs_power_down_pb(void) if (retval) return retval; - pr_debug("sst: in fsl power down pb\n"); + pr_debug("in fsl power down pb\n"); return fs_enable_audiodac(UNMUTE); } @@ -380,7 +382,7 @@ static int fs_set_pcm_audio_params(int sfreq, int word_size, int num_channel) sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2); } - pr_debug("sst: sfreq:%d,Register value = %x\n", sfreq, config1); + pr_debug("sfreq:%d,Register value = %x\n", sfreq, config1); if (word_size == 24) { sc_access[0].reg_addr = AUDIOPORT1; @@ -438,18 +440,18 @@ static int fs_set_selected_input_dev(u8 value) switch (value) { case AMIC: - pr_debug("sst: Selecting amic not supported in mono cfg\n"); + pr_debug("Selecting amic not supported in mono cfg\n"); return sst_sc_reg_access(sc_access_mic, PMIC_READ_MODIFY, 2); break; case HS_MIC: - pr_debug("sst: Selecting hsmic\n"); + pr_debug("Selecting hsmic\n"); return sst_sc_reg_access(sc_access_hsmic, PMIC_READ_MODIFY, 2); break; case DMIC: - pr_debug("sst: Selecting dmic\n"); + pr_debug("Selecting dmic\n"); return sst_sc_reg_access(sc_access_dmic, PMIC_READ_MODIFY, 2); break; @@ -505,7 +507,7 @@ static int fs_set_mute(int dev_id, u8 value) return retval; - pr_debug("sst: dev_id:0x%x value:0x%x\n", dev_id, value); + pr_debug("dev_id:0x%x value:0x%x\n", dev_id, value); switch (dev_id) { case PMIC_SND_DMIC_MUTE: sc_access[0].reg_addr = MICCTRL; @@ -606,7 +608,7 @@ static int fs_set_vol(int dev_id, int value) switch (dev_id) { case PMIC_SND_LEFT_PB_VOL: - pr_debug("sst: PMIC_SND_LEFT_PB_VOL:%d\n", value); + pr_debug("PMIC_SND_LEFT_PB_VOL:%d\n", value); sc_access[0].value = sc_access[1].value = value; sc_access[0].reg_addr = AUD16; sc_access[1].reg_addr = AUD15; @@ -616,7 +618,7 @@ static int fs_set_vol(int dev_id, int value) break; case PMIC_SND_RIGHT_PB_VOL: - pr_debug("sst: PMIC_SND_RIGHT_PB_VOL:%d\n", value); + pr_debug("PMIC_SND_RIGHT_PB_VOL:%d\n", value); sc_access[0].value = sc_access[1].value = value; sc_access[0].reg_addr = AUD17; sc_access[1].reg_addr = AUD15; @@ -629,7 +631,7 @@ static int fs_set_vol(int dev_id, int value) reg_num = 2; break; case PMIC_SND_CAPTURE_VOL: - pr_debug("sst: PMIC_SND_CAPTURE_VOL:%d\n", value); + pr_debug("PMIC_SND_CAPTURE_VOL:%d\n", value); sc_access[0].reg_addr = MICLICTRL1; sc_access[1].reg_addr = MICLICTRL2; sc_access[2].reg_addr = DMICCTRL1; @@ -726,17 +728,17 @@ static int fs_get_vol(int dev_id, int *value) switch (dev_id) { case PMIC_SND_CAPTURE_VOL: - pr_debug("sst: PMIC_SND_CAPTURE_VOL\n"); + pr_debug("PMIC_SND_CAPTURE_VOL\n"); sc_access.reg_addr = MICLICTRL1; mask = (MASK5|MASK4|MASK3|MASK2|MASK1|MASK0); break; case PMIC_SND_LEFT_PB_VOL: - pr_debug("sst: PMIC_SND_LEFT_PB_VOL\n"); + pr_debug("PMIC_SND_LEFT_PB_VOL\n"); sc_access.reg_addr = AUD16; mask = (MASK5|MASK4|MASK3|MASK2|MASK1|MASK0); break; case PMIC_SND_RIGHT_PB_VOL: - pr_debug("sst: PMIC_SND_RT_PB_VOL\n"); + pr_debug("PMIC_SND_RT_PB_VOL\n"); sc_access.reg_addr = AUD17; mask = (MASK5|MASK4|MASK3|MASK2|MASK1|MASK0); break; @@ -745,9 +747,9 @@ static int fs_get_vol(int dev_id, int *value) } retval = sst_sc_reg_access(&sc_access, PMIC_READ, 1); - pr_debug("sst: value read = 0x%x\n", sc_access.value); + pr_debug("value read = 0x%x\n", sc_access.value); *value = (int) (sc_access.value & mask); - pr_debug("sst: value returned = 0x%x\n", *value); + pr_debug("value returned = 0x%x\n", *value); return retval; } diff --git a/trunk/drivers/staging/intel_sst/intelmid_v1_control.c b/trunk/drivers/staging/intel_sst/intelmid_v1_control.c index 9de86b2f6b08..62a932bf809a 100644 --- a/trunk/drivers/staging/intel_sst/intelmid_v1_control.c +++ b/trunk/drivers/staging/intel_sst/intelmid_v1_control.c @@ -25,6 +25,8 @@ * This file contains the control operations of vendor 2 */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -150,11 +152,11 @@ static int mx_init_capture_card(void) retval = sst_sc_reg_access(sc_access, PMIC_WRITE, 8); if (0 != retval) { /* pmic communication fails */ - pr_debug("sst: pmic commn failed\n"); + pr_debug("pmic commn failed\n"); return retval; } - pr_debug("sst: Capture configuration complete!!\n"); + pr_debug("Capture configuration complete!!\n"); return 0; } @@ -174,11 +176,11 @@ static int mx_init_playback_card(void) retval = sst_sc_reg_access(sc_access, PMIC_WRITE, 9); if (0 != retval) { /* pmic communication fails */ - pr_debug("sst: pmic commn failed\n"); + pr_debug("pmic commn failed\n"); return retval; } - pr_debug("sst: Playback configuration complete!!\n"); + pr_debug("Playback configuration complete!!\n"); return 0; } @@ -204,7 +206,7 @@ static int mx_enable_audiodac(int value) retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 2); if (retval) return retval; - pr_debug("sst: mute status = %d", snd_pmic_ops_mx.mute_status); + pr_debug("mute status = %d\n", snd_pmic_ops_mx.mute_status); if (snd_pmic_ops_mx.mute_status == MUTE || snd_pmic_ops_mx.master_mute == MUTE) return retval; @@ -412,7 +414,7 @@ static int mx_set_pcm_voice_params(void) if (retval) return retval; } - pr_debug("sst: SST DBG mx_set_pcm_voice_params called\n"); + pr_debug("SST DBG:mx_set_pcm_voice_params called\n"); return sst_sc_reg_access(sc_access, PMIC_WRITE, 44); } @@ -529,7 +531,7 @@ static int mx_set_selected_output_dev(u8 dev_id) return retval; } - pr_debug("sst: mx_set_selected_output_dev dev_id:0x%x\n", dev_id); + pr_debug("mx_set_selected_output_dev dev_id:0x%x\n", dev_id); snd_pmic_ops_mx.output_dev_id = dev_id; switch (dev_id) { case STEREO_HEADPHONE: @@ -549,7 +551,7 @@ static int mx_set_selected_output_dev(u8 dev_id) num_reg = 1; break; case RECEIVER: - pr_debug("sst: RECEIVER Koski selected\n"); + pr_debug("RECEIVER Koski selected\n"); /* configuration - AS enable, receiver enable */ sc_access[0].reg_addr = 0xFF; @@ -559,7 +561,7 @@ static int mx_set_selected_output_dev(u8 dev_id) num_reg = 1; break; default: - pr_err("sst: Not a valid output dev\n"); + pr_err("Not a valid output dev\n"); return 0; } return sst_sc_reg_access(sc_access, PMIC_WRITE, num_reg); @@ -598,7 +600,7 @@ static int mx_set_selected_input_dev(u8 dev_id) return retval; } snd_pmic_ops_mx.input_dev_id = dev_id; - pr_debug("sst: mx_set_selected_input_dev dev_id:0x%x\n", dev_id); + pr_debug("mx_set_selected_input_dev dev_id:0x%x\n", dev_id); switch (dev_id) { case AMIC: @@ -646,7 +648,7 @@ static int mx_set_mute(int dev_id, u8 value) } - pr_debug("sst: set_mute dev_id:0x%x , value:%d\n", dev_id, value); + pr_debug("set_mute dev_id:0x%x , value:%d\n", dev_id, value); switch (dev_id) { case PMIC_SND_DMIC_MUTE: @@ -760,7 +762,7 @@ static int mx_set_vol(int dev_id, int value) if (retval) return retval; } - pr_debug("sst: set_vol dev_id:0x%x ,value:%d\n", dev_id, value); + pr_debug("set_vol dev_id:0x%x ,value:%d\n", dev_id, value); switch (dev_id) { case PMIC_SND_RECEIVER_VOL: return 0; @@ -875,7 +877,7 @@ static int mx_get_vol(int dev_id, int *value) if (retval) return retval; *value = -(sc_access.value & mask); - pr_debug("sst: get volume value extracted %d\n", *value); + pr_debug("get volume value extracted %d\n", *value); return retval; } diff --git a/trunk/drivers/staging/intel_sst/intelmid_v2_control.c b/trunk/drivers/staging/intel_sst/intelmid_v2_control.c index 3a7de769842a..81cb9d70870b 100644 --- a/trunk/drivers/staging/intel_sst/intelmid_v2_control.c +++ b/trunk/drivers/staging/intel_sst/intelmid_v2_control.c @@ -26,6 +26,8 @@ * This file contains the control operations of vendor 3 */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include "intel_sst.h" @@ -120,7 +122,7 @@ static int nc_init_card(void) snd_pmic_ops_nc.master_mute = UNMUTE; snd_pmic_ops_nc.mute_status = UNMUTE; sst_sc_reg_access(sc_access, PMIC_WRITE, 26); - pr_debug("sst: init complete!!\n"); + pr_debug("init complete!!\n"); return 0; } @@ -169,7 +171,7 @@ static int nc_power_up_pb(unsigned int port) nc_enable_audiodac(MUTE); msleep(30); - pr_debug("sst: powering up pb....\n"); + pr_debug("powering up pb....\n"); sc_access[0].reg_addr = VAUDIOCNT; sc_access[0].value = 0x27; @@ -222,7 +224,7 @@ static int nc_power_up_cp(unsigned int port) return retval; - pr_debug("sst: powering up cp....\n"); + pr_debug("powering up cp....\n"); if (port == 0xFF) return 0; @@ -275,7 +277,7 @@ static int nc_power_down(void) nc_enable_audiodac(MUTE); - pr_debug("sst: powering dn nc_power_down ....\n"); + pr_debug("powering dn nc_power_down ....\n"); msleep(30); @@ -324,7 +326,7 @@ static int nc_power_down_pb(void) if (retval) return retval; - pr_debug("sst: powering dn pb....\n"); + pr_debug("powering dn pb....\n"); nc_enable_audiodac(MUTE); @@ -370,7 +372,7 @@ static int nc_power_down_cp(void) if (retval) return retval; - pr_debug("sst: powering dn cp....\n"); + pr_debug("powering dn cp....\n"); return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1); } @@ -400,7 +402,7 @@ static int nc_set_pcm_voice_params(void) return retval; sst_sc_reg_access(sc_access, PMIC_WRITE, 14); - pr_debug("sst: Voice parameters set successfully!!\n"); + pr_debug("Voice parameters set successfully!!\n"); return 0; } @@ -451,20 +453,20 @@ static int nc_set_pcm_audio_params(int sfreq, int word_size, int num_channel) sc_access.value = 0x07; sc_access.reg_addr = RMUTE; - pr_debug("sst: RIGHT_HP_MUTE value%d\n", sc_access.value); + pr_debug("RIGHT_HP_MUTE value%d\n", sc_access.value); sc_access.mask = MASK2; sst_sc_reg_access(&sc_access, PMIC_READ_MODIFY, 1); } else { sc_access.value = 0x00; sc_access.reg_addr = RMUTE; - pr_debug("sst: RIGHT_HP_MUTE value %d\n", sc_access.value); + pr_debug("RIGHT_HP_MUTE value %d\n", sc_access.value); sc_access.mask = MASK2; sst_sc_reg_access(&sc_access, PMIC_READ_MODIFY, 1); } - pr_debug("sst: word_size = %d\n", word_size); + pr_debug("word_size = %d\n", word_size); if (word_size == 24) { sc_access.reg_addr = AUDIOPORT2; @@ -477,7 +479,7 @@ static int nc_set_pcm_audio_params(int sfreq, int word_size, int num_channel) } sst_sc_reg_access(&sc_access, PMIC_READ_MODIFY, 1); - pr_debug("sst: word_size = %d\n", word_size); + pr_debug("word_size = %d\n", word_size); sc_access.reg_addr = AUDIOPORT1; sc_access.mask = MASK5|MASK4|MASK1|MASK0; if (word_size == 16) @@ -508,7 +510,7 @@ static int nc_set_selected_output_dev(u8 value) retval = nc_init_card(); if (retval) return retval; - pr_debug("sst: nc set selected output:%d\n", value); + pr_debug("nc set selected output:%d\n", value); switch (value) { case STEREO_HEADPHONE: retval = sst_sc_reg_access(sc_access_HP, PMIC_WRITE, 2); @@ -517,7 +519,7 @@ static int nc_set_selected_output_dev(u8 value) retval = sst_sc_reg_access(sc_access_IS, PMIC_WRITE, 2); break; default: - pr_err("sst: rcvd illegal request: %d\n", value); + pr_err("rcvd illegal request: %d\n", value); return -EINVAL; } return retval; @@ -541,7 +543,7 @@ static int nc_audio_init(void) }; sst_sc_reg_access(sc_access, PMIC_WRITE, 12); - pr_debug("sst: Audio Init successfully!!\n"); + pr_debug("Audio Init successfully!!\n"); /*set output device */ nc_set_selected_output_dev(snd_pmic_ops_nc.output_dev_id); @@ -549,13 +551,13 @@ static int nc_audio_init(void) if (snd_pmic_ops_nc.num_channel == 1) { sc_acces.value = 0x07; sc_acces.reg_addr = RMUTE; - pr_debug("sst: RIGHT_HP_MUTE value%d\n", sc_acces.value); + pr_debug("RIGHT_HP_MUTE value%d\n", sc_acces.value); sc_acces.mask = MASK2; sst_sc_reg_access(&sc_acces, PMIC_READ_MODIFY, 1); } else { sc_acces.value = 0x00; sc_acces.reg_addr = RMUTE; - pr_debug("sst: RIGHT_HP_MUTE value%d\n", sc_acces.value); + pr_debug("RIGHT_HP_MUTE value%d\n", sc_acces.value); sc_acces.mask = MASK2; sst_sc_reg_access(&sc_acces, PMIC_READ_MODIFY, 1); } @@ -629,11 +631,11 @@ static int nc_set_mute(int dev_id, u8 value) if (retval) return retval; - pr_debug("sst: set device id::%d, value %d\n", dev_id, value); + pr_debug("set device id::%d, value %d\n", dev_id, value); switch (dev_id) { case PMIC_SND_MUTE_ALL: - pr_debug("sst: PMIC_SND_MUTE_ALL value %d\n", value); + pr_debug("PMIC_SND_MUTE_ALL value %d\n", value); snd_pmic_ops_nc.mute_status = value; snd_pmic_ops_nc.master_mute = value; if (value == UNMUTE) { @@ -669,7 +671,7 @@ static int nc_set_mute(int dev_id, u8 value) } break; case PMIC_SND_HP_MIC_MUTE: - pr_debug("sst: PMIC_SND_HPMIC_MUTE value %d\n", value); + pr_debug("PMIC_SND_HPMIC_MUTE value %d\n", value); if (value == UNMUTE) { /* unmute the system, set the 6th bit to one */ sc_access[0].value = 0x00; @@ -682,7 +684,7 @@ static int nc_set_mute(int dev_id, u8 value) retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1); break; case PMIC_SND_AMIC_MUTE: - pr_debug("sst: PMIC_SND_AMIC_MUTE value %d\n", value); + pr_debug("PMIC_SND_AMIC_MUTE value %d\n", value); if (value == UNMUTE) { /* unmute the system, set the 6th bit to one */ sc_access[0].value = 0x00; @@ -696,7 +698,7 @@ static int nc_set_mute(int dev_id, u8 value) break; case PMIC_SND_DMIC_MUTE: - pr_debug("sst: INPUT_MUTE_DMIC value%d\n", value); + pr_debug("INPUT_MUTE_DMIC value%d\n", value); if (value == UNMUTE) { /* unmute the system, set the 6th bit to one */ sc_access[1].value = 0x00; @@ -724,13 +726,13 @@ static int nc_set_mute(int dev_id, u8 value) if (dev_id == PMIC_SND_LEFT_HP_MUTE) { sc_access[0].reg_addr = LMUTE; - pr_debug("sst: LEFT_HP_MUTE value %d\n", + pr_debug("LEFT_HP_MUTE value %d\n", sc_access[0].value); } else { if (snd_pmic_ops_nc.num_channel == 1) sc_access[0].value = 0x04; sc_access[0].reg_addr = RMUTE; - pr_debug("sst: RIGHT_HP_MUTE value %d\n", + pr_debug("RIGHT_HP_MUTE value %d\n", sc_access[0].value); } sc_access[0].mask = MASK2; @@ -743,7 +745,7 @@ static int nc_set_mute(int dev_id, u8 value) else sc_access[0].value = 0x03; sc_access[0].reg_addr = LMUTE; - pr_debug("sst: SPEAKER_MUTE %d\n", sc_access[0].value); + pr_debug("SPEAKER_MUTE %d\n", sc_access[0].value); sc_access[0].mask = MASK1; retval = sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 1); break; @@ -764,10 +766,10 @@ static int nc_set_vol(int dev_id, int value) if (retval) return retval; - pr_debug("sst: set volume:%d\n", dev_id); + pr_debug("set volume:%d\n", dev_id); switch (dev_id) { case PMIC_SND_CAPTURE_VOL: - pr_debug("sst: PMIC_SND_CAPTURE_VOL:value::%d\n", value); + pr_debug("PMIC_SND_CAPTURE_VOL:value::%d\n", value); sc_access[0].value = sc_access[1].value = sc_access[2].value = -value; sc_access[0].mask = sc_access[1].mask = sc_access[2].mask = @@ -779,7 +781,7 @@ static int nc_set_vol(int dev_id, int value) break; case PMIC_SND_LEFT_PB_VOL: - pr_debug("sst: PMIC_SND_LEFT_HP_VOL %d\n", value); + pr_debug("PMIC_SND_LEFT_HP_VOL %d\n", value); sc_access[0].value = -value; sc_access[0].reg_addr = AUDIOLVOL; sc_access[0].mask = @@ -788,7 +790,7 @@ static int nc_set_vol(int dev_id, int value) break; case PMIC_SND_RIGHT_PB_VOL: - pr_debug("sst: PMIC_SND_RIGHT_HP_VOL value %d\n", value); + pr_debug("PMIC_SND_RIGHT_HP_VOL value %d\n", value); if (snd_pmic_ops_nc.num_channel == 1) { sc_access[0].value = 0x04; sc_access[0].reg_addr = RMUTE; @@ -821,11 +823,11 @@ static int nc_set_selected_input_dev(u8 value) return retval; snd_pmic_ops_nc.input_dev_id = value; - pr_debug("sst: nc set selected input:%d\n", value); + pr_debug("nc set selected input:%d\n", value); switch (value) { case AMIC: - pr_debug("sst: Selecting AMIC\n"); + pr_debug("Selecting AMIC\n"); sc_access[0].reg_addr = 0x107; sc_access[0].value = 0x40; sc_access[0].mask = MASK6|MASK4|MASK3|MASK1|MASK0; @@ -842,7 +844,7 @@ static int nc_set_selected_input_dev(u8 value) break; case HS_MIC: - pr_debug("sst: Selecting HS_MIC\n"); + pr_debug("Selecting HS_MIC\n"); sc_access[0].reg_addr = 0x107; sc_access[0].mask = MASK6|MASK4|MASK3|MASK1|MASK0; sc_access[0].value = 0x10; @@ -859,7 +861,7 @@ static int nc_set_selected_input_dev(u8 value) break; case DMIC: - pr_debug("sst: DMIC\n"); + pr_debug("DMIC\n"); sc_access[0].reg_addr = 0x107; sc_access[0].mask = MASK6|MASK4|MASK3|MASK1|MASK0; sc_access[0].value = 0x0B; @@ -890,23 +892,23 @@ static int nc_get_mute(int dev_id, u8 *value) if (retval) return retval; - pr_debug("sst: get mute::%d\n", dev_id); + pr_debug("get mute::%d\n", dev_id); switch (dev_id) { case PMIC_SND_AMIC_MUTE: - pr_debug("sst: PMIC_SND_INPUT_MUTE_MIC1\n"); + pr_debug("PMIC_SND_INPUT_MUTE_MIC1\n"); sc_access.reg_addr = LILSEL; mask = MASK6; break; case PMIC_SND_HP_MIC_MUTE: - pr_debug("sst: PMIC_SND_INPUT_MUTE_MIC2\n"); + pr_debug("PMIC_SND_INPUT_MUTE_MIC2\n"); sc_access.reg_addr = LIRSEL; mask = MASK6; break; case PMIC_SND_LEFT_HP_MUTE: case PMIC_SND_RIGHT_HP_MUTE: mask = MASK2; - pr_debug("sst: PMIC_SN_LEFT/RIGHT_HP_MUTE\n"); + pr_debug("PMIC_SN_LEFT/RIGHT_HP_MUTE\n"); if (dev_id == PMIC_SND_RIGHT_HP_MUTE) sc_access.reg_addr = RMUTE; else @@ -914,12 +916,12 @@ static int nc_get_mute(int dev_id, u8 *value) break; case PMIC_SND_LEFT_SPEAKER_MUTE: - pr_debug("sst: PMIC_MONO_EARPIECE_MUTE\n"); + pr_debug("PMIC_MONO_EARPIECE_MUTE\n"); sc_access.reg_addr = RMUTE; mask = MASK1; break; case PMIC_SND_DMIC_MUTE: - pr_debug("sst: PMIC_SND_INPUT_MUTE_DMIC\n"); + pr_debug("PMIC_SND_INPUT_MUTE_DMIC\n"); sc_access.reg_addr = 0x105; mask = MASK6; break; @@ -928,16 +930,16 @@ static int nc_get_mute(int dev_id, u8 *value) } retval = sst_sc_reg_access(&sc_access, PMIC_READ, 1); - pr_debug("sst: reg value = %d\n", sc_access.value); + pr_debug("reg value = %d\n", sc_access.value); if (retval) return retval; *value = (sc_access.value) & mask; - pr_debug("sst: masked value = %d\n", *value); + pr_debug("masked value = %d\n", *value); if (*value) *value = 0; else *value = 1; - pr_debug("sst: value returned = 0x%x\n", *value); + pr_debug("value returned = 0x%x\n", *value); return retval; } @@ -953,19 +955,19 @@ static int nc_get_vol(int dev_id, int *value) switch (dev_id) { case PMIC_SND_CAPTURE_VOL: - pr_debug("sst: PMIC_SND_INPUT_CAPTURE_VOL\n"); + pr_debug("PMIC_SND_INPUT_CAPTURE_VOL\n"); sc_access.reg_addr = LILSEL; mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5); break; case PMIC_SND_RIGHT_PB_VOL: - pr_debug("sst: GET_VOLUME_PMIC_LEFT_HP_VOL\n"); + pr_debug("GET_VOLUME_PMIC_LEFT_HP_VOL\n"); sc_access.reg_addr = AUDIOLVOL; mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6); break; case PMIC_SND_LEFT_PB_VOL: - pr_debug("sst: GET_VOLUME_PMIC_RIGHT_HP_VOL\n"); + pr_debug("GET_VOLUME_PMIC_RIGHT_HP_VOL\n"); sc_access.reg_addr = AUDIORVOL; mask = (MASK0|MASK1|MASK2|MASK3|MASK4|MASK5|MASK6); break; @@ -975,9 +977,9 @@ static int nc_get_vol(int dev_id, int *value) } retval = sst_sc_reg_access(&sc_access, PMIC_READ, 1); - pr_debug("sst: value read = 0x%x\n", sc_access.value); + pr_debug("value read = 0x%x\n", sc_access.value); *value = -((sc_access.value) & mask); - pr_debug("sst: get vol value returned = %d\n", *value); + pr_debug("get vol value returned = %d\n", *value); return retval; } diff --git a/trunk/drivers/staging/msm/Makefile b/trunk/drivers/staging/msm/Makefile index bb3606faf20e..07a89ecfcc2b 100644 --- a/trunk/drivers/staging/msm/Makefile +++ b/trunk/drivers/staging/msm/Makefile @@ -41,11 +41,11 @@ obj-$(CONFIG_FB_MSM_EBI2) += ebi2_lcd.o obj-$(CONFIG_FB_MSM_LCDC) += lcdc.o # MDDI -msm_mddi-objs := mddi.o mddihost.o mddihosti.o +msm_mddi-y := mddi.o mddihost.o mddihosti.o obj-$(CONFIG_FB_MSM_MDDI) += msm_mddi.o # External MDDI -msm_mddi_ext-objs := mddihost_e.o mddi_ext.o +msm_mddi_ext-y := mddihost_e.o mddi_ext.o obj-$(CONFIG_FB_MSM_EXTMDDI) += msm_mddi_ext.o # TVEnc diff --git a/trunk/drivers/staging/pohmelfs/crypto.c b/trunk/drivers/staging/pohmelfs/crypto.c index 2fdb3e01460d..6540864216c8 100644 --- a/trunk/drivers/staging/pohmelfs/crypto.c +++ b/trunk/drivers/staging/pohmelfs/crypto.c @@ -130,10 +130,8 @@ int pohmelfs_crypto_engine_init(struct pohmelfs_crypto_engine *e, struct pohmelf void pohmelfs_crypto_engine_exit(struct pohmelfs_crypto_engine *e) { - if (e->hash) - crypto_free_hash(e->hash); - if (e->cipher) - crypto_free_ablkcipher(e->cipher); + crypto_free_hash(e->hash); + crypto_free_ablkcipher(e->cipher); kfree(e->data); } diff --git a/trunk/drivers/staging/rtl8192u/r8192U_core.c b/trunk/drivers/staging/rtl8192u/r8192U_core.c index 494f180acc26..4cc7b418c91e 100644 --- a/trunk/drivers/staging/rtl8192u/r8192U_core.c +++ b/trunk/drivers/staging/rtl8192u/r8192U_core.c @@ -1507,7 +1507,7 @@ static void rtl8192_tx_isr(struct urb *tx_urb) { // // Handle HW Beacon: - // We had transfer our beacon frame to host controler at this moment. + // We had transfer our beacon frame to host controller at this moment. // // // Caution: diff --git a/trunk/drivers/staging/ste_rmi4/Kconfig b/trunk/drivers/staging/ste_rmi4/Kconfig new file mode 100644 index 000000000000..95fd5a915f0a --- /dev/null +++ b/trunk/drivers/staging/ste_rmi4/Kconfig @@ -0,0 +1,9 @@ +config TOUCHSCREEN_SYNAPTICS_I2C_RMI4 + tristate "Synaptics i2c rmi4 touchscreen" + depends on I2C + help + Say Y here if you have a Synaptics RMI4 and + want to enable support for the built-in touchscreen. + + To compile this driver as a module, choose M here: the + module will be called synaptics_rmi4_ts. diff --git a/trunk/drivers/staging/ste_rmi4/Makefile b/trunk/drivers/staging/ste_rmi4/Makefile new file mode 100644 index 000000000000..6cce2ed187ef --- /dev/null +++ b/trunk/drivers/staging/ste_rmi4/Makefile @@ -0,0 +1,4 @@ +# +# Makefile for the RMI4 touchscreen driver. +# +obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += synaptics_i2c_rmi4.o diff --git a/trunk/drivers/staging/ste_rmi4/TODO b/trunk/drivers/staging/ste_rmi4/TODO new file mode 100644 index 000000000000..9be2437da85f --- /dev/null +++ b/trunk/drivers/staging/ste_rmi4/TODO @@ -0,0 +1,7 @@ +TODO +---- + +Wait for the official upstream synaptics rmi4 clearpad drivers as promised over the past few months +Merge any device support needed from this driver into it +Delete this driver + diff --git a/trunk/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c b/trunk/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c new file mode 100644 index 000000000000..e8f047e86a32 --- /dev/null +++ b/trunk/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c @@ -0,0 +1,1179 @@ +/** + * + * Synaptics Register Mapped Interface (RMI4) I2C Physical Layer Driver. + * Copyright (c) 2007-2010, Synaptics Incorporated + * + * Author: Js HA for ST-Ericsson + * Author: Naveen Kumar G for ST-Ericsson + * Copyright 2010 (c) ST-Ericsson AB + */ +/* + * This file is licensed under the GPL2 license. + * + *############################################################################# + * GPL + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include "synaptics_i2c_rmi4.h" + +/* TODO: for multiple device support will need a per-device mutex */ +#define DRIVER_NAME "synaptics_rmi4_i2c" + +#define MAX_ERROR_REPORT 6 +#define MAX_TOUCH_MAJOR 15 +#define MAX_RETRY_COUNT 5 +#define STD_QUERY_LEN 21 +#define PAGE_LEN 2 +#define DATA_BUF_LEN 32 +#define BUF_LEN 37 +#define QUERY_LEN 9 +#define DATA_LEN 12 +#define HAS_TAP 0x01 +#define HAS_PALMDETECT 0x01 +#define HAS_ROTATE 0x02 +#define HAS_TAPANDHOLD 0x02 +#define HAS_DOUBLETAP 0x04 +#define HAS_EARLYTAP 0x08 +#define HAS_RELEASE 0x08 +#define HAS_FLICK 0x10 +#define HAS_PRESS 0x20 +#define HAS_PINCH 0x40 + +#define MASK_16BIT 0xFFFF +#define MASK_8BIT 0xFF +#define MASK_7BIT 0x7F +#define MASK_5BIT 0x1F +#define MASK_4BIT 0x0F +#define MASK_3BIT 0x07 +#define MASK_2BIT 0x03 +#define TOUCHPAD_CTRL_INTR 0x8 +#define PDT_START_SCAN_LOCATION (0x00E9) +#define PDT_END_SCAN_LOCATION (0x000A) +#define PDT_ENTRY_SIZE (0x0006) +#define RMI4_NUMBER_OF_MAX_FINGERS (8) +#define SYNAPTICS_RMI4_TOUCHPAD_FUNC_NUM (0x11) +#define SYNAPTICS_RMI4_DEVICE_CONTROL_FUNC_NUM (0x01) + +/** + * struct synaptics_rmi4_fn_desc - contains the funtion descriptor information + * @query_base_addr: base address for query + * @cmd_base_addr: base address for command + * @ctrl_base_addr: base address for control + * @data_base_addr: base address for data + * @intr_src_count: count for the interrupt source + * @fn_number: function number + * + * This structure is used to gives the function descriptor information + * of the particular functionality. + */ +struct synaptics_rmi4_fn_desc { + unsigned char query_base_addr; + unsigned char cmd_base_addr; + unsigned char ctrl_base_addr; + unsigned char data_base_addr; + unsigned char intr_src_count; + unsigned char fn_number; +}; + +/** + * struct synaptics_rmi4_fn - contains the funtion information + * @fn_number: function number + * @num_of_data_sources: number of data sources + * @num_of_data_points: number of fingers touched + * @size_of_data_register_block: data register block size + * @index_to_intr_reg: index for interrupt register + * @intr_mask: interrupt mask value + * @fn_desc: variable for function descriptor structure + * @link: linked list for function descriptors + * + * This structure gives information about the number of data sources and + * the number of data registers associated with the function. + */ +struct synaptics_rmi4_fn { + unsigned char fn_number; + unsigned char num_of_data_sources; + unsigned char num_of_data_points; + unsigned char size_of_data_register_block; + unsigned char index_to_intr_reg; + unsigned char intr_mask; + struct synaptics_rmi4_fn_desc fn_desc; + struct list_head link; +}; + +/** + * struct synaptics_rmi4_device_info - contains the rmi4 device information + * @version_major: protocol major version number + * @version_minor: protocol minor version number + * @manufacturer_id: manufacturer identification byte + * @product_props: product properties information + * @product_info: product info array + * @date_code: device manufacture date + * @tester_id: tester id array + * @serial_number: serial number for that device + * @product_id_string: product id for the device + * @support_fn_list: linked list for device information + * + * This structure gives information about the number of data sources and + * the number of data registers associated with the function. + */ +struct synaptics_rmi4_device_info { + unsigned int version_major; + unsigned int version_minor; + unsigned char manufacturer_id; + unsigned char product_props; + unsigned char product_info[2]; + unsigned char date_code[3]; + unsigned short tester_id; + unsigned short serial_number; + unsigned char product_id_string[11]; + struct list_head support_fn_list; +}; + +/** + * struct synaptics_rmi4_data - contains the rmi4 device data + * @rmi4_mod_info: structure variable for rmi4 device info + * @input_dev: pointer for input device + * @i2c_client: pointer for i2c client + * @board: constant pointer for touch platform data + * @fn_list_mutex: mutex for funtion list + * @rmi4_page_mutex: mutex for rmi4 page + * @current_page: variable for integer + * @number_of_interrupt_register: interrupt registers count + * @fn01_ctrl_base_addr: control base address for fn01 + * @fn01_query_base_addr: query base address for fn01 + * @fn01_data_base_addr: data base address for fn01 + * @sensor_max_x: sensor maximum x value + * @sensor_max_y: sensor maximum y value + * @regulator: pointer to the regulator structure + * @wait: wait queue structure variable + * @touch_stopped: flag to stop the thread function + * + * This structure gives the device data information. + */ +struct synaptics_rmi4_data { + struct synaptics_rmi4_device_info rmi4_mod_info; + struct input_dev *input_dev; + struct i2c_client *i2c_client; + const struct synaptics_rmi4_platform_data *board; + struct mutex fn_list_mutex; + struct mutex rmi4_page_mutex; + int current_page; + unsigned int number_of_interrupt_register; + unsigned short fn01_ctrl_base_addr; + unsigned short fn01_query_base_addr; + unsigned short fn01_data_base_addr; + int sensor_max_x; + int sensor_max_y; + struct regulator *regulator; + wait_queue_head_t wait; + bool touch_stopped; +}; + +/** + * synaptics_rmi4_set_page() - sets the page + * @pdata: pointer to synaptics_rmi4_data structure + * @address: set the address of the page + * + * This function is used to set the page and returns integer. + */ +static int synaptics_rmi4_set_page(struct synaptics_rmi4_data *pdata, + unsigned int address) +{ + unsigned char txbuf[PAGE_LEN]; + int retval; + unsigned int page; + struct i2c_client *i2c = pdata->i2c_client; + + page = ((address >> 8) & MASK_8BIT); + if (page != pdata->current_page) { + txbuf[0] = MASK_8BIT; + txbuf[1] = page; + retval = i2c_master_send(i2c, txbuf, PAGE_LEN); + if (retval != PAGE_LEN) + dev_err(&i2c->dev, "%s:failed:%d\n", __func__, retval); + else + pdata->current_page = page; + } else + retval = PAGE_LEN; + return retval; +} +/** + * synaptics_rmi4_i2c_block_read() - read the block of data + * @pdata: pointer to synaptics_rmi4_data structure + * @address: read the block of data from this offset + * @valp: pointer to a buffer containing the data to be read + * @size: number of bytes to read + * + * This function is to read the block of data and returns integer. + */ +static int synaptics_rmi4_i2c_block_read(struct synaptics_rmi4_data *pdata, + unsigned short address, + unsigned char *valp, int size) +{ + int retval = 0; + int retry_count = 0; + int index; + struct i2c_client *i2c = pdata->i2c_client; + + mutex_lock(&(pdata->rmi4_page_mutex)); + retval = synaptics_rmi4_set_page(pdata, address); + if (retval != PAGE_LEN) + goto exit; + index = address & MASK_8BIT; +retry: + retval = i2c_smbus_read_i2c_block_data(i2c, index, size, valp); + if (retval != size) { + if (++retry_count == MAX_RETRY_COUNT) + dev_err(&i2c->dev, + "%s:address 0x%04x size %d failed:%d\n", + __func__, address, size, retval); + else { + synaptics_rmi4_set_page(pdata, address); + goto retry; + } + } +exit: + mutex_unlock(&(pdata->rmi4_page_mutex)); + return retval; +} + +/** + * synaptics_rmi4_i2c_byte_write() - write the single byte data + * @pdata: pointer to synaptics_rmi4_data structure + * @address: write the block of data from this offset + * @data: data to be write + * + * This function is to write the single byte data and returns integer. + */ +static int synaptics_rmi4_i2c_byte_write(struct synaptics_rmi4_data *pdata, + unsigned short address, + unsigned char data) +{ + unsigned char txbuf[2]; + int retval = 0; + struct i2c_client *i2c = pdata->i2c_client; + + /* Can't have anyone else changing the page behind our backs */ + mutex_lock(&(pdata->rmi4_page_mutex)); + + retval = synaptics_rmi4_set_page(pdata, address); + if (retval != PAGE_LEN) + goto exit; + txbuf[0] = address & MASK_8BIT; + txbuf[1] = data; + retval = i2c_master_send(pdata->i2c_client, txbuf, 2); + /* Add in retry on writes only in certian error return values */ + if (retval != 2) { + dev_err(&i2c->dev, "%s:failed:%d\n", __func__, retval); + retval = -EIO; + } else + retval = 1; +exit: + mutex_unlock(&(pdata->rmi4_page_mutex)); + return retval; +} + +/** + * synpatics_rmi4_touchpad_report() - reports for the rmi4 touchpad device + * @pdata: pointer to synaptics_rmi4_data structure + * @rfi: pointer to synaptics_rmi4_fn structure + * + * This function calls to reports for the rmi4 touchpad device + */ +static int synpatics_rmi4_touchpad_report(struct synaptics_rmi4_data *pdata, + struct synaptics_rmi4_fn *rfi) +{ + /* number of touch points - fingers down in this case */ + int touch_count = 0; + int finger; + int fingers_supported; + int finger_registers; + int reg; + int finger_shift; + int finger_status; + int retval; + unsigned short data_base_addr; + unsigned short data_offset; + unsigned char data_reg_blk_size; + unsigned char values[2]; + unsigned char data[DATA_LEN]; + int x[RMI4_NUMBER_OF_MAX_FINGERS]; + int y[RMI4_NUMBER_OF_MAX_FINGERS]; + int wx[RMI4_NUMBER_OF_MAX_FINGERS]; + int wy[RMI4_NUMBER_OF_MAX_FINGERS]; + struct i2c_client *client = pdata->i2c_client; + + /* get 2D sensor finger data */ + /* + * First get the finger status field - the size of the finger status + * field is determined by the number of finger supporte - 2 bits per + * finger, so the number of registers to read is: + * registerCount = ceil(numberOfFingers/4). + * Read the required number of registers and check each 2 bit field to + * determine if a finger is down: + * 00 = finger not present, + * 01 = finger present and data accurate, + * 10 = finger present but data may not be accurate, + * 11 = reserved for product use. + */ + fingers_supported = rfi->num_of_data_points; + finger_registers = (fingers_supported + 3)/4; + data_base_addr = rfi->fn_desc.data_base_addr; + retval = synaptics_rmi4_i2c_block_read(pdata, data_base_addr, values, + finger_registers); + if (retval != finger_registers) { + dev_err(&client->dev, "%s:read status registers failed\n", + __func__); + return 0; + } + /* + * For each finger present, read the proper number of registers + * to get absolute data. + */ + data_reg_blk_size = rfi->size_of_data_register_block; + for (finger = 0; finger < fingers_supported; finger++) { + /* determine which data byte the finger status is in */ + reg = finger/4; + /* bit shift to get finger's status */ + finger_shift = (finger % 4) * 2; + finger_status = (values[reg] >> finger_shift) & 3; + /* + * if finger status indicates a finger is present then + * read the finger data and report it + */ + if (finger_status == 1 || finger_status == 2) { + /* Read the finger data */ + data_offset = data_base_addr + + ((finger * data_reg_blk_size) + + finger_registers); + retval = synaptics_rmi4_i2c_block_read(pdata, + data_offset, data, + data_reg_blk_size); + if (retval != data_reg_blk_size) { + printk(KERN_ERR "%s:read data failed\n", + __func__); + return 0; + } else { + x[touch_count] = + (data[0] << 4) | (data[2] & MASK_4BIT); + y[touch_count] = + (data[1] << 4) | + ((data[2] >> 4) & MASK_4BIT); + wy[touch_count] = + (data[3] >> 4) & MASK_4BIT; + wx[touch_count] = + (data[3] & MASK_4BIT); + + if (pdata->board->x_flip) + x[touch_count] = + pdata->sensor_max_x - + x[touch_count]; + if (pdata->board->y_flip) + y[touch_count] = + pdata->sensor_max_y - + y[touch_count]; + } + /* number of active touch points */ + touch_count++; + } + } + + /* report to input subsystem */ + if (touch_count) { + for (finger = 0; finger < touch_count; finger++) { + input_report_abs(pdata->input_dev, ABS_MT_TOUCH_MAJOR, + max(wx[finger] , wy[finger])); + input_report_abs(pdata->input_dev, ABS_MT_POSITION_X, + x[finger]); + input_report_abs(pdata->input_dev, ABS_MT_POSITION_Y, + y[finger]); + input_mt_sync(pdata->input_dev); + } + } else + input_mt_sync(pdata->input_dev); + + /* sync after groups of events */ + input_sync(pdata->input_dev); + /* return the number of touch points */ + return touch_count; +} + +/** + * synaptics_rmi4_report_device() - reports the rmi4 device + * @pdata: pointer to synaptics_rmi4_data structure + * @rfi: pointer to synaptics_rmi4_fn + * + * This function is used to call the report function of the rmi4 device. + */ +static int synaptics_rmi4_report_device(struct synaptics_rmi4_data *pdata, + struct synaptics_rmi4_fn *rfi) +{ + int touch = 0; + struct i2c_client *client = pdata->i2c_client; + static int num_error_reports; + if (rfi->fn_number != SYNAPTICS_RMI4_TOUCHPAD_FUNC_NUM) { + num_error_reports++; + if (num_error_reports < MAX_ERROR_REPORT) + dev_err(&client->dev, "%s:report not supported\n", + __func__); + } else + touch = synpatics_rmi4_touchpad_report(pdata, rfi); + return touch; +} +/** + * synaptics_rmi4_sensor_report() - reports to input subsystem + * @pdata: pointer to synaptics_rmi4_data structure + * + * This function is used to reads in all data sources and reports + * them to the input subsystem. + */ +static int synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *pdata) +{ + unsigned char intr_status[4]; + /* number of touch points - fingers or buttons */ + int touch = 0; + unsigned int retval; + struct synaptics_rmi4_fn *rfi; + struct synaptics_rmi4_device_info *rmi; + struct i2c_client *client = pdata->i2c_client; + + /* + * Get the interrupt status from the function $01 + * control register+1 to find which source(s) were interrupting + * so we can read the data from the source(s) (2D sensor, buttons..) + */ + retval = synaptics_rmi4_i2c_block_read(pdata, + pdata->fn01_data_base_addr + 1, + intr_status, + pdata->number_of_interrupt_register); + if (retval != pdata->number_of_interrupt_register) { + dev_err(&client->dev, + "could not read interrupt status registers\n"); + return 0; + } + /* + * check each function that has data sources and if the interrupt for + * that triggered then call that RMI4 functions report() function to + * gather data and report it to the input subsystem + */ + rmi = &(pdata->rmi4_mod_info); + list_for_each_entry(rfi, &rmi->support_fn_list, link) { + if (rfi->num_of_data_sources) { + if (intr_status[rfi->index_to_intr_reg] & + rfi->intr_mask) + touch = synaptics_rmi4_report_device(pdata, + rfi); + } + } + /* return the number of touch points */ + return touch; +} + +/** + * synaptics_rmi4_irq() - thread function for rmi4 attention line + * @irq: irq value + * @data: void pointer + * + * This function is interrupt thread function. It just notifies the + * application layer that attention is required. + */ +static irqreturn_t synaptics_rmi4_irq(int irq, void *data) +{ + struct synaptics_rmi4_data *pdata = data; + int touch_count; + do { + touch_count = synaptics_rmi4_sensor_report(pdata); + if (touch_count) + wait_event_timeout(pdata->wait, pdata->touch_stopped, + msecs_to_jiffies(1)); + else + break; + } while (!pdata->touch_stopped); + return IRQ_HANDLED; +} + +/** + * synpatics_rmi4_touchpad_detect() - detects the rmi4 touchpad device + * @pdata: pointer to synaptics_rmi4_data structure + * @rfi: pointer to synaptics_rmi4_fn structure + * @fd: pointer to synaptics_rmi4_fn_desc structure + * @interruptcount: count the number of interrupts + * + * This function calls to detects the rmi4 touchpad device + */ +static int synpatics_rmi4_touchpad_detect(struct synaptics_rmi4_data *pdata, + struct synaptics_rmi4_fn *rfi, + struct synaptics_rmi4_fn_desc *fd, + unsigned int interruptcount) +{ + unsigned char queries[QUERY_LEN]; + unsigned short intr_offset; + unsigned char abs_data_size; + unsigned char abs_data_blk_size; + unsigned char egr_0, egr_1; + unsigned int all_data_blk_size; + int has_pinch, has_flick, has_tap; + int has_tapandhold, has_doubletap; + int has_earlytap, has_press; + int has_palmdetect, has_rotate; + int has_rel; + int i; + int retval; + struct i2c_client *client = pdata->i2c_client; + + rfi->fn_desc.query_base_addr = fd->query_base_addr; + rfi->fn_desc.data_base_addr = fd->data_base_addr; + rfi->fn_desc.intr_src_count = fd->intr_src_count; + rfi->fn_desc.fn_number = fd->fn_number; + rfi->fn_number = fd->fn_number; + rfi->num_of_data_sources = fd->intr_src_count; + rfi->fn_desc.ctrl_base_addr = fd->ctrl_base_addr; + rfi->fn_desc.cmd_base_addr = fd->cmd_base_addr; + + /* + * need to get number of fingers supported, data size, etc. + * to be used when getting data since the number of registers to + * read depends on the number of fingers supported and data size. + */ + retval = synaptics_rmi4_i2c_block_read(pdata, fd->query_base_addr, + queries, + sizeof(queries)); + if (retval != sizeof(queries)) { + dev_err(&client->dev, "%s:read function query registers\n", + __func__); + return retval; + } + /* + * 2D data sources have only 3 bits for the number of fingers + * supported - so the encoding is a bit wierd. + */ + if ((queries[1] & MASK_3BIT) <= 4) + /* add 1 since zero based */ + rfi->num_of_data_points = (queries[1] & MASK_3BIT) + 1; + else { + /* + * a value of 5 is up to 10 fingers - 6 and 7 are reserved + * (shouldn't get these i int retval;n a normal 2D source). + */ + if ((queries[1] & MASK_3BIT) == 5) + rfi->num_of_data_points = 10; + } + /* Need to get interrupt info for handling interrupts */ + rfi->index_to_intr_reg = (interruptcount + 7)/8; + if (rfi->index_to_intr_reg != 0) + rfi->index_to_intr_reg -= 1; + /* + * loop through interrupts for each source in fn $11 + * and or in a bit to the interrupt mask for each. + */ + intr_offset = interruptcount % 8; + rfi->intr_mask = 0; + for (i = intr_offset; + i < ((fd->intr_src_count & MASK_3BIT) + intr_offset); i++) + rfi->intr_mask |= 1 << i; + + /* Size of just the absolute data for one finger */ + abs_data_size = queries[5] & MASK_2BIT; + /* One each for X and Y, one for LSB for X & Y, one for W, one for Z */ + abs_data_blk_size = 3 + (2 * (abs_data_size == 0 ? 1 : 0)); + rfi->size_of_data_register_block = abs_data_blk_size; + + /* + * need to determine the size of data to read - this depends on + * conditions such as whether Relative data is reported and if Gesture + * data is reported. + */ + egr_0 = queries[7]; + egr_1 = queries[8]; + + /* + * Get info about what EGR data is supported, whether it has + * Relative data supported, etc. + */ + has_pinch = egr_0 & HAS_PINCH; + has_flick = egr_0 & HAS_FLICK; + has_tap = egr_0 & HAS_TAP; + has_earlytap = egr_0 & HAS_EARLYTAP; + has_press = egr_0 & HAS_PRESS; + has_rotate = egr_1 & HAS_ROTATE; + has_rel = queries[1] & HAS_RELEASE; + has_tapandhold = egr_0 & HAS_TAPANDHOLD; + has_doubletap = egr_0 & HAS_DOUBLETAP; + has_palmdetect = egr_1 & HAS_PALMDETECT; + + /* + * Size of all data including finger status, absolute data for each + * finger, relative data and EGR data + */ + all_data_blk_size = + /* finger status, four fingers per register */ + ((rfi->num_of_data_points + 3) / 4) + + /* absolute data, per finger times number of fingers */ + (abs_data_blk_size * rfi->num_of_data_points) + + /* + * two relative registers (if relative is being reported) + */ + 2 * has_rel + + /* + * F11_2D_data8 is only present if the egr_0 + * register is non-zero. + */ + !!(egr_0) + + /* + * F11_2D_data9 is only present if either egr_0 or + * egr_1 registers are non-zero. + */ + (egr_0 || egr_1) + + /* + * F11_2D_data10 is only present if EGR_PINCH or EGR_FLICK of + * egr_0 reports as 1. + */ + !!(has_pinch | has_flick) + + /* + * F11_2D_data11 and F11_2D_data12 are only present if + * EGR_FLICK of egr_0 reports as 1. + */ + 2 * !!(has_flick); + return retval; +} + +/** + * synpatics_rmi4_touchpad_config() - confiures the rmi4 touchpad device + * @pdata: pointer to synaptics_rmi4_data structure + * @rfi: pointer to synaptics_rmi4_fn structure + * + * This function calls to confiures the rmi4 touchpad device + */ +int synpatics_rmi4_touchpad_config(struct synaptics_rmi4_data *pdata, + struct synaptics_rmi4_fn *rfi) +{ + /* + * For the data source - print info and do any + * source specific configuration. + */ + unsigned char data[BUF_LEN]; + int retval = 0; + struct i2c_client *client = pdata->i2c_client; + + /* Get and print some info about the data source... */ + /* To Query 2D devices we need to read from the address obtained + * from the function descriptor stored in the RMI function info. + */ + retval = synaptics_rmi4_i2c_block_read(pdata, + rfi->fn_desc.query_base_addr, + data, QUERY_LEN); + if (retval != QUERY_LEN) + dev_err(&client->dev, "%s:read query registers failed\n", + __func__); + else { + retval = synaptics_rmi4_i2c_block_read(pdata, + rfi->fn_desc.ctrl_base_addr, + data, DATA_BUF_LEN); + if (retval != DATA_BUF_LEN) { + dev_err(&client->dev, + "%s:read control registers failed\n", + __func__); + return retval; + } + /* Store these for use later*/ + pdata->sensor_max_x = ((data[6] & MASK_8BIT) << 0) | + ((data[7] & MASK_4BIT) << 8); + pdata->sensor_max_y = ((data[8] & MASK_5BIT) << 0) | + ((data[9] & MASK_4BIT) << 8); + } + return retval; +} + +/** + * synaptics_rmi4_i2c_query_device() - query the rmi4 device + * @pdata: pointer to synaptics_rmi4_data structure + * + * This function is used to query the rmi4 device. + */ +static int synaptics_rmi4_i2c_query_device(struct synaptics_rmi4_data *pdata) +{ + int i; + int retval; + unsigned char std_queries[STD_QUERY_LEN]; + unsigned char intr_count = 0; + int data_sources = 0; + unsigned int ctrl_offset; + struct synaptics_rmi4_fn *rfi; + struct synaptics_rmi4_fn_desc rmi_fd; + struct synaptics_rmi4_device_info *rmi; + struct i2c_client *client = pdata->i2c_client; + + /* + * init the physical drivers RMI module + * info list of functions + */ + INIT_LIST_HEAD(&pdata->rmi4_mod_info.support_fn_list); + + /* + * Read the Page Descriptor Table to determine what functions + * are present + */ + for (i = PDT_START_SCAN_LOCATION; i > PDT_END_SCAN_LOCATION; + i -= PDT_ENTRY_SIZE) { + retval = synaptics_rmi4_i2c_block_read(pdata, i, + (unsigned char *)&rmi_fd, + sizeof(rmi_fd)); + if (retval != sizeof(rmi_fd)) { + /* failed to read next PDT entry */ + dev_err(&client->dev, "%s: read error\n", __func__); + return -EIO; + } + rfi = NULL; + if (rmi_fd.fn_number) { + switch (rmi_fd.fn_number & MASK_8BIT) { + case SYNAPTICS_RMI4_DEVICE_CONTROL_FUNC_NUM: + pdata->fn01_query_base_addr = + rmi_fd.query_base_addr; + pdata->fn01_ctrl_base_addr = + rmi_fd.ctrl_base_addr; + pdata->fn01_data_base_addr = + rmi_fd.data_base_addr; + break; + case SYNAPTICS_RMI4_TOUCHPAD_FUNC_NUM: + if (rmi_fd.intr_src_count) { + rfi = kmalloc(sizeof(*rfi), + GFP_KERNEL); + if (!rfi) { + dev_err(&client->dev, + "%s:kmalloc failed\n", + __func__); + return -ENOMEM; + } + retval = synpatics_rmi4_touchpad_detect + (pdata, rfi, + &rmi_fd, + intr_count); + if (retval < 0) + return retval; + } + break; + } + /* interrupt count for next iteration */ + intr_count += (rmi_fd.intr_src_count & MASK_3BIT); + /* + * We only want to add functions to the list + * that have data associated with them. + */ + if (rfi && rmi_fd.intr_src_count) { + /* link this function info to the RMI module */ + mutex_lock(&(pdata->fn_list_mutex)); + list_add_tail(&rfi->link, + &pdata->rmi4_mod_info.support_fn_list); + mutex_unlock(&(pdata->fn_list_mutex)); + } + } else { + /* + * A zero in the function number + * signals the end of the PDT + */ + dev_dbg(&client->dev, + "%s:end of PDT\n", __func__); + break; + } + } + /* + * calculate the interrupt register count - used in the + * ISR to read the correct number of interrupt registers + */ + pdata->number_of_interrupt_register = (intr_count + 7) / 8; + /* + * Function $01 will be used to query the product properties, + * and product ID so we had to read the PDT above first to get + * the Fn $01 query address and prior to filling in the product + * info. NOTE: Even an unflashed device will still have FN $01. + */ + + /* Load up the standard queries and get the RMI4 module info */ + retval = synaptics_rmi4_i2c_block_read(pdata, + pdata->fn01_query_base_addr, + std_queries, + sizeof(std_queries)); + if (retval != sizeof(std_queries)) { + dev_err(&client->dev, "%s:Failed reading queries\n", + __func__); + return -EIO; + } + + /* Currently supported RMI version is 4.0 */ + pdata->rmi4_mod_info.version_major = 4; + pdata->rmi4_mod_info.version_minor = 0; + /* + * get manufacturer id, product_props, product info, + * date code, tester id, serial num and product id (name) + */ + pdata->rmi4_mod_info.manufacturer_id = std_queries[0]; + pdata->rmi4_mod_info.product_props = std_queries[1]; + pdata->rmi4_mod_info.product_info[0] = std_queries[2]; + pdata->rmi4_mod_info.product_info[1] = std_queries[3]; + /* year - 2001-2032 */ + pdata->rmi4_mod_info.date_code[0] = std_queries[4] & MASK_5BIT; + /* month - 1-12 */ + pdata->rmi4_mod_info.date_code[1] = std_queries[5] & MASK_4BIT; + /* day - 1-31 */ + pdata->rmi4_mod_info.date_code[2] = std_queries[6] & MASK_5BIT; + pdata->rmi4_mod_info.tester_id = ((std_queries[7] & MASK_7BIT) << 8) | + (std_queries[8] & MASK_7BIT); + pdata->rmi4_mod_info.serial_number = + ((std_queries[9] & MASK_7BIT) << 8) | + (std_queries[10] & MASK_7BIT); + memcpy(pdata->rmi4_mod_info.product_id_string, &std_queries[11], 10); + + /* Check if this is a Synaptics device - report if not. */ + if (pdata->rmi4_mod_info.manufacturer_id != 1) + dev_err(&client->dev, "%s: non-Synaptics mfg id:%d\n", + __func__, pdata->rmi4_mod_info.manufacturer_id); + + list_for_each_entry(rfi, &pdata->rmi4_mod_info.support_fn_list, link) + data_sources += rfi->num_of_data_sources; + if (data_sources) { + rmi = &(pdata->rmi4_mod_info); + list_for_each_entry(rfi, &rmi->support_fn_list, link) { + if (rfi->num_of_data_sources) { + if (rfi->fn_number == + SYNAPTICS_RMI4_TOUCHPAD_FUNC_NUM) { + retval = synpatics_rmi4_touchpad_config + (pdata, rfi); + if (retval < 0) + return retval; + } else + dev_err(&client->dev, + "%s:fn_number not supported\n", + __func__); + /* + * Turn on interrupts for this + * function's data sources. + */ + ctrl_offset = pdata->fn01_ctrl_base_addr + 1 + + rfi->index_to_intr_reg; + retval = synaptics_rmi4_i2c_byte_write(pdata, + ctrl_offset, + rfi->intr_mask); + if (retval < 0) + return retval; + } + } + } + return 0; +} + +/** + * synaptics_rmi4_probe() - Initialze the i2c-client touchscreen driver + * @i2c: i2c client structure pointer + * @id:i2c device id pointer + * + * This function will allocate and initialize the instance + * data and request the irq and set the instance data as the clients + * platform data then register the physical driver which will do a scan of + * the rmi4 Physical Device Table and enumerate any rmi4 functions that + * have data sources associated with them. + */ +static int __devinit synaptics_rmi4_probe + (struct i2c_client *client, const struct i2c_device_id *dev_id) +{ + int retval; + unsigned char intr_status[4]; + struct synaptics_rmi4_data *rmi4_data; + const struct synaptics_rmi4_platform_data *platformdata = + client->dev.platform_data; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, "i2c smbus byte data not supported\n"); + return -EIO; + } + + if (!platformdata) { + dev_err(&client->dev, "%s: no platform data\n", __func__); + return -EINVAL; + } + + /* Allocate and initialize the instance data for this client */ + rmi4_data = kzalloc(sizeof(struct synaptics_rmi4_data) * 2, + GFP_KERNEL); + if (!rmi4_data) { + dev_err(&client->dev, "%s: no memory allocated\n", __func__); + return -ENOMEM; + } + + rmi4_data->input_dev = input_allocate_device(); + if (rmi4_data->input_dev == NULL) { + dev_err(&client->dev, "%s:input device alloc failed\n", + __func__); + retval = -ENOMEM; + goto err_input; + } + + dev_set_name(&client->dev, platformdata->name); + + if (platformdata->regulator_en) { + rmi4_data->regulator = regulator_get(&client->dev, "v-touch"); + if (IS_ERR(rmi4_data->regulator)) { + dev_err(&client->dev, "%s:get regulator failed\n", + __func__); + retval = PTR_ERR(rmi4_data->regulator); + goto err_regulator; + } + regulator_enable(rmi4_data->regulator); + } + + init_waitqueue_head(&rmi4_data->wait); + /* + * Copy i2c_client pointer into RTID's i2c_client pointer for + * later use in rmi4_read, rmi4_write, etc. + */ + rmi4_data->i2c_client = client; + /* So we set the page correctly the first time */ + rmi4_data->current_page = MASK_16BIT; + rmi4_data->board = platformdata; + rmi4_data->touch_stopped = false; + + /* init the mutexes for maintain the lists */ + mutex_init(&(rmi4_data->fn_list_mutex)); + mutex_init(&(rmi4_data->rmi4_page_mutex)); + + /* + * Register physical driver - this will call the detect function that + * will then scan the device and determine the supported + * rmi4 functions. + */ + retval = synaptics_rmi4_i2c_query_device(rmi4_data); + if (retval) { + dev_err(&client->dev, "%s: rmi4 query device failed\n", + __func__); + goto err_query_dev; + } + + /* Store the instance data in the i2c_client */ + i2c_set_clientdata(client, rmi4_data); + + /*initialize the input device parameters */ + rmi4_data->input_dev->name = DRIVER_NAME; + rmi4_data->input_dev->phys = "Synaptics_Clearpad"; + rmi4_data->input_dev->id.bustype = BUS_I2C; + rmi4_data->input_dev->dev.parent = &client->dev; + input_set_drvdata(rmi4_data->input_dev, rmi4_data); + + /* Initialize the function handlers for rmi4 */ + set_bit(EV_SYN, rmi4_data->input_dev->evbit); + set_bit(EV_KEY, rmi4_data->input_dev->evbit); + set_bit(EV_ABS, rmi4_data->input_dev->evbit); + + input_set_abs_params(rmi4_data->input_dev, ABS_MT_POSITION_X, 0, + rmi4_data->sensor_max_x, 0, 0); + input_set_abs_params(rmi4_data->input_dev, ABS_MT_POSITION_Y, 0, + rmi4_data->sensor_max_y, 0, 0); + input_set_abs_params(rmi4_data->input_dev, ABS_MT_TOUCH_MAJOR, 0, + MAX_TOUCH_MAJOR, 0, 0); + + retval = input_register_device(rmi4_data->input_dev); + if (retval) { + dev_err(&client->dev, "%s:input register failed\n", __func__); + goto err_input_register; + } + + /* Clear interrupts */ + synaptics_rmi4_i2c_block_read(rmi4_data, + rmi4_data->fn01_data_base_addr + 1, intr_status, + rmi4_data->number_of_interrupt_register); + retval = request_threaded_irq(platformdata->irq_number, NULL, + synaptics_rmi4_irq, + platformdata->irq_type, + platformdata->name, rmi4_data); + if (retval) { + dev_err(&client->dev, "%s:Unable to get attn irq %d\n", + __func__, platformdata->irq_number); + goto err_request_irq; + } + + return retval; + +err_request_irq: + free_irq(platformdata->irq_number, rmi4_data); + input_unregister_device(rmi4_data->input_dev); +err_input_register: + i2c_set_clientdata(client, NULL); +err_query_dev: + if (platformdata->regulator_en) { + regulator_disable(rmi4_data->regulator); + regulator_put(rmi4_data->regulator); + } +err_regulator: + input_free_device(rmi4_data->input_dev); + rmi4_data->input_dev = NULL; +err_input: + kfree(rmi4_data); + + return retval; +} +/** + * synaptics_rmi4_remove() - Removes the i2c-client touchscreen driver + * @client: i2c client structure pointer + * + * This funtion uses to remove the i2c-client + * touchscreen driver and returns integer. + */ +static int __devexit synaptics_rmi4_remove(struct i2c_client *client) +{ + struct synaptics_rmi4_data *rmi4_data = i2c_get_clientdata(client); + const struct synaptics_rmi4_platform_data *pdata = rmi4_data->board; + + rmi4_data->touch_stopped = true; + wake_up(&rmi4_data->wait); + free_irq(pdata->irq_number, rmi4_data); + input_unregister_device(rmi4_data->input_dev); + if (pdata->regulator_en) { + regulator_disable(rmi4_data->regulator); + regulator_put(rmi4_data->regulator); + } + kfree(rmi4_data); + + return 0; +} + +#ifdef CONFIG_PM +/** + * synaptics_rmi4_suspend() - suspend the touch screen controller + * @dev: pointer to device structure + * + * This funtion is used to suspend the + * touch panel controller and returns integer + */ +static int synaptics_rmi4_suspend(struct device *dev) +{ + /* Touch sleep mode */ + int retval; + unsigned char intr_status; + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + const struct synaptics_rmi4_platform_data *pdata = rmi4_data->board; + + rmi4_data->touch_stopped = true; + disable_irq(pdata->irq_number); + + retval = synaptics_rmi4_i2c_block_read(rmi4_data, + rmi4_data->fn01_data_base_addr + 1, + &intr_status, + rmi4_data->number_of_interrupt_register); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_i2c_byte_write(rmi4_data, + rmi4_data->fn01_ctrl_base_addr + 1, + (intr_status & ~TOUCHPAD_CTRL_INTR)); + if (retval < 0) + return retval; + + if (pdata->regulator_en) + regulator_disable(rmi4_data->regulator); + + return 0; +} +/** + * synaptics_rmi4_resume() - resume the touch screen controller + * @dev: pointer to device structure + * + * This funtion is used to resume the touch panel + * controller and returns integer. + */ +static int synaptics_rmi4_resume(struct device *dev) +{ + int retval; + unsigned char intr_status; + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + const struct synaptics_rmi4_platform_data *pdata = rmi4_data->board; + + if (pdata->regulator_en) + regulator_enable(rmi4_data->regulator); + + enable_irq(pdata->irq_number); + rmi4_data->touch_stopped = false; + + retval = synaptics_rmi4_i2c_block_read(rmi4_data, + rmi4_data->fn01_data_base_addr + 1, + &intr_status, + rmi4_data->number_of_interrupt_register); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_i2c_byte_write(rmi4_data, + rmi4_data->fn01_ctrl_base_addr + 1, + (intr_status | TOUCHPAD_CTRL_INTR)); + if (retval < 0) + return retval; + + return 0; +} + +static const struct dev_pm_ops synaptics_rmi4_dev_pm_ops = { + .suspend = synaptics_rmi4_suspend, + .resume = synaptics_rmi4_resume, +}; +#endif + +static const struct i2c_device_id synaptics_rmi4_id_table[] = { + { DRIVER_NAME, 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, synaptics_rmi4_id_table); + +static struct i2c_driver synaptics_rmi4_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &synaptics_rmi4_dev_pm_ops, +#endif + }, + .probe = synaptics_rmi4_probe, + .remove = __devexit_p(synaptics_rmi4_remove), + .id_table = synaptics_rmi4_id_table, +}; +/** + * synaptics_rmi4_init() - Initialize the touchscreen driver + * + * This funtion uses to initializes the synaptics + * touchscreen driver and returns integer. + */ +static int __init synaptics_rmi4_init(void) +{ + return i2c_add_driver(&synaptics_rmi4_driver); +} +/** + * synaptics_rmi4_exit() - De-initialize the touchscreen driver + * + * This funtion uses to de-initialize the synaptics + * touchscreen driver and returns none. + */ +static void __exit synaptics_rmi4_exit(void) +{ + i2c_del_driver(&synaptics_rmi4_driver); +} + + +module_init(synaptics_rmi4_init); +module_exit(synaptics_rmi4_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("naveen.gaddipati@stericsson.com, js.ha@stericsson.com"); +MODULE_DESCRIPTION("synaptics rmi4 i2c touch Driver"); +MODULE_ALIAS("i2c:synaptics_rmi4_ts"); diff --git a/trunk/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h b/trunk/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h new file mode 100644 index 000000000000..820ae275fa2b --- /dev/null +++ b/trunk/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h @@ -0,0 +1,50 @@ +/** + * + * Synaptics Register Mapped Interface (RMI4) I2C Physical Layer Driver. + * Copyright (c) 2007-2010, Synaptics Incorporated + * + * Author: Js HA for ST-Ericsson + * Author: Naveen Kumar G for ST-Ericsson + * Copyright 2010 (c) ST-Ericsson AB + */ +/* + * This file is licensed under the GPL2 license. + * + *############################################################################# + * GPL + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * 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. + * + *############################################################################# + */ + +#ifndef _SYNAPTICS_RMI4_H_INCLUDED_ +#define _SYNAPTICS_RMI4_H_INCLUDED_ + +/** + * struct synaptics_rmi4_platform_data - contains the rmi4 platform data + * @irq_number: irq number + * @irq_type: irq type + * @x flip: x flip flag + * @y flip: y flip flag + * @regulator_en: regulator enable flag + * + * This structure gives platform data for rmi4. + */ +struct synaptics_rmi4_platform_data { + const char *name; + int irq_number; + int irq_type; + bool x_flip; + bool y_flip; + bool regulator_en; +}; + +#endif diff --git a/trunk/drivers/staging/vt6656/card.c b/trunk/drivers/staging/vt6656/card.c index 8de21aac1bff..a49053bd7c65 100644 --- a/trunk/drivers/staging/vt6656/card.c +++ b/trunk/drivers/staging/vt6656/card.c @@ -1092,7 +1092,7 @@ CARDbChannelSwitch ( pDevice->sMgmtObj.uCurrChannel = byNewChannel; bResult = CARDbSetMediaChannel(pDevice, byNewChannel); - return(bResult); + return bResult; } pDevice->byChannelSwitchCount = byCount; pDevice->byNewChannel = byNewChannel; diff --git a/trunk/drivers/staging/vt6656/dpc.c b/trunk/drivers/staging/vt6656/dpc.c index 1f9d29636803..f4fb0c6e4eac 100644 --- a/trunk/drivers/staging/vt6656/dpc.c +++ b/trunk/drivers/staging/vt6656/dpc.c @@ -1608,8 +1608,8 @@ void RXvMngWorkItem(void *Context) } } - pDevice->bIsRxMngWorkItemQueued = FALSE; - spin_unlock_irq(&pDevice->lock); + pDevice->bIsRxMngWorkItemQueued = FALSE; + spin_unlock_irq(&pDevice->lock); } diff --git a/trunk/drivers/staging/vt6656/rxtx.c b/trunk/drivers/staging/vt6656/rxtx.c index bbdc127a987d..8f18578a5903 100644 --- a/trunk/drivers/staging/vt6656/rxtx.c +++ b/trunk/drivers/staging/vt6656/rxtx.c @@ -68,8 +68,7 @@ /*--------------------- Static Classes ----------------------------*/ /*--------------------- Static Variables --------------------------*/ -//static int msglevel =MSG_LEVEL_DEBUG; -static int msglevel =MSG_LEVEL_INFO; +static int msglevel = MSG_LEVEL_INFO; /*--------------------- Static Functions --------------------------*/ diff --git a/trunk/drivers/staging/vt6656/tkip.c b/trunk/drivers/staging/vt6656/tkip.c index a6bd533f9577..0715636cb9cb 100644 --- a/trunk/drivers/staging/vt6656/tkip.c +++ b/trunk/drivers/staging/vt6656/tkip.c @@ -214,13 +214,14 @@ void TKIPvMixKey( /* Phase 1, step 2 */ for (i=0; i<8; i++) { j = 2*(i & 1); - p1k[0] = (p1k[0] + tkip_sbox( (p1k[4] ^ ((256*pbyTKey[1+j]) + pbyTKey[j])) % 65536 )) % 65536; - p1k[1] = (p1k[1] + tkip_sbox( (p1k[0] ^ ((256*pbyTKey[5+j]) + pbyTKey[4+j])) % 65536 )) % 65536; - p1k[2] = (p1k[2] + tkip_sbox( (p1k[1] ^ ((256*pbyTKey[9+j]) + pbyTKey[8+j])) % 65536 )) % 65536; - p1k[3] = (p1k[3] + tkip_sbox( (p1k[2] ^ ((256*pbyTKey[13+j]) + pbyTKey[12+j])) % 65536 )) % 65536; - p1k[4] = (p1k[4] + tkip_sbox( (p1k[3] ^ (((256*pbyTKey[1+j]) + pbyTKey[j]))) % 65536 )) % 65536; + p1k[0] = (p1k[0] + tkip_sbox((p1k[4] ^ ((256*pbyTKey[1+j]) + pbyTKey[j])) % 65536)) % 65536; + p1k[1] = (p1k[1] + tkip_sbox((p1k[0] ^ ((256*pbyTKey[5+j]) + pbyTKey[4+j])) % 65536)) % 65536; + p1k[2] = (p1k[2] + tkip_sbox((p1k[1] ^ ((256*pbyTKey[9+j]) + pbyTKey[8+j])) % 65536)) % 65536; + p1k[3] = (p1k[3] + tkip_sbox((p1k[2] ^ ((256*pbyTKey[13+j]) + pbyTKey[12+j])) % 65536)) % 65536; + p1k[4] = (p1k[4] + tkip_sbox((p1k[3] ^ (((256*pbyTKey[1+j]) + pbyTKey[j]))) % 65536)) % 65536; p1k[4] = (p1k[4] + i) % 65536; } + /* Phase 2, Step 1 */ ppk0 = p1k[0]; ppk1 = p1k[1]; @@ -230,19 +231,19 @@ void TKIPvMixKey( ppk5 = (p1k[4] + tsc2) % 65536; /* Phase2, Step 2 */ - ppk0 = ppk0 + tkip_sbox( (ppk5 ^ ((256*pbyTKey[1]) + pbyTKey[0])) % 65536); - ppk1 = ppk1 + tkip_sbox( (ppk0 ^ ((256*pbyTKey[3]) + pbyTKey[2])) % 65536); - ppk2 = ppk2 + tkip_sbox( (ppk1 ^ ((256*pbyTKey[5]) + pbyTKey[4])) % 65536); - ppk3 = ppk3 + tkip_sbox( (ppk2 ^ ((256*pbyTKey[7]) + pbyTKey[6])) % 65536); - ppk4 = ppk4 + tkip_sbox( (ppk3 ^ ((256*pbyTKey[9]) + pbyTKey[8])) % 65536); - ppk5 = ppk5 + tkip_sbox( (ppk4 ^ ((256*pbyTKey[11]) + pbyTKey[10])) % 65536); - - ppk0 = ppk0 + rotr1(ppk5 ^ ((256*pbyTKey[13]) + pbyTKey[12])); - ppk1 = ppk1 + rotr1(ppk0 ^ ((256*pbyTKey[15]) + pbyTKey[14])); - ppk2 = ppk2 + rotr1(ppk1); - ppk3 = ppk3 + rotr1(ppk2); - ppk4 = ppk4 + rotr1(ppk3); - ppk5 = ppk5 + rotr1(ppk4); + ppk0 = ppk0 + tkip_sbox((ppk5 ^ ((256*pbyTKey[1]) + pbyTKey[0])) % 65536); + ppk1 = ppk1 + tkip_sbox((ppk0 ^ ((256*pbyTKey[3]) + pbyTKey[2])) % 65536); + ppk2 = ppk2 + tkip_sbox((ppk1 ^ ((256*pbyTKey[5]) + pbyTKey[4])) % 65536); + ppk3 = ppk3 + tkip_sbox((ppk2 ^ ((256*pbyTKey[7]) + pbyTKey[6])) % 65536); + ppk4 = ppk4 + tkip_sbox((ppk3 ^ ((256*pbyTKey[9]) + pbyTKey[8])) % 65536); + ppk5 = ppk5 + tkip_sbox((ppk4 ^ ((256*pbyTKey[11]) + pbyTKey[10])) % 65536); + + ppk0 = ppk0 + rotr1(ppk5 ^ ((256*pbyTKey[13]) + pbyTKey[12])); + ppk1 = ppk1 + rotr1(ppk0 ^ ((256*pbyTKey[15]) + pbyTKey[14])); + ppk2 = ppk2 + rotr1(ppk1); + ppk3 = ppk3 + rotr1(ppk2); + ppk4 = ppk4 + rotr1(ppk3); + ppk5 = ppk5 + rotr1(ppk4); /* Phase 2, Step 3 */ pbyRC4Key[0] = (tsc2 >> 8) % 256; diff --git a/trunk/drivers/staging/winbond/core.h b/trunk/drivers/staging/winbond/core.h index 2b87a0007319..d7b3aca5ddeb 100644 --- a/trunk/drivers/staging/winbond/core.h +++ b/trunk/drivers/staging/winbond/core.h @@ -4,7 +4,7 @@ #include #include -#include "wbhal_s.h" +#include "wbhal.h" #include "mto.h" #include "mac_structures.h" diff --git a/trunk/drivers/staging/winbond/mds.c b/trunk/drivers/staging/winbond/mds.c index 9217762b1814..90f2cc019d3b 100644 --- a/trunk/drivers/staging/winbond/mds.c +++ b/trunk/drivers/staging/winbond/mds.c @@ -2,8 +2,9 @@ #include "mlmetxrx_f.h" #include "mto.h" #include "sysdef.h" -#include "wbhal_f.h" +#include "wbhal.h" #include "wblinux_f.h" +#include "wb35tx_f.h" unsigned char Mds_initial(struct wbsoft_priv *adapter) @@ -17,11 +18,6 @@ Mds_initial(struct wbsoft_priv *adapter) return hal_get_tx_buffer(&adapter->sHwData, &pMds->pTxBuffer); } -void -Mds_Destroy(struct wbsoft_priv *adapter) -{ -} - static void Mds_DurationSet(struct wbsoft_priv *adapter, struct wb35_descriptor *pDes, u8 *buffer) { struct T00_descriptor *pT00; diff --git a/trunk/drivers/staging/winbond/mds_f.h b/trunk/drivers/staging/winbond/mds_f.h index 7f68deae6d04..ce8be079e957 100644 --- a/trunk/drivers/staging/winbond/mds_f.h +++ b/trunk/drivers/staging/winbond/mds_f.h @@ -1,11 +1,10 @@ #ifndef __WINBOND_MDS_F_H #define __WINBOND_MDS_F_H -#include "wbhal_s.h" +#include "wbhal.h" #include "core.h" unsigned char Mds_initial(struct wbsoft_priv *adapter); -void Mds_Destroy(struct wbsoft_priv *adapter); void Mds_Tx(struct wbsoft_priv *adapter); void Mds_SendComplete(struct wbsoft_priv *adapter, struct T02_descriptor *pt02); void Mds_MpduProcess(struct wbsoft_priv *adapter, struct wb35_descriptor *prxdes); diff --git a/trunk/drivers/staging/winbond/mto.c b/trunk/drivers/staging/winbond/mto.c index 9cd212783d61..1faebceceff7 100644 --- a/trunk/drivers/staging/winbond/mto.c +++ b/trunk/drivers/staging/winbond/mto.c @@ -19,7 +19,9 @@ #include "sysdef.h" #include "sme_api.h" -#include "wbhal_f.h" +#include "wbhal.h" +#include "wb35reg_f.h" +#include "core.h" /* Declare SQ3 to rate and fragmentation threshold table */ /* Declare fragmentation thresholds table */ diff --git a/trunk/drivers/staging/winbond/phy_calibration.c b/trunk/drivers/staging/winbond/phy_calibration.c index 2b375ba3812a..0658b09c7853 100644 --- a/trunk/drivers/staging/winbond/phy_calibration.c +++ b/trunk/drivers/staging/winbond/phy_calibration.c @@ -12,7 +12,9 @@ /****************** INCLUDE FILES SECTION ***********************************/ #include "sysdef.h" #include "phy_calibration.h" -#include "wbhal_f.h" +#include "wbhal.h" +#include "wb35reg_f.h" +#include "core.h" /****************** DEBUG CONSTANT AND MACRO SECTION ************************/ diff --git a/trunk/drivers/staging/winbond/phy_calibration.h b/trunk/drivers/staging/winbond/phy_calibration.h index 303203148839..84f6e840a47a 100644 --- a/trunk/drivers/staging/winbond/phy_calibration.h +++ b/trunk/drivers/staging/winbond/phy_calibration.h @@ -1,7 +1,7 @@ #ifndef __WINBOND_PHY_CALIBRATION_H #define __WINBOND_PHY_CALIBRATION_H -#include "wbhal_f.h" +#include "wbhal.h" #define REG_AGC_CTRL1 0x1000 #define REG_AGC_CTRL2 0x1004 diff --git a/trunk/drivers/staging/winbond/reg.c b/trunk/drivers/staging/winbond/reg.c index 990f9d4bdbbd..439d213fe951 100644 --- a/trunk/drivers/staging/winbond/reg.c +++ b/trunk/drivers/staging/winbond/reg.c @@ -1,5 +1,7 @@ #include "sysdef.h" -#include "wbhal_f.h" +#include "wbhal.h" +#include "wb35reg_f.h" +#include "core.h" /* * ==================================================== diff --git a/trunk/drivers/staging/winbond/wb35reg_f.h b/trunk/drivers/staging/winbond/wb35reg_f.h index bf23c1084199..95dc98096845 100644 --- a/trunk/drivers/staging/winbond/wb35reg_f.h +++ b/trunk/drivers/staging/winbond/wb35reg_f.h @@ -1,7 +1,7 @@ #ifndef __WINBOND_WB35REG_F_H #define __WINBOND_WB35REG_F_H -#include "wbhal_s.h" +#include "wbhal.h" /* * ==================================== diff --git a/trunk/drivers/staging/winbond/wb35reg_s.h b/trunk/drivers/staging/winbond/wb35reg_s.h index 4eff009444b8..9d5993bfc1f4 100644 --- a/trunk/drivers/staging/winbond/wb35reg_s.h +++ b/trunk/drivers/staging/winbond/wb35reg_s.h @@ -5,6 +5,8 @@ #include #include +struct hw_data; + /* ========================================================================= * * HAL setting function @@ -168,4 +170,76 @@ struct wb35_reg { u32 SQ3_filter[MAX_SQ3_FILTER_SIZE]; u32 SQ3_index; }; + +/* ===================================================================== + * Function declaration + * ===================================================================== + */ +void hal_remove_mapping_key(struct hw_data *hw_data, u8 *mac_addr); +void hal_remove_default_key(struct hw_data *hw_data, u32 index); +unsigned char hal_set_mapping_key(struct hw_data *adapter, u8 *mac_addr, + u8 null_key, u8 wep_on, u8 *tx_tsc, + u8 *rx_tsc, u8 key_type, u8 key_len, + u8 *key_data); +unsigned char hal_set_default_key(struct hw_data *adapter, u8 index, + u8 null_key, u8 wep_on, u8 *tx_tsc, + u8 *rx_tsc, u8 key_type, u8 key_len, + u8 *key_data); +void hal_clear_all_default_key(struct hw_data *hw_data); +void hal_clear_all_group_key(struct hw_data *hw_data); +void hal_clear_all_mapping_key(struct hw_data *hw_data); +void hal_clear_all_key(struct hw_data *hw_data); +void hal_set_power_save_mode(struct hw_data *hw_data, unsigned char power_save, + unsigned char wakeup, unsigned char dtim); +void hal_get_power_save_mode(struct hw_data *hw_data, u8 *in_pwr_save); +void hal_set_slot_time(struct hw_data *hw_data, u8 type); + +#define hal_set_atim_window(_A, _ATM) + +void hal_start_bss(struct hw_data *hw_data, u8 mac_op_mode); + +/* 0:BSS STA 1:IBSS STA */ +void hal_join_request(struct hw_data *hw_data, u8 bss_type); + +void hal_stop_sync_bss(struct hw_data *hw_data); +void hal_resume_sync_bss(struct hw_data *hw_data); +void hal_set_aid(struct hw_data *hw_data, u16 aid); +void hal_set_bssid(struct hw_data *hw_data, u8 *bssid); +void hal_get_bssid(struct hw_data *hw_data, u8 *bssid); +void hal_set_listen_interval(struct hw_data *hw_data, u16 listen_interval); +void hal_set_cap_info(struct hw_data *hw_data, u16 capability_info); +void hal_set_ssid(struct hw_data *hw_data, u8 *ssid, u8 ssid_len); +void hal_start_tx0(struct hw_data *hw_data); + +#define hal_get_cwmin(_A) ((_A)->cwmin) + +void hal_set_cwmax(struct hw_data *hw_data, u16 cwin_max); + +#define hal_get_cwmax(_A) ((_A)->cwmax) + +void hal_set_rsn_wpa(struct hw_data *hw_data, u32 *rsn_ie_bitmap, + u32 *rsn_oui_type , unsigned char desired_auth_mode); +void hal_set_connect_info(struct hw_data *hw_data, unsigned char bo_connect); +u8 hal_get_est_sq3(struct hw_data *hw_data, u8 count); +void hal_descriptor_indicate(struct hw_data *hw_data, + struct wb35_descriptor *des); +u8 hal_get_antenna_number(struct hw_data *hw_data); +u32 hal_get_bss_pk_cnt(struct hw_data *hw_data); + +#define hal_get_region_from_EEPROM(_A) ((_A)->reg.EEPROMRegion) +#define hal_get_tx_buffer(_A, _B) Wb35Tx_get_tx_buffer(_A, _B) +#define hal_software_set(_A) (_A->SoftwareSet) +#define hal_driver_init_OK(_A) (_A->IsInitOK) +#define hal_rssi_boundary_high(_A) (_A->RSSI_high) +#define hal_rssi_boundary_low(_A) (_A->RSSI_low) +#define hal_scan_interval(_A) (_A->Scan_Interval) + +#define PHY_DEBUG(msg, args...) + +/* return 100ms count */ +#define hal_get_time_count(_P) (_P->time_count / 10) +#define hal_detect_error(_P) (_P->WbUsb.DetectCount) + +#define hal_ibss_disconnect(_A) (hal_stop_sync_bss(_A)) + #endif diff --git a/trunk/drivers/staging/winbond/wb35rx.c b/trunk/drivers/staging/winbond/wb35rx.c index 448514aada44..5af271f2de9c 100644 --- a/trunk/drivers/staging/winbond/wb35rx.c +++ b/trunk/drivers/staging/winbond/wb35rx.c @@ -174,7 +174,7 @@ static void Wb35Rx_Complete(struct urb *urb) /* The IRP is completed */ pWb35Rx->EP3vm_state = VM_COMPLETED; - if (pHwData->SurpriseRemove || pHwData->HwStop) /* Must be here, or RxBufferId is invalid */ + if (pHwData->SurpriseRemove) /* Must be here, or RxBufferId is invalid */ goto error; if (pWb35Rx->rx_halt) @@ -239,7 +239,7 @@ static void Wb35Rx(struct ieee80211_hw *hw) u32 RxBufferId; /* Issuing URB */ - if (pHwData->SurpriseRemove || pHwData->HwStop) + if (pHwData->SurpriseRemove) goto error; if (pWb35Rx->rx_halt) diff --git a/trunk/drivers/staging/winbond/wb35rx_f.h b/trunk/drivers/staging/winbond/wb35rx_f.h index 98acce517d90..1fdf65ea6041 100644 --- a/trunk/drivers/staging/winbond/wb35rx_f.h +++ b/trunk/drivers/staging/winbond/wb35rx_f.h @@ -2,7 +2,7 @@ #define __WINBOND_WB35RX_F_H #include -#include "wbhal_s.h" +#include "wbhal.h" //==================================== // Interface function declare diff --git a/trunk/drivers/staging/winbond/wb35tx.c b/trunk/drivers/staging/winbond/wb35tx.c index 2a9d05557678..fd52554e46f8 100644 --- a/trunk/drivers/staging/winbond/wb35tx.c +++ b/trunk/drivers/staging/winbond/wb35tx.c @@ -41,7 +41,7 @@ static void Wb35Tx_complete(struct urb * pUrb) pWb35Tx->TxSendIndex++; pWb35Tx->TxSendIndex %= MAX_USB_TX_BUFFER_NUMBER; - if (pHwData->SurpriseRemove || pHwData->HwStop) // Let WbWlanHalt to handle surprise remove + if (pHwData->SurpriseRemove) // Let WbWlanHalt to handle surprise remove goto error; if (pWb35Tx->tx_halt) @@ -74,7 +74,7 @@ static void Wb35Tx(struct wbsoft_priv *adapter) u32 SendIndex; - if (pHwData->SurpriseRemove || pHwData->HwStop) + if (pHwData->SurpriseRemove) goto cleanup; if (pWb35Tx->tx_halt) @@ -222,7 +222,7 @@ static void Wb35Tx_EP2VM_complete(struct urb * pUrb) pWb35Tx->EP2VM_status = pUrb->status; // For Linux 2.4. Interrupt will always trigger - if (pHwData->SurpriseRemove || pHwData->HwStop) // Let WbWlanHalt to handle surprise remove + if (pHwData->SurpriseRemove) // Let WbWlanHalt to handle surprise remove goto error; if (pWb35Tx->tx_halt) @@ -263,7 +263,7 @@ static void Wb35Tx_EP2VM(struct wbsoft_priv *adapter) u32 * pltmp = (u32 *)pWb35Tx->EP2_buf; int retv; - if (pHwData->SurpriseRemove || pHwData->HwStop) + if (pHwData->SurpriseRemove) goto error; if (pWb35Tx->tx_halt) diff --git a/trunk/drivers/staging/winbond/wb35tx_f.h b/trunk/drivers/staging/winbond/wb35tx_f.h index 1d3b515f83bc..018fd35e815d 100644 --- a/trunk/drivers/staging/winbond/wb35tx_f.h +++ b/trunk/drivers/staging/winbond/wb35tx_f.h @@ -2,7 +2,6 @@ #define __WINBOND_WB35TX_F_H #include "core.h" -#include "wbhal_f.h" /* * ==================================== diff --git a/trunk/drivers/staging/winbond/wbhal_s.h b/trunk/drivers/staging/winbond/wbhal.h similarity index 98% rename from trunk/drivers/staging/winbond/wbhal_s.h rename to trunk/drivers/staging/winbond/wbhal.h index 821a1b3f1301..dcf3b213b4f1 100644 --- a/trunk/drivers/staging/winbond/wbhal_s.h +++ b/trunk/drivers/staging/winbond/wbhal.h @@ -342,9 +342,6 @@ struct wb35_descriptor { /* Skip length = 8 DWORD */ void *buffer_address[MAX_DESCRIPTOR_BUFFER_INDEX]; }; - -#define DEFAULT_NULL_PACKET_COUNT 180000 /* 180 seconds */ - #define MAX_TXVGA_EEPROM 9 /* How many word(u16) of EEPROM will be used for TxVGA */ #define MAX_RF_PARAMETER 32 @@ -510,16 +507,8 @@ struct hw_data { u32 RxByteCountLast; u32 TxByteCountLast; - atomic_t SurpriseRemoveCount; - /* For global timer */ u32 time_count; /* TICK_TIME_100ms 1 = 100ms */ - - /* For error recover */ - u32 HwStop; - - /* For avoid AP disconnect */ - u32 NullPacketCount; }; #endif diff --git a/trunk/drivers/staging/winbond/wbhal_f.h b/trunk/drivers/staging/winbond/wbhal_f.h deleted file mode 100644 index fc78c14ae583..000000000000 --- a/trunk/drivers/staging/winbond/wbhal_f.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * ===================================================================== - * Device related include - * ===================================================================== -*/ -#include "wb35reg_f.h" -#include "wb35tx_f.h" -#include "wb35rx_f.h" - -#include "core.h" - -/* ===================================================================== - * Function declaration - * ===================================================================== - */ -void hal_remove_mapping_key(struct hw_data *hw_data, u8 *mac_addr); -void hal_remove_default_key(struct hw_data *hw_data, u32 index); -unsigned char hal_set_mapping_key(struct hw_data *adapter, u8 *mac_addr, - u8 null_key, u8 wep_on, u8 *tx_tsc, - u8 *rx_tsc, u8 key_type, u8 key_len, - u8 *key_data); -unsigned char hal_set_default_key(struct hw_data *adapter, u8 index, - u8 null_key, u8 wep_on, u8 *tx_tsc, - u8 *rx_tsc, u8 key_type, u8 key_len, - u8 *key_data); -void hal_clear_all_default_key(struct hw_data *hw_data); -void hal_clear_all_group_key(struct hw_data *hw_data); -void hal_clear_all_mapping_key(struct hw_data *hw_data); -void hal_clear_all_key(struct hw_data *hw_data); -void hal_set_power_save_mode(struct hw_data *hw_data, unsigned char power_save, - unsigned char wakeup, unsigned char dtim); -void hal_get_power_save_mode(struct hw_data *hw_data, u8 *in_pwr_save); -void hal_set_slot_time(struct hw_data *hw_data, u8 type); - -#define hal_set_atim_window(_A, _ATM) - -void hal_start_bss(struct hw_data *hw_data, u8 mac_op_mode); - -/* 0:BSS STA 1:IBSS STA */ -void hal_join_request(struct hw_data *hw_data, u8 bss_type); - -void hal_stop_sync_bss(struct hw_data *hw_data); -void hal_resume_sync_bss(struct hw_data *hw_data); -void hal_set_aid(struct hw_data *hw_data, u16 aid); -void hal_set_bssid(struct hw_data *hw_data, u8 *bssid); -void hal_get_bssid(struct hw_data *hw_data, u8 *bssid); -void hal_set_listen_interval(struct hw_data *hw_data, u16 listen_interval); -void hal_set_cap_info(struct hw_data *hw_data, u16 capability_info); -void hal_set_ssid(struct hw_data *hw_data, u8 *ssid, u8 ssid_len); -void hal_start_tx0(struct hw_data *hw_data); - -#define hal_get_cwmin(_A) ((_A)->cwmin) - -void hal_set_cwmax(struct hw_data *hw_data, u16 cwin_max); - -#define hal_get_cwmax(_A) ((_A)->cwmax) - -void hal_set_rsn_wpa(struct hw_data *hw_data, u32 *rsn_ie_bitmap, - u32 *rsn_oui_type , unsigned char desired_auth_mode); -void hal_set_connect_info(struct hw_data *hw_data, unsigned char bo_connect); -u8 hal_get_est_sq3(struct hw_data *hw_data, u8 count); -void hal_descriptor_indicate(struct hw_data *hw_data, - struct wb35_descriptor *des); -u8 hal_get_antenna_number(struct hw_data *hw_data); -u32 hal_get_bss_pk_cnt(struct hw_data *hw_data); - -#define hal_get_region_from_EEPROM(_A) ((_A)->reg.EEPROMRegion) -#define hal_get_tx_buffer(_A, _B) Wb35Tx_get_tx_buffer(_A, _B) -#define hal_software_set(_A) (_A->SoftwareSet) -#define hal_driver_init_OK(_A) (_A->IsInitOK) -#define hal_rssi_boundary_high(_A) (_A->RSSI_high) -#define hal_rssi_boundary_low(_A) (_A->RSSI_low) -#define hal_scan_interval(_A) (_A->Scan_Interval) - -#define PHY_DEBUG(msg, args...) - -/* return 100ms count */ -#define hal_get_time_count(_P) (_P->time_count / 10) -#define hal_detect_error(_P) (_P->WbUsb.DetectCount) - -#define hal_ibss_disconnect(_A) (hal_stop_sync_bss(_A)) diff --git a/trunk/drivers/staging/winbond/wbusb.c b/trunk/drivers/staging/winbond/wbusb.c index 3f60cf7e6ec1..dcb6d5b63d76 100644 --- a/trunk/drivers/staging/winbond/wbusb.c +++ b/trunk/drivers/staging/winbond/wbusb.c @@ -16,7 +16,10 @@ #include "mds_f.h" #include "mlmetxrx_f.h" #include "mto.h" -#include "wbhal_f.h" +#include "wbhal.h" +#include "wb35reg_f.h" +#include "wb35tx_f.h" +#include "wb35rx_f.h" #include "wblinux_f.h" MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver"); @@ -608,15 +611,6 @@ static void hal_led_control(unsigned long data) } break; } - - /* Active send null packet to avoid AP disconnect */ - if (pHwData->LED_LinkOn) { - pHwData->NullPacketCount += TimeInterval; - if (pHwData->NullPacketCount >= - DEFAULT_NULL_PACKET_COUNT) { - pHwData->NullPacketCount = 0; - } - } } pHwData->time_count += TimeInterval; @@ -860,8 +854,6 @@ static void hal_halt(struct hw_data *pHwData) static void wb35_hw_halt(struct wbsoft_priv *adapter) { - Mds_Destroy(adapter); - /* Turn off Rx and Tx hardware ability */ hal_stop(&adapter->sHwData); #ifdef _PE_USB_INI_DUMP_ diff --git a/trunk/drivers/staging/wlags49_h2/wl_sysfs.c b/trunk/drivers/staging/wlags49_h2/wl_sysfs.c index e4c8804ac37d..9b833b30ae62 100644 --- a/trunk/drivers/staging/wlags49_h2/wl_sysfs.c +++ b/trunk/drivers/staging/wlags49_h2/wl_sysfs.c @@ -42,7 +42,7 @@ static ssize_t show_tallies(struct device *d, struct device_attribute *attr, CFG_HERMES_TALLIES_STRCT tallies; ssize_t ret = -EINVAL; - read_lock(&dev_base_lock); + rcu_read_lock(); if (dev_isalive(dev)) { wl_lock(lp, &flags); @@ -102,7 +102,7 @@ static ssize_t show_tallies(struct device *d, struct device_attribute *attr, } } - read_unlock(&dev_base_lock); + rcu_read_unlock(); return ret; } diff --git a/trunk/drivers/staging/xgifb/XGI_main_26.c b/trunk/drivers/staging/xgifb/XGI_main_26.c index 4f73d095c3ac..36ec45b84fca 100644 --- a/trunk/drivers/staging/xgifb/XGI_main_26.c +++ b/trunk/drivers/staging/xgifb/XGI_main_26.c @@ -472,9 +472,11 @@ unsigned char XGIfb_query_north_bridge_space(struct xgi_hw_device_info *pXGIhw_e break; } - pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridge_id, pdev); - if (pdev) + pdev = pci_get_device(PCI_VENDOR_ID_SI, nbridge_id, pdev); + if (pdev) { valid_pdev = 1; + pci_dev_put(pdev); + } } if (!valid_pdev) { diff --git a/trunk/drivers/tty/Makefile b/trunk/drivers/tty/Makefile new file mode 100644 index 000000000000..c43ef48b1a0f --- /dev/null +++ b/trunk/drivers/tty/Makefile @@ -0,0 +1,11 @@ +obj-y += tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o \ + tty_buffer.o tty_port.o tty_mutex.o +obj-$(CONFIG_LEGACY_PTYS) += pty.o +obj-$(CONFIG_UNIX98_PTYS) += pty.o +obj-$(CONFIG_AUDIT) += tty_audit.o +obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o +obj-$(CONFIG_N_HDLC) += n_hdlc.o +obj-$(CONFIG_N_GSM) += n_gsm.o +obj-$(CONFIG_R3964) += n_r3964.o + +obj-y += vt/ diff --git a/trunk/drivers/char/n_gsm.c b/trunk/drivers/tty/n_gsm.c similarity index 100% rename from trunk/drivers/char/n_gsm.c rename to trunk/drivers/tty/n_gsm.c diff --git a/trunk/drivers/char/n_hdlc.c b/trunk/drivers/tty/n_hdlc.c similarity index 100% rename from trunk/drivers/char/n_hdlc.c rename to trunk/drivers/tty/n_hdlc.c diff --git a/trunk/drivers/char/n_r3964.c b/trunk/drivers/tty/n_r3964.c similarity index 100% rename from trunk/drivers/char/n_r3964.c rename to trunk/drivers/tty/n_r3964.c diff --git a/trunk/drivers/char/n_tty.c b/trunk/drivers/tty/n_tty.c similarity index 100% rename from trunk/drivers/char/n_tty.c rename to trunk/drivers/tty/n_tty.c diff --git a/trunk/drivers/char/pty.c b/trunk/drivers/tty/pty.c similarity index 100% rename from trunk/drivers/char/pty.c rename to trunk/drivers/tty/pty.c diff --git a/trunk/drivers/char/sysrq.c b/trunk/drivers/tty/sysrq.c similarity index 100% rename from trunk/drivers/char/sysrq.c rename to trunk/drivers/tty/sysrq.c diff --git a/trunk/drivers/char/tty_audit.c b/trunk/drivers/tty/tty_audit.c similarity index 100% rename from trunk/drivers/char/tty_audit.c rename to trunk/drivers/tty/tty_audit.c diff --git a/trunk/drivers/char/tty_buffer.c b/trunk/drivers/tty/tty_buffer.c similarity index 100% rename from trunk/drivers/char/tty_buffer.c rename to trunk/drivers/tty/tty_buffer.c diff --git a/trunk/drivers/char/tty_io.c b/trunk/drivers/tty/tty_io.c similarity index 100% rename from trunk/drivers/char/tty_io.c rename to trunk/drivers/tty/tty_io.c diff --git a/trunk/drivers/char/tty_ioctl.c b/trunk/drivers/tty/tty_ioctl.c similarity index 100% rename from trunk/drivers/char/tty_ioctl.c rename to trunk/drivers/tty/tty_ioctl.c diff --git a/trunk/drivers/char/tty_ldisc.c b/trunk/drivers/tty/tty_ldisc.c similarity index 100% rename from trunk/drivers/char/tty_ldisc.c rename to trunk/drivers/tty/tty_ldisc.c diff --git a/trunk/drivers/char/tty_mutex.c b/trunk/drivers/tty/tty_mutex.c similarity index 100% rename from trunk/drivers/char/tty_mutex.c rename to trunk/drivers/tty/tty_mutex.c diff --git a/trunk/drivers/char/tty_port.c b/trunk/drivers/tty/tty_port.c similarity index 100% rename from trunk/drivers/char/tty_port.c rename to trunk/drivers/tty/tty_port.c diff --git a/trunk/drivers/char/.gitignore b/trunk/drivers/tty/vt/.gitignore similarity index 100% rename from trunk/drivers/char/.gitignore rename to trunk/drivers/tty/vt/.gitignore diff --git a/trunk/drivers/tty/vt/Makefile b/trunk/drivers/tty/vt/Makefile new file mode 100644 index 000000000000..14a51c9960df --- /dev/null +++ b/trunk/drivers/tty/vt/Makefile @@ -0,0 +1,34 @@ +# +# This file contains the font map for the default (hardware) font +# +FONTMAPFILE = cp437.uni + +obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o \ + selection.o keyboard.o +obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o +obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o + +# Files generated that shall be removed upon make clean +clean-files := consolemap_deftbl.c defkeymap.c + +quiet_cmd_conmk = CONMK $@ + cmd_conmk = scripts/conmakehash $< > $@ + +$(obj)/consolemap_deftbl.c: $(src)/$(FONTMAPFILE) + $(call cmd,conmk) + +$(obj)/defkeymap.o: $(obj)/defkeymap.c + +# Uncomment if you're changing the keymap and have an appropriate +# loadkeys version for the map. By default, we'll use the shipped +# versions. +# GENERATE_KEYMAP := 1 + +ifdef GENERATE_KEYMAP + +$(obj)/defkeymap.c: $(obj)/%.c: $(src)/%.map + loadkeys --mktable $< > $@.tmp + sed -e 's/^static *//' $@.tmp > $@ + rm $@.tmp + +endif diff --git a/trunk/drivers/char/consolemap.c b/trunk/drivers/tty/vt/consolemap.c similarity index 100% rename from trunk/drivers/char/consolemap.c rename to trunk/drivers/tty/vt/consolemap.c diff --git a/trunk/drivers/char/cp437.uni b/trunk/drivers/tty/vt/cp437.uni similarity index 100% rename from trunk/drivers/char/cp437.uni rename to trunk/drivers/tty/vt/cp437.uni diff --git a/trunk/drivers/char/defkeymap.c_shipped b/trunk/drivers/tty/vt/defkeymap.c_shipped similarity index 100% rename from trunk/drivers/char/defkeymap.c_shipped rename to trunk/drivers/tty/vt/defkeymap.c_shipped diff --git a/trunk/drivers/char/defkeymap.map b/trunk/drivers/tty/vt/defkeymap.map similarity index 100% rename from trunk/drivers/char/defkeymap.map rename to trunk/drivers/tty/vt/defkeymap.map diff --git a/trunk/drivers/char/keyboard.c b/trunk/drivers/tty/vt/keyboard.c similarity index 100% rename from trunk/drivers/char/keyboard.c rename to trunk/drivers/tty/vt/keyboard.c diff --git a/trunk/drivers/char/selection.c b/trunk/drivers/tty/vt/selection.c similarity index 100% rename from trunk/drivers/char/selection.c rename to trunk/drivers/tty/vt/selection.c diff --git a/trunk/drivers/char/vc_screen.c b/trunk/drivers/tty/vt/vc_screen.c similarity index 100% rename from trunk/drivers/char/vc_screen.c rename to trunk/drivers/tty/vt/vc_screen.c diff --git a/trunk/drivers/char/vt.c b/trunk/drivers/tty/vt/vt.c similarity index 100% rename from trunk/drivers/char/vt.c rename to trunk/drivers/tty/vt/vt.c diff --git a/trunk/drivers/char/vt_ioctl.c b/trunk/drivers/tty/vt/vt_ioctl.c similarity index 100% rename from trunk/drivers/char/vt_ioctl.c rename to trunk/drivers/tty/vt/vt_ioctl.c diff --git a/trunk/drivers/usb/gadget/u_ether.c b/trunk/drivers/usb/gadget/u_ether.c index cb23355f52d3..fbe86ca95802 100644 --- a/trunk/drivers/usb/gadget/u_ether.c +++ b/trunk/drivers/usb/gadget/u_ether.c @@ -811,7 +811,6 @@ int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN]) INFO(dev, "MAC %pM\n", net->dev_addr); INFO(dev, "HOST MAC %pM\n", dev->host_mac); - netif_stop_queue(net); the_dev = dev; } diff --git a/trunk/fs/cifs/TODO b/trunk/fs/cifs/TODO index 5aff46c61e52..355abcdcda98 100644 --- a/trunk/fs/cifs/TODO +++ b/trunk/fs/cifs/TODO @@ -81,7 +81,7 @@ u) DOS attrs - returned as pseudo-xattr in Samba format (check VFAT and NTFS for v) mount check for unmatched uids -w) Add support for new vfs entry points for setlease and fallocate +w) Add support for new vfs entry point for fallocate x) Fix Samba 3 server to handle Linux kernel aio so dbench with lots of processes can proceed better in parallel (on the server) diff --git a/trunk/fs/cifs/cifs_fs_sb.h b/trunk/fs/cifs/cifs_fs_sb.h index 525ba59a4105..e9a393c9c2ca 100644 --- a/trunk/fs/cifs/cifs_fs_sb.h +++ b/trunk/fs/cifs/cifs_fs_sb.h @@ -15,7 +15,7 @@ * the GNU Lesser General Public License for more details. * */ -#include +#include #ifndef _CIFS_FS_SB_H #define _CIFS_FS_SB_H @@ -42,9 +42,9 @@ #define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ struct cifs_sb_info { - struct radix_tree_root tlink_tree; -#define CIFS_TLINK_MASTER_TAG 0 /* is "master" (mount) tcon */ + struct rb_root tlink_tree; spinlock_t tlink_tree_lock; + struct tcon_link *master_tlink; struct nls_table *local_nls; unsigned int rsize; unsigned int wsize; diff --git a/trunk/fs/cifs/cifsfs.c b/trunk/fs/cifs/cifsfs.c index 75c4eaa79588..9c3789762ab7 100644 --- a/trunk/fs/cifs/cifsfs.c +++ b/trunk/fs/cifs/cifsfs.c @@ -116,7 +116,7 @@ cifs_read_super(struct super_block *sb, void *data, return -ENOMEM; spin_lock_init(&cifs_sb->tlink_tree_lock); - INIT_RADIX_TREE(&cifs_sb->tlink_tree, GFP_KERNEL); + cifs_sb->tlink_tree = RB_ROOT; rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY); if (rc) { @@ -321,8 +321,7 @@ cifs_alloc_inode(struct super_block *sb) /* Until the file is open and we have gotten oplock info back from the server, can not assume caching of file data or metadata */ - cifs_inode->clientCanCacheRead = false; - cifs_inode->clientCanCacheAll = false; + cifs_set_oplock_level(cifs_inode, 0); cifs_inode->delete_pending = false; cifs_inode->invalid_mapping = false; cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ diff --git a/trunk/fs/cifs/cifsglob.h b/trunk/fs/cifs/cifsglob.h index f259e4d7612d..b577bf0a1bb3 100644 --- a/trunk/fs/cifs/cifsglob.h +++ b/trunk/fs/cifs/cifsglob.h @@ -336,7 +336,8 @@ struct cifsTconInfo { * "get" on the container. */ struct tcon_link { - unsigned long tl_index; + struct rb_node tl_rbnode; + uid_t tl_uid; unsigned long tl_flags; #define TCON_LINK_MASTER 0 #define TCON_LINK_PENDING 1 diff --git a/trunk/fs/cifs/cifsproto.h b/trunk/fs/cifs/cifsproto.h index edb6d90efdf2..7ed69b6b5fe6 100644 --- a/trunk/fs/cifs/cifsproto.h +++ b/trunk/fs/cifs/cifsproto.h @@ -104,6 +104,7 @@ extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601); extern u64 cifs_UnixTimeToNT(struct timespec); extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset); +extern void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock); extern struct cifsFileInfo *cifs_new_fileinfo(__u16 fileHandle, struct file *file, struct tcon_link *tlink, diff --git a/trunk/fs/cifs/connect.c b/trunk/fs/cifs/connect.c index 9eb327defa1d..251a17c03545 100644 --- a/trunk/fs/cifs/connect.c +++ b/trunk/fs/cifs/connect.c @@ -116,6 +116,7 @@ struct smb_vol { static int ipv4_connect(struct TCP_Server_Info *server); static int ipv6_connect(struct TCP_Server_Info *server); +static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); static void cifs_prune_tlinks(struct work_struct *work); /* @@ -2900,24 +2901,16 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, goto mount_fail_check; } - tlink->tl_index = pSesInfo->linux_uid; + tlink->tl_uid = pSesInfo->linux_uid; tlink->tl_tcon = tcon; tlink->tl_time = jiffies; set_bit(TCON_LINK_MASTER, &tlink->tl_flags); set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags); - rc = radix_tree_preload(GFP_KERNEL); - if (rc == -ENOMEM) { - kfree(tlink); - goto mount_fail_check; - } - + cifs_sb->master_tlink = tlink; spin_lock(&cifs_sb->tlink_tree_lock); - radix_tree_insert(&cifs_sb->tlink_tree, pSesInfo->linux_uid, tlink); - radix_tree_tag_set(&cifs_sb->tlink_tree, pSesInfo->linux_uid, - CIFS_TLINK_MASTER_TAG); + tlink_rb_insert(&cifs_sb->tlink_tree, tlink); spin_unlock(&cifs_sb->tlink_tree_lock); - radix_tree_preload_end(); queue_delayed_work(system_nrt_wq, &cifs_sb->prune_tlinks, TLINK_IDLE_EXPIRE); @@ -3107,32 +3100,25 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, int cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) { - int i, ret; + struct rb_root *root = &cifs_sb->tlink_tree; + struct rb_node *node; + struct tcon_link *tlink; char *tmp; - struct tcon_link *tlink[8]; - unsigned long index = 0; cancel_delayed_work_sync(&cifs_sb->prune_tlinks); - do { - spin_lock(&cifs_sb->tlink_tree_lock); - ret = radix_tree_gang_lookup(&cifs_sb->tlink_tree, - (void **)tlink, index, - ARRAY_SIZE(tlink)); - /* increment index for next pass */ - if (ret > 0) - index = tlink[ret - 1]->tl_index + 1; - for (i = 0; i < ret; i++) { - cifs_get_tlink(tlink[i]); - clear_bit(TCON_LINK_IN_TREE, &tlink[i]->tl_flags); - radix_tree_delete(&cifs_sb->tlink_tree, - tlink[i]->tl_index); - } - spin_unlock(&cifs_sb->tlink_tree_lock); + spin_lock(&cifs_sb->tlink_tree_lock); + while ((node = rb_first(root))) { + tlink = rb_entry(node, struct tcon_link, tl_rbnode); + cifs_get_tlink(tlink); + clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags); + rb_erase(node, root); - for (i = 0; i < ret; i++) - cifs_put_tlink(tlink[i]); - } while (ret != 0); + spin_unlock(&cifs_sb->tlink_tree_lock); + cifs_put_tlink(tlink); + spin_lock(&cifs_sb->tlink_tree_lock); + } + spin_unlock(&cifs_sb->tlink_tree_lock); tmp = cifs_sb->prepath; cifs_sb->prepathlen = 0; @@ -3271,22 +3257,10 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) return tcon; } -static struct tcon_link * +static inline struct tcon_link * cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb) { - struct tcon_link *tlink; - unsigned int ret; - - spin_lock(&cifs_sb->tlink_tree_lock); - ret = radix_tree_gang_lookup_tag(&cifs_sb->tlink_tree, (void **)&tlink, - 0, 1, CIFS_TLINK_MASTER_TAG); - spin_unlock(&cifs_sb->tlink_tree_lock); - - /* the master tcon should always be present */ - if (ret == 0) - BUG(); - - return tlink; + return cifs_sb->master_tlink; } struct cifsTconInfo * @@ -3302,6 +3276,47 @@ cifs_sb_tcon_pending_wait(void *unused) return signal_pending(current) ? -ERESTARTSYS : 0; } +/* find and return a tlink with given uid */ +static struct tcon_link * +tlink_rb_search(struct rb_root *root, uid_t uid) +{ + struct rb_node *node = root->rb_node; + struct tcon_link *tlink; + + while (node) { + tlink = rb_entry(node, struct tcon_link, tl_rbnode); + + if (tlink->tl_uid > uid) + node = node->rb_left; + else if (tlink->tl_uid < uid) + node = node->rb_right; + else + return tlink; + } + return NULL; +} + +/* insert a tcon_link into the tree */ +static void +tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink) +{ + struct rb_node **new = &(root->rb_node), *parent = NULL; + struct tcon_link *tlink; + + while (*new) { + tlink = rb_entry(*new, struct tcon_link, tl_rbnode); + parent = *new; + + if (tlink->tl_uid > new_tlink->tl_uid) + new = &((*new)->rb_left); + else + new = &((*new)->rb_right); + } + + rb_link_node(&new_tlink->tl_rbnode, parent, new); + rb_insert_color(&new_tlink->tl_rbnode, root); +} + /* * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the * current task. @@ -3309,7 +3324,7 @@ cifs_sb_tcon_pending_wait(void *unused) * If the superblock doesn't refer to a multiuser mount, then just return * the master tcon for the mount. * - * First, search the radix tree for an existing tcon for this fsuid. If one + * First, search the rbtree for an existing tcon for this fsuid. If one * exists, then check to see if it's pending construction. If it is then wait * for construction to complete. Once it's no longer pending, check to see if * it failed and either return an error or retry construction, depending on @@ -3322,14 +3337,14 @@ struct tcon_link * cifs_sb_tlink(struct cifs_sb_info *cifs_sb) { int ret; - unsigned long fsuid = (unsigned long) current_fsuid(); + uid_t fsuid = current_fsuid(); struct tcon_link *tlink, *newtlink; if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb)); spin_lock(&cifs_sb->tlink_tree_lock); - tlink = radix_tree_lookup(&cifs_sb->tlink_tree, fsuid); + tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid); if (tlink) cifs_get_tlink(tlink); spin_unlock(&cifs_sb->tlink_tree_lock); @@ -3338,36 +3353,24 @@ cifs_sb_tlink(struct cifs_sb_info *cifs_sb) newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL); if (newtlink == NULL) return ERR_PTR(-ENOMEM); - newtlink->tl_index = fsuid; + newtlink->tl_uid = fsuid; newtlink->tl_tcon = ERR_PTR(-EACCES); set_bit(TCON_LINK_PENDING, &newtlink->tl_flags); set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags); cifs_get_tlink(newtlink); - ret = radix_tree_preload(GFP_KERNEL); - if (ret != 0) { - kfree(newtlink); - return ERR_PTR(ret); - } - spin_lock(&cifs_sb->tlink_tree_lock); /* was one inserted after previous search? */ - tlink = radix_tree_lookup(&cifs_sb->tlink_tree, fsuid); + tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid); if (tlink) { cifs_get_tlink(tlink); spin_unlock(&cifs_sb->tlink_tree_lock); - radix_tree_preload_end(); kfree(newtlink); goto wait_for_construction; } - ret = radix_tree_insert(&cifs_sb->tlink_tree, fsuid, newtlink); - spin_unlock(&cifs_sb->tlink_tree_lock); - radix_tree_preload_end(); - if (ret) { - kfree(newtlink); - return ERR_PTR(ret); - } tlink = newtlink; + tlink_rb_insert(&cifs_sb->tlink_tree, tlink); + spin_unlock(&cifs_sb->tlink_tree_lock); } else { wait_for_construction: ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING, @@ -3413,39 +3416,39 @@ cifs_prune_tlinks(struct work_struct *work) { struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info, prune_tlinks.work); - struct tcon_link *tlink[8]; - unsigned long now = jiffies; - unsigned long index = 0; - int i, ret; + struct rb_root *root = &cifs_sb->tlink_tree; + struct rb_node *node = rb_first(root); + struct rb_node *tmp; + struct tcon_link *tlink; - do { - spin_lock(&cifs_sb->tlink_tree_lock); - ret = radix_tree_gang_lookup(&cifs_sb->tlink_tree, - (void **)tlink, index, - ARRAY_SIZE(tlink)); - /* increment index for next pass */ - if (ret > 0) - index = tlink[ret - 1]->tl_index + 1; - for (i = 0; i < ret; i++) { - if (test_bit(TCON_LINK_MASTER, &tlink[i]->tl_flags) || - atomic_read(&tlink[i]->tl_count) != 0 || - time_after(tlink[i]->tl_time + TLINK_IDLE_EXPIRE, - now)) { - tlink[i] = NULL; - continue; - } - cifs_get_tlink(tlink[i]); - clear_bit(TCON_LINK_IN_TREE, &tlink[i]->tl_flags); - radix_tree_delete(&cifs_sb->tlink_tree, - tlink[i]->tl_index); - } - spin_unlock(&cifs_sb->tlink_tree_lock); + /* + * Because we drop the spinlock in the loop in order to put the tlink + * it's not guarded against removal of links from the tree. The only + * places that remove entries from the tree are this function and + * umounts. Because this function is non-reentrant and is canceled + * before umount can proceed, this is safe. + */ + spin_lock(&cifs_sb->tlink_tree_lock); + node = rb_first(root); + while (node != NULL) { + tmp = node; + node = rb_next(tmp); + tlink = rb_entry(tmp, struct tcon_link, tl_rbnode); + + if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) || + atomic_read(&tlink->tl_count) != 0 || + time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies)) + continue; - for (i = 0; i < ret; i++) { - if (tlink[i] != NULL) - cifs_put_tlink(tlink[i]); - } - } while (ret != 0); + cifs_get_tlink(tlink); + clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags); + rb_erase(tmp, root); + + spin_unlock(&cifs_sb->tlink_tree_lock); + cifs_put_tlink(tlink); + spin_lock(&cifs_sb->tlink_tree_lock); + } + spin_unlock(&cifs_sb->tlink_tree_lock); queue_delayed_work(system_nrt_wq, &cifs_sb->prune_tlinks, TLINK_IDLE_EXPIRE); diff --git a/trunk/fs/cifs/file.c b/trunk/fs/cifs/file.c index ae82159cf7fa..06c3e83fa387 100644 --- a/trunk/fs/cifs/file.c +++ b/trunk/fs/cifs/file.c @@ -146,12 +146,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb, xid, NULL); - if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { - pCifsInode->clientCanCacheAll = true; - pCifsInode->clientCanCacheRead = true; - cFYI(1, "Exclusive Oplock granted on inode %p", inode); - } else if ((oplock & 0xF) == OPLOCK_READ) - pCifsInode->clientCanCacheRead = true; + cifs_set_oplock_level(pCifsInode, oplock); return rc; } @@ -253,12 +248,7 @@ cifs_new_fileinfo(__u16 fileHandle, struct file *file, list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList); spin_unlock(&cifs_file_list_lock); - if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { - pCifsInode->clientCanCacheAll = true; - pCifsInode->clientCanCacheRead = true; - cFYI(1, "Exclusive Oplock inode %p", inode); - } else if ((oplock & 0xF) == OPLOCK_READ) - pCifsInode->clientCanCacheRead = true; + cifs_set_oplock_level(pCifsInode, oplock); file->private_data = pCifsFile; return pCifsFile; @@ -271,8 +261,9 @@ cifs_new_fileinfo(__u16 fileHandle, struct file *file, */ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) { + struct inode *inode = cifs_file->dentry->d_inode; struct cifsTconInfo *tcon = tlink_tcon(cifs_file->tlink); - struct cifsInodeInfo *cifsi = CIFS_I(cifs_file->dentry->d_inode); + struct cifsInodeInfo *cifsi = CIFS_I(inode); struct cifsLockInfo *li, *tmp; spin_lock(&cifs_file_list_lock); @@ -288,8 +279,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) if (list_empty(&cifsi->openFileList)) { cFYI(1, "closing last open instance for inode %p", cifs_file->dentry->d_inode); - cifsi->clientCanCacheRead = false; - cifsi->clientCanCacheAll = false; + cifs_set_oplock_level(cifsi, 0); } spin_unlock(&cifs_file_list_lock); @@ -607,8 +597,6 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush) rc = filemap_write_and_wait(inode->i_mapping); mapping_set_error(inode->i_mapping, rc); - pCifsInode->clientCanCacheAll = false; - pCifsInode->clientCanCacheRead = false; if (tcon->unix_ext) rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, xid); @@ -622,18 +610,9 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush) invalidate the current end of file on the server we can not go to the server to get the new inod info */ - if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { - pCifsInode->clientCanCacheAll = true; - pCifsInode->clientCanCacheRead = true; - cFYI(1, "Exclusive Oplock granted on inode %p", - pCifsFile->dentry->d_inode); - } else if ((oplock & 0xF) == OPLOCK_READ) { - pCifsInode->clientCanCacheRead = true; - pCifsInode->clientCanCacheAll = false; - } else { - pCifsInode->clientCanCacheRead = false; - pCifsInode->clientCanCacheAll = false; - } + + cifs_set_oplock_level(pCifsInode, oplock); + cifs_relock_file(pCifsFile); reopen_error_exit: @@ -775,12 +754,6 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); tcon = tlink_tcon(((struct cifsFileInfo *)file->private_data)->tlink); - - if (file->private_data == NULL) { - rc = -EBADF; - FreeXid(xid); - return rc; - } netfid = ((struct cifsFileInfo *)file->private_data)->netfid; if ((tcon->ses->capabilities & CAP_UNIX) && @@ -956,6 +929,7 @@ cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, ssize_t cifs_user_write(struct file *file, const char __user *write_data, size_t write_size, loff_t *poffset) { + struct inode *inode = file->f_path.dentry->d_inode; int rc = 0; unsigned int bytes_written = 0; unsigned int total_written; @@ -963,7 +937,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, struct cifsTconInfo *pTcon; int xid, long_op; struct cifsFileInfo *open_file; - struct cifsInodeInfo *cifsi = CIFS_I(file->f_path.dentry->d_inode); + struct cifsInodeInfo *cifsi = CIFS_I(inode); cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); @@ -1029,21 +1003,17 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, cifs_stats_bytes_written(pTcon, total_written); - /* since the write may have blocked check these pointers again */ - if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) { - struct inode *inode = file->f_path.dentry->d_inode; /* Do not update local mtime - server will set its actual value on write - * inode->i_ctime = inode->i_mtime = - * current_fs_time(inode->i_sb);*/ - if (total_written > 0) { - spin_lock(&inode->i_lock); - if (*poffset > file->f_path.dentry->d_inode->i_size) - i_size_write(file->f_path.dentry->d_inode, - *poffset); - spin_unlock(&inode->i_lock); - } - mark_inode_dirty_sync(file->f_path.dentry->d_inode); + * inode->i_ctime = inode->i_mtime = + * current_fs_time(inode->i_sb);*/ + if (total_written > 0) { + spin_lock(&inode->i_lock); + if (*poffset > inode->i_size) + i_size_write(inode, *poffset); + spin_unlock(&inode->i_lock); } + mark_inode_dirty_sync(inode); + FreeXid(xid); return total_written; } @@ -1178,7 +1148,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only) { struct cifsFileInfo *open_file; - struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb); + struct cifs_sb_info *cifs_sb; bool any_available = false; int rc; @@ -1192,6 +1162,8 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, return NULL; } + cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb); + /* only filter by fsuid on multiuser mounts */ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) fsuid_only = false; diff --git a/trunk/fs/cifs/ioctl.c b/trunk/fs/cifs/ioctl.c index 077bf756f342..2fa22f20cfc5 100644 --- a/trunk/fs/cifs/ioctl.c +++ b/trunk/fs/cifs/ioctl.c @@ -63,8 +63,6 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) #ifdef CONFIG_CIFS_POSIX case FS_IOC_GETFLAGS: if (CIFS_UNIX_EXTATTR_CAP & caps) { - if (pSMBFile == NULL) - break; rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid, &ExtAttrBits, &ExtAttrMask); if (rc == 0) @@ -80,8 +78,6 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) rc = -EFAULT; break; } - if (pSMBFile == NULL) - break; /* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid, extAttrBits, &ExtAttrMask);*/ } diff --git a/trunk/fs/cifs/misc.c b/trunk/fs/cifs/misc.c index c4e296fe3518..43f10281bc19 100644 --- a/trunk/fs/cifs/misc.c +++ b/trunk/fs/cifs/misc.c @@ -569,10 +569,9 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) cFYI(1, "file id match, oplock break"); pCifsInode = CIFS_I(netfile->dentry->d_inode); - pCifsInode->clientCanCacheAll = false; - if (pSMB->OplockLevel == 0) - pCifsInode->clientCanCacheRead = false; + cifs_set_oplock_level(pCifsInode, + pSMB->OplockLevel); /* * cifs_oplock_break_put() can't be called * from here. Get reference after queueing @@ -722,3 +721,23 @@ cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb) cifs_sb_master_tcon(cifs_sb)->treeName); } } + +void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock) +{ + oplock &= 0xF; + + if (oplock == OPLOCK_EXCLUSIVE) { + cinode->clientCanCacheAll = true; + cinode->clientCanCacheRead = true; + cFYI(1, "Exclusive Oplock granted on inode %p", + &cinode->vfs_inode); + } else if (oplock == OPLOCK_READ) { + cinode->clientCanCacheAll = false; + cinode->clientCanCacheRead = true; + cFYI(1, "Level II Oplock granted on inode %p", + &cinode->vfs_inode); + } else { + cinode->clientCanCacheAll = false; + cinode->clientCanCacheRead = false; + } +} diff --git a/trunk/fs/ext4/ext4.h b/trunk/fs/ext4/ext4.h index 8b5dd6369f82..6a5edea2d70b 100644 --- a/trunk/fs/ext4/ext4.h +++ b/trunk/fs/ext4/ext4.h @@ -177,7 +177,7 @@ struct mpage_da_data { struct ext4_io_page { struct page *p_page; - int p_count; + atomic_t p_count; }; #define MAX_IO_PAGES 128 @@ -858,6 +858,7 @@ struct ext4_inode_info { spinlock_t i_completed_io_lock; /* current io_end structure for async DIO write*/ ext4_io_end_t *cur_aio_dio; + atomic_t i_ioend_count; /* Number of outstanding io_end structs */ /* * Transactions that contain inode's metadata needed to complete @@ -2060,6 +2061,7 @@ extern int ext4_move_extents(struct file *o_filp, struct file *d_filp, /* page-io.c */ extern int __init ext4_init_pageio(void); extern void ext4_exit_pageio(void); +extern void ext4_ioend_wait(struct inode *); extern void ext4_free_io_end(ext4_io_end_t *io); extern ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags); extern int ext4_end_io_nolock(ext4_io_end_t *io); diff --git a/trunk/fs/ext4/inode.c b/trunk/fs/ext4/inode.c index 4d78342f3bf0..bdbe69902207 100644 --- a/trunk/fs/ext4/inode.c +++ b/trunk/fs/ext4/inode.c @@ -53,6 +53,7 @@ static inline int ext4_begin_ordered_truncate(struct inode *inode, loff_t new_size) { + trace_ext4_begin_ordered_truncate(inode, new_size); return jbd2_journal_begin_ordered_truncate( EXT4_SB(inode->i_sb)->s_journal, &EXT4_I(inode)->jinode, @@ -178,6 +179,7 @@ void ext4_evict_inode(struct inode *inode) handle_t *handle; int err; + trace_ext4_evict_inode(inode); if (inode->i_nlink) { truncate_inode_pages(&inode->i_data, 0); goto no_delete; @@ -5647,6 +5649,7 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode) int err, ret; might_sleep(); + trace_ext4_mark_inode_dirty(inode, _RET_IP_); err = ext4_reserve_inode_write(handle, inode, &iloc); if (ext4_handle_valid(handle) && EXT4_I(inode)->i_extra_isize < sbi->s_want_extra_isize && diff --git a/trunk/fs/ext4/mballoc.c b/trunk/fs/ext4/mballoc.c index c58eba34724a..5b4d4e3a4d58 100644 --- a/trunk/fs/ext4/mballoc.c +++ b/trunk/fs/ext4/mballoc.c @@ -4640,8 +4640,6 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, * with group lock held. generate_buddy look at * them with group lock_held */ - if (test_opt(sb, DISCARD)) - ext4_issue_discard(sb, block_group, bit, count); ext4_lock_group(sb, block_group); mb_clear_bits(bitmap_bh->b_data, bit, count); mb_free_blocks(inode, &e4b, bit, count); diff --git a/trunk/fs/ext4/page-io.c b/trunk/fs/ext4/page-io.c index 46a7d6a9d976..7f5451cd1d38 100644 --- a/trunk/fs/ext4/page-io.c +++ b/trunk/fs/ext4/page-io.c @@ -32,8 +32,14 @@ static struct kmem_cache *io_page_cachep, *io_end_cachep; +#define WQ_HASH_SZ 37 +#define to_ioend_wq(v) (&ioend_wq[((unsigned long)v) % WQ_HASH_SZ]) +static wait_queue_head_t ioend_wq[WQ_HASH_SZ]; + int __init ext4_init_pageio(void) { + int i; + io_page_cachep = KMEM_CACHE(ext4_io_page, SLAB_RECLAIM_ACCOUNT); if (io_page_cachep == NULL) return -ENOMEM; @@ -42,6 +48,8 @@ int __init ext4_init_pageio(void) kmem_cache_destroy(io_page_cachep); return -ENOMEM; } + for (i = 0; i < WQ_HASH_SZ; i++) + init_waitqueue_head(&ioend_wq[i]); return 0; } @@ -52,24 +60,37 @@ void ext4_exit_pageio(void) kmem_cache_destroy(io_page_cachep); } +void ext4_ioend_wait(struct inode *inode) +{ + wait_queue_head_t *wq = to_ioend_wq(inode); + + wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_ioend_count) == 0)); +} + +static void put_io_page(struct ext4_io_page *io_page) +{ + if (atomic_dec_and_test(&io_page->p_count)) { + end_page_writeback(io_page->p_page); + put_page(io_page->p_page); + kmem_cache_free(io_page_cachep, io_page); + } +} + void ext4_free_io_end(ext4_io_end_t *io) { int i; + wait_queue_head_t *wq; BUG_ON(!io); if (io->page) put_page(io->page); - for (i = 0; i < io->num_io_pages; i++) { - if (--io->pages[i]->p_count == 0) { - struct page *page = io->pages[i]->p_page; - - end_page_writeback(page); - put_page(page); - kmem_cache_free(io_page_cachep, io->pages[i]); - } - } + for (i = 0; i < io->num_io_pages; i++) + put_io_page(io->pages[i]); io->num_io_pages = 0; - iput(io->inode); + wq = to_ioend_wq(io->inode); + if (atomic_dec_and_test(&EXT4_I(io->inode)->i_ioend_count) && + waitqueue_active(wq)) + wake_up_all(wq); kmem_cache_free(io_end_cachep, io); } @@ -142,8 +163,8 @@ ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags) io = kmem_cache_alloc(io_end_cachep, flags); if (io) { memset(io, 0, sizeof(*io)); - io->inode = igrab(inode); - BUG_ON(!io->inode); + atomic_inc(&EXT4_I(inode)->i_ioend_count); + io->inode = inode; INIT_WORK(&io->work, ext4_end_io_work); INIT_LIST_HEAD(&io->list); } @@ -171,35 +192,15 @@ static void ext4_end_bio(struct bio *bio, int error) struct workqueue_struct *wq; struct inode *inode; unsigned long flags; - ext4_fsblk_t err_block; int i; BUG_ON(!io_end); - inode = io_end->inode; bio->bi_private = NULL; bio->bi_end_io = NULL; if (test_bit(BIO_UPTODATE, &bio->bi_flags)) error = 0; - err_block = bio->bi_sector >> (inode->i_blkbits - 9); bio_put(bio); - if (!(inode->i_sb->s_flags & MS_ACTIVE)) { - pr_err("sb umounted, discard end_io request for inode %lu\n", - io_end->inode->i_ino); - ext4_free_io_end(io_end); - return; - } - - if (error) { - io_end->flag |= EXT4_IO_END_ERROR; - ext4_warning(inode->i_sb, "I/O error writing to inode %lu " - "(offset %llu size %ld starting block %llu)", - inode->i_ino, - (unsigned long long) io_end->offset, - (long) io_end->size, - (unsigned long long) err_block); - } - for (i = 0; i < io_end->num_io_pages; i++) { struct page *page = io_end->pages[i]->p_page; struct buffer_head *bh, *head; @@ -236,13 +237,7 @@ static void ext4_end_bio(struct bio *bio, int error) } while (bh != head); } - if (--io_end->pages[i]->p_count == 0) { - struct page *page = io_end->pages[i]->p_page; - - end_page_writeback(page); - put_page(page); - kmem_cache_free(io_page_cachep, io_end->pages[i]); - } + put_io_page(io_end->pages[i]); /* * If this is a partial write which happened to make @@ -254,8 +249,19 @@ static void ext4_end_bio(struct bio *bio, int error) if (!partial_write) SetPageUptodate(page); } - io_end->num_io_pages = 0; + inode = io_end->inode; + + if (error) { + io_end->flag |= EXT4_IO_END_ERROR; + ext4_warning(inode->i_sb, "I/O error writing to inode %lu " + "(offset %llu size %ld starting block %llu)", + inode->i_ino, + (unsigned long long) io_end->offset, + (long) io_end->size, + (unsigned long long) + bio->bi_sector >> (inode->i_blkbits - 9)); + } /* Add the io_end to per-inode completed io list*/ spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); @@ -305,7 +311,6 @@ static int io_submit_init(struct ext4_io_submit *io, bio->bi_private = io->io_end = io_end; bio->bi_end_io = ext4_end_bio; - io_end->inode = inode; io_end->offset = (page->index << PAGE_CACHE_SHIFT) + bh_offset(bh); io->io_bio = bio; @@ -360,7 +365,7 @@ static int io_submit_add_bh(struct ext4_io_submit *io, if ((io_end->num_io_pages == 0) || (io_end->pages[io_end->num_io_pages-1] != io_page)) { io_end->pages[io_end->num_io_pages++] = io_page; - io_page->p_count++; + atomic_inc(&io_page->p_count); } return 0; } @@ -389,7 +394,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, return -ENOMEM; } io_page->p_page = page; - io_page->p_count = 0; + atomic_set(&io_page->p_count, 1); get_page(page); for (bh = head = page_buffers(page), block_start = 0; @@ -421,10 +426,6 @@ int ext4_bio_write_page(struct ext4_io_submit *io, * PageWriteback bit from the page to prevent the system from * wedging later on. */ - if (io_page->p_count == 0) { - put_page(page); - end_page_writeback(page); - kmem_cache_free(io_page_cachep, io_page); - } + put_io_page(io_page); return ret; } diff --git a/trunk/fs/ext4/super.c b/trunk/fs/ext4/super.c index 40131b777af6..61182fe6254e 100644 --- a/trunk/fs/ext4/super.c +++ b/trunk/fs/ext4/super.c @@ -828,12 +828,22 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) ei->cur_aio_dio = NULL; ei->i_sync_tid = 0; ei->i_datasync_tid = 0; + atomic_set(&ei->i_ioend_count, 0); return &ei->vfs_inode; } +static int ext4_drop_inode(struct inode *inode) +{ + int drop = generic_drop_inode(inode); + + trace_ext4_drop_inode(inode, drop); + return drop; +} + static void ext4_destroy_inode(struct inode *inode) { + ext4_ioend_wait(inode); if (!list_empty(&(EXT4_I(inode)->i_orphan))) { ext4_msg(inode->i_sb, KERN_ERR, "Inode %lu (%p): orphan list check failed!", @@ -1173,6 +1183,7 @@ static const struct super_operations ext4_sops = { .destroy_inode = ext4_destroy_inode, .write_inode = ext4_write_inode, .dirty_inode = ext4_dirty_inode, + .drop_inode = ext4_drop_inode, .evict_inode = ext4_evict_inode, .put_super = ext4_put_super, .sync_fs = ext4_sync_fs, @@ -1194,6 +1205,7 @@ static const struct super_operations ext4_nojournal_sops = { .destroy_inode = ext4_destroy_inode, .write_inode = ext4_write_inode, .dirty_inode = ext4_dirty_inode, + .drop_inode = ext4_drop_inode, .evict_inode = ext4_evict_inode, .write_super = ext4_write_super, .put_super = ext4_put_super, @@ -2699,7 +2711,6 @@ static int ext4_lazyinit_thread(void *arg) struct ext4_li_request *elr; unsigned long next_wakeup; DEFINE_WAIT(wait); - int ret; BUG_ON(NULL == eli); @@ -2723,13 +2734,12 @@ static int ext4_lazyinit_thread(void *arg) elr = list_entry(pos, struct ext4_li_request, lr_request); - if (time_after_eq(jiffies, elr->lr_next_sched)) - ret = ext4_run_li_request(elr); - - if (ret) { - ret = 0; - ext4_remove_li_request(elr); - continue; + if (time_after_eq(jiffies, elr->lr_next_sched)) { + if (ext4_run_li_request(elr) != 0) { + /* error, remove the lazy_init job */ + ext4_remove_li_request(elr); + continue; + } } if (time_before(elr->lr_next_sched, next_wakeup)) @@ -2740,7 +2750,8 @@ static int ext4_lazyinit_thread(void *arg) if (freezing(current)) refrigerator(); - if (time_after_eq(jiffies, next_wakeup)) { + if ((time_after_eq(jiffies, next_wakeup)) || + (MAX_JIFFY_OFFSET == next_wakeup)) { cond_resched(); continue; } @@ -3348,6 +3359,24 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) get_random_bytes(&sbi->s_next_generation, sizeof(u32)); spin_lock_init(&sbi->s_next_gen_lock); + err = percpu_counter_init(&sbi->s_freeblocks_counter, + ext4_count_free_blocks(sb)); + if (!err) { + err = percpu_counter_init(&sbi->s_freeinodes_counter, + ext4_count_free_inodes(sb)); + } + if (!err) { + err = percpu_counter_init(&sbi->s_dirs_counter, + ext4_count_dirs(sb)); + } + if (!err) { + err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0); + } + if (err) { + ext4_msg(sb, KERN_ERR, "insufficient memory"); + goto failed_mount3; + } + sbi->s_stripe = ext4_get_stripe_size(sbi); sbi->s_max_writeback_mb_bump = 128; @@ -3446,22 +3475,19 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) } set_task_ioprio(sbi->s_journal->j_task, journal_ioprio); -no_journal: - err = percpu_counter_init(&sbi->s_freeblocks_counter, - ext4_count_free_blocks(sb)); - if (!err) - err = percpu_counter_init(&sbi->s_freeinodes_counter, - ext4_count_free_inodes(sb)); - if (!err) - err = percpu_counter_init(&sbi->s_dirs_counter, - ext4_count_dirs(sb)); - if (!err) - err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0); - if (err) { - ext4_msg(sb, KERN_ERR, "insufficient memory"); - goto failed_mount_wq; - } + /* + * The journal may have updated the bg summary counts, so we + * need to update the global counters. + */ + percpu_counter_set(&sbi->s_freeblocks_counter, + ext4_count_free_blocks(sb)); + percpu_counter_set(&sbi->s_freeinodes_counter, + ext4_count_free_inodes(sb)); + percpu_counter_set(&sbi->s_dirs_counter, + ext4_count_dirs(sb)); + percpu_counter_set(&sbi->s_dirtyblocks_counter, 0); +no_journal: EXT4_SB(sb)->dio_unwritten_wq = create_workqueue("ext4-dio-unwritten"); if (!EXT4_SB(sb)->dio_unwritten_wq) { printk(KERN_ERR "EXT4-fs: failed to create DIO workqueue\n"); @@ -3611,10 +3637,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) jbd2_journal_destroy(sbi->s_journal); sbi->s_journal = NULL; } - percpu_counter_destroy(&sbi->s_freeblocks_counter); - percpu_counter_destroy(&sbi->s_freeinodes_counter); - percpu_counter_destroy(&sbi->s_dirs_counter); - percpu_counter_destroy(&sbi->s_dirtyblocks_counter); failed_mount3: if (sbi->s_flex_groups) { if (is_vmalloc_addr(sbi->s_flex_groups)) @@ -3622,6 +3644,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) else kfree(sbi->s_flex_groups); } + percpu_counter_destroy(&sbi->s_freeblocks_counter); + percpu_counter_destroy(&sbi->s_freeinodes_counter); + percpu_counter_destroy(&sbi->s_dirs_counter); + percpu_counter_destroy(&sbi->s_dirtyblocks_counter); failed_mount2: for (i = 0; i < db_count; i++) brelse(sbi->s_group_desc[i]); @@ -3949,13 +3975,11 @@ static int ext4_commit_super(struct super_block *sb, int sync) else es->s_kbytes_written = cpu_to_le64(EXT4_SB(sb)->s_kbytes_written); - if (percpu_counter_initialized(&EXT4_SB(sb)->s_freeblocks_counter)) - ext4_free_blocks_count_set(es, percpu_counter_sum_positive( - &EXT4_SB(sb)->s_freeblocks_counter)); - if (percpu_counter_initialized(&EXT4_SB(sb)->s_freeinodes_counter)) - es->s_free_inodes_count = - cpu_to_le32(percpu_counter_sum_positive( - &EXT4_SB(sb)->s_freeinodes_counter)); + ext4_free_blocks_count_set(es, percpu_counter_sum_positive( + &EXT4_SB(sb)->s_freeblocks_counter)); + es->s_free_inodes_count = + cpu_to_le32(percpu_counter_sum_positive( + &EXT4_SB(sb)->s_freeinodes_counter)); sb->s_dirt = 0; BUFFER_TRACE(sbh, "marking dirty"); mark_buffer_dirty(sbh); @@ -4556,12 +4580,10 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id, static int ext4_quota_off(struct super_block *sb, int type) { - /* Force all delayed allocation blocks to be allocated */ - if (test_opt(sb, DELALLOC)) { - down_read(&sb->s_umount); + /* Force all delayed allocation blocks to be allocated. + * Caller already holds s_umount sem */ + if (test_opt(sb, DELALLOC)) sync_filesystem(sb); - up_read(&sb->s_umount); - } return dquot_quota_off(sb, type); } diff --git a/trunk/include/asm-generic/stat.h b/trunk/include/asm-generic/stat.h index 47e64170305d..bd8cad21998e 100644 --- a/trunk/include/asm-generic/stat.h +++ b/trunk/include/asm-generic/stat.h @@ -33,18 +33,18 @@ struct stat { int st_blksize; /* Optimal block size for I/O. */ int __pad2; long st_blocks; /* Number 512-byte blocks allocated. */ - int st_atime; /* Time of last access. */ - unsigned int st_atime_nsec; - int st_mtime; /* Time of last modification. */ - unsigned int st_mtime_nsec; - int st_ctime; /* Time of last status change. */ - unsigned int st_ctime_nsec; + long st_atime; /* Time of last access. */ + unsigned long st_atime_nsec; + long st_mtime; /* Time of last modification. */ + unsigned long st_mtime_nsec; + long st_ctime; /* Time of last status change. */ + unsigned long st_ctime_nsec; unsigned int __unused4; unsigned int __unused5; }; -#if __BITS_PER_LONG != 64 /* This matches struct stat64 in glibc2.1. Only used for 32 bit. */ +#if __BITS_PER_LONG != 64 || defined(__ARCH_WANT_STAT64) struct stat64 { unsigned long long st_dev; /* Device. */ unsigned long long st_ino; /* File serial number. */ diff --git a/trunk/include/linux/mmc/sh_mmcif.h b/trunk/include/linux/mmc/sh_mmcif.h index d19e2114fd86..5c99da1078aa 100644 --- a/trunk/include/linux/mmc/sh_mmcif.h +++ b/trunk/include/linux/mmc/sh_mmcif.h @@ -59,19 +59,19 @@ struct sh_mmcif_plat_data { #define MMCIF_CE_HOST_STS2 0x0000004C #define MMCIF_CE_VERSION 0x0000007C -extern inline u32 sh_mmcif_readl(void __iomem *addr, int reg) +static inline u32 sh_mmcif_readl(void __iomem *addr, int reg) { return readl(addr + reg); } -extern inline void sh_mmcif_writel(void __iomem *addr, int reg, u32 val) +static inline void sh_mmcif_writel(void __iomem *addr, int reg, u32 val) { writel(val, addr + reg); } #define SH_MMCIF_BBS 512 /* boot block size */ -extern inline void sh_mmcif_boot_cmd_send(void __iomem *base, +static inline void sh_mmcif_boot_cmd_send(void __iomem *base, unsigned long cmd, unsigned long arg) { sh_mmcif_writel(base, MMCIF_CE_INT, 0); @@ -79,7 +79,7 @@ extern inline void sh_mmcif_boot_cmd_send(void __iomem *base, sh_mmcif_writel(base, MMCIF_CE_CMD_SET, cmd); } -extern inline int sh_mmcif_boot_cmd_poll(void __iomem *base, unsigned long mask) +static inline int sh_mmcif_boot_cmd_poll(void __iomem *base, unsigned long mask) { unsigned long tmp; int cnt; @@ -95,14 +95,14 @@ extern inline int sh_mmcif_boot_cmd_poll(void __iomem *base, unsigned long mask) return -1; } -extern inline int sh_mmcif_boot_cmd(void __iomem *base, +static inline int sh_mmcif_boot_cmd(void __iomem *base, unsigned long cmd, unsigned long arg) { sh_mmcif_boot_cmd_send(base, cmd, arg); return sh_mmcif_boot_cmd_poll(base, 0x00010000); } -extern inline int sh_mmcif_boot_do_read_single(void __iomem *base, +static inline int sh_mmcif_boot_do_read_single(void __iomem *base, unsigned int block_nr, unsigned long *buf) { @@ -125,7 +125,7 @@ extern inline int sh_mmcif_boot_do_read_single(void __iomem *base, return 0; } -extern inline int sh_mmcif_boot_do_read(void __iomem *base, +static inline int sh_mmcif_boot_do_read(void __iomem *base, unsigned long first_block, unsigned long nr_blocks, void *buf) @@ -143,7 +143,7 @@ extern inline int sh_mmcif_boot_do_read(void __iomem *base, return ret; } -extern inline void sh_mmcif_boot_init(void __iomem *base) +static inline void sh_mmcif_boot_init(void __iomem *base) { unsigned long tmp; @@ -177,7 +177,7 @@ extern inline void sh_mmcif_boot_init(void __iomem *base) sh_mmcif_boot_cmd(base, 0x03400040, 0x00010000); } -extern inline void sh_mmcif_boot_slurp(void __iomem *base, +static inline void sh_mmcif_boot_slurp(void __iomem *base, unsigned char *buf, unsigned long no_bytes) { diff --git a/trunk/include/linux/sh_clk.h b/trunk/include/linux/sh_clk.h index 4dca992f3093..cea0c38e7a63 100644 --- a/trunk/include/linux/sh_clk.h +++ b/trunk/include/linux/sh_clk.h @@ -122,6 +122,10 @@ int clk_rate_table_find(struct clk *clk, long clk_rate_div_range_round(struct clk *clk, unsigned int div_min, unsigned int div_max, unsigned long rate); +long clk_round_parent(struct clk *clk, unsigned long target, + unsigned long *best_freq, unsigned long *parent_freq, + unsigned int div_min, unsigned int div_max); + #define SH_CLK_MSTP32(_parent, _enable_reg, _enable_bit, _flags) \ { \ .parent = _parent, \ diff --git a/trunk/include/linux/sh_timer.h b/trunk/include/linux/sh_timer.h index 864bd56bd3b0..4d9dcd138315 100644 --- a/trunk/include/linux/sh_timer.h +++ b/trunk/include/linux/sh_timer.h @@ -5,7 +5,6 @@ struct sh_timer_config { char *name; long channel_offset; int timer_bit; - char *clk; unsigned long clockevent_rating; unsigned long clocksource_rating; }; diff --git a/trunk/include/net/caif/caif_dev.h b/trunk/include/net/caif/caif_dev.h index 6da573c75d54..8eff83b95366 100644 --- a/trunk/include/net/caif/caif_dev.h +++ b/trunk/include/net/caif/caif_dev.h @@ -28,7 +28,7 @@ struct caif_param { * @sockaddr: Socket address to connect. * @priority: Priority of the connection. * @link_selector: Link selector (high bandwidth or low latency) - * @link_name: Name of the CAIF Link Layer to use. + * @ifindex: kernel index of the interface. * @param: Connect Request parameters (CAIF_SO_REQ_PARAM). * * This struct is used when connecting a CAIF channel. @@ -39,7 +39,7 @@ struct caif_connect_request { struct sockaddr_caif sockaddr; enum caif_channel_priority priority; enum caif_link_selector link_selector; - char link_name[16]; + int ifindex; struct caif_param param; }; diff --git a/trunk/include/net/caif/caif_spi.h b/trunk/include/net/caif/caif_spi.h index ce4570dff020..87c3d11b8e55 100644 --- a/trunk/include/net/caif/caif_spi.h +++ b/trunk/include/net/caif/caif_spi.h @@ -121,6 +121,8 @@ struct cfspi { wait_queue_head_t wait; spinlock_t lock; bool flow_stop; + bool slave; + bool slave_talked; #ifdef CONFIG_DEBUG_FS enum cfspi_state dbg_state; u16 pcmd; diff --git a/trunk/include/net/caif/cfcnfg.h b/trunk/include/net/caif/cfcnfg.h index bd646faffa47..f688478bfb84 100644 --- a/trunk/include/net/caif/cfcnfg.h +++ b/trunk/include/net/caif/cfcnfg.h @@ -139,10 +139,10 @@ struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, enum cfcnfg_phy_preference phy_pref); /** - * cfcnfg_get_named() - Get the Physical Identifier of CAIF Link Layer + * cfcnfg_get_id_from_ifi() - Get the Physical Identifier of ifindex, + * it matches caif physical id with the kernel interface id. * @cnfg: Configuration object - * @name: Name of the Physical Layer (Caif Link Layer) + * @ifi: ifindex obtained from socket.c bindtodevice. */ -int cfcnfg_get_named(struct cfcnfg *cnfg, char *name); - +int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi); #endif /* CFCNFG_H_ */ diff --git a/trunk/include/net/netlink.h b/trunk/include/net/netlink.h index f3b201d335b3..9801c55de5d6 100644 --- a/trunk/include/net/netlink.h +++ b/trunk/include/net/netlink.h @@ -384,7 +384,7 @@ static inline int nlmsg_parse(const struct nlmsghdr *nlh, int hdrlen, * * Returns the first attribute which matches the specified type. */ -static inline struct nlattr *nlmsg_find_attr(struct nlmsghdr *nlh, +static inline struct nlattr *nlmsg_find_attr(const struct nlmsghdr *nlh, int hdrlen, int attrtype) { return nla_find(nlmsg_attrdata(nlh, hdrlen), diff --git a/trunk/include/trace/events/ext4.h b/trunk/include/trace/events/ext4.h index 289010d3270b..e5e345fb2a5c 100644 --- a/trunk/include/trace/events/ext4.h +++ b/trunk/include/trace/events/ext4.h @@ -98,6 +98,103 @@ TRACE_EVENT(ext4_allocate_inode, (unsigned long) __entry->dir, __entry->mode) ); +TRACE_EVENT(ext4_evict_inode, + TP_PROTO(struct inode *inode), + + TP_ARGS(inode), + + TP_STRUCT__entry( + __field( int, dev_major ) + __field( int, dev_minor ) + __field( ino_t, ino ) + __field( int, nlink ) + ), + + TP_fast_assign( + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); + __entry->ino = inode->i_ino; + __entry->nlink = inode->i_nlink; + ), + + TP_printk("dev %d,%d ino %lu nlink %d", + __entry->dev_major, __entry->dev_minor, + (unsigned long) __entry->ino, __entry->nlink) +); + +TRACE_EVENT(ext4_drop_inode, + TP_PROTO(struct inode *inode, int drop), + + TP_ARGS(inode, drop), + + TP_STRUCT__entry( + __field( int, dev_major ) + __field( int, dev_minor ) + __field( ino_t, ino ) + __field( int, drop ) + ), + + TP_fast_assign( + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); + __entry->ino = inode->i_ino; + __entry->drop = drop; + ), + + TP_printk("dev %d,%d ino %lu drop %d", + __entry->dev_major, __entry->dev_minor, + (unsigned long) __entry->ino, __entry->drop) +); + +TRACE_EVENT(ext4_mark_inode_dirty, + TP_PROTO(struct inode *inode, unsigned long IP), + + TP_ARGS(inode, IP), + + TP_STRUCT__entry( + __field( int, dev_major ) + __field( int, dev_minor ) + __field( ino_t, ino ) + __field(unsigned long, ip ) + ), + + TP_fast_assign( + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); + __entry->ino = inode->i_ino; + __entry->ip = IP; + ), + + TP_printk("dev %d,%d ino %lu caller %pF", + __entry->dev_major, __entry->dev_minor, + (unsigned long) __entry->ino, (void *)__entry->ip) +); + +TRACE_EVENT(ext4_begin_ordered_truncate, + TP_PROTO(struct inode *inode, loff_t new_size), + + TP_ARGS(inode, new_size), + + TP_STRUCT__entry( + __field( int, dev_major ) + __field( int, dev_minor ) + __field( ino_t, ino ) + __field( loff_t, new_size ) + ), + + TP_fast_assign( + __entry->dev_major = MAJOR(inode->i_sb->s_dev); + __entry->dev_minor = MINOR(inode->i_sb->s_dev); + __entry->ino = inode->i_ino; + __entry->new_size = new_size; + ), + + TP_printk("dev %d,%d ino %lu new_size %lld", + __entry->dev_major, __entry->dev_minor, + (unsigned long) __entry->ino, + (long long) __entry->new_size) +); + DECLARE_EVENT_CLASS(ext4__write_begin, TP_PROTO(struct inode *inode, loff_t pos, unsigned int len, diff --git a/trunk/kernel/exit.c b/trunk/kernel/exit.c index b194febf5799..21aa7b3001fb 100644 --- a/trunk/kernel/exit.c +++ b/trunk/kernel/exit.c @@ -95,6 +95,14 @@ static void __exit_signal(struct task_struct *tsk) tty = sig->tty; sig->tty = NULL; } else { + /* + * This can only happen if the caller is de_thread(). + * FIXME: this is the temporary hack, we should teach + * posix-cpu-timers to handle this case correctly. + */ + if (unlikely(has_group_leader_pid(tsk))) + posix_cpu_timers_exit_group(tsk); + /* * If there is any task waiting for the group exit * then notify it: diff --git a/trunk/kernel/relay.c b/trunk/kernel/relay.c index c7cf397fb929..859ea5a9605f 100644 --- a/trunk/kernel/relay.c +++ b/trunk/kernel/relay.c @@ -70,17 +70,10 @@ static const struct vm_operations_struct relay_file_mmap_ops = { */ static struct page **relay_alloc_page_array(unsigned int n_pages) { - struct page **array; - size_t pa_size = n_pages * sizeof(struct page *); - - if (pa_size > PAGE_SIZE) { - array = vmalloc(pa_size); - if (array) - memset(array, 0, pa_size); - } else { - array = kzalloc(pa_size, GFP_KERNEL); - } - return array; + const size_t pa_size = n_pages * sizeof(struct page *); + if (pa_size > PAGE_SIZE) + return vzalloc(pa_size); + return kzalloc(pa_size, GFP_KERNEL); } /* diff --git a/trunk/kernel/watchdog.c b/trunk/kernel/watchdog.c index bafba687a6d8..6e3c41a4024c 100644 --- a/trunk/kernel/watchdog.c +++ b/trunk/kernel/watchdog.c @@ -43,7 +43,7 @@ static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts_saved); static DEFINE_PER_CPU(struct perf_event *, watchdog_ev); #endif -static int __initdata no_watchdog; +static int no_watchdog; /* boot commands */ diff --git a/trunk/net/caif/caif_config_util.c b/trunk/net/caif/caif_config_util.c index 76ae68303d3a..d522d8c1703e 100644 --- a/trunk/net/caif/caif_config_util.c +++ b/trunk/net/caif/caif_config_util.c @@ -16,11 +16,18 @@ int connect_req_to_link_param(struct cfcnfg *cnfg, { struct dev_info *dev_info; enum cfcnfg_phy_preference pref; + int res; + memset(l, 0, sizeof(*l)); - l->priority = s->priority; + /* In caif protocol low value is high priority */ + l->priority = CAIF_PRIO_MAX - s->priority + 1; - if (s->link_name[0] != '\0') - l->phyid = cfcnfg_get_named(cnfg, s->link_name); + if (s->ifindex != 0){ + res = cfcnfg_get_id_from_ifi(cnfg, s->ifindex); + if (res < 0) + return res; + l->phyid = res; + } else { switch (s->link_selector) { case CAIF_LINK_HIGH_BANDW: diff --git a/trunk/net/caif/caif_dev.c b/trunk/net/caif/caif_dev.c index b99369a055d1..a42a408306e4 100644 --- a/trunk/net/caif/caif_dev.c +++ b/trunk/net/caif/caif_dev.c @@ -307,6 +307,8 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, case NETDEV_UNREGISTER: caifd = caif_get(dev); + if (caifd == NULL) + break; netdev_info(dev, "unregister\n"); atomic_set(&caifd->state, what); caif_device_destroy(dev); diff --git a/trunk/net/caif/caif_socket.c b/trunk/net/caif/caif_socket.c index 2eca2dd0000f..1bf0cf503796 100644 --- a/trunk/net/caif/caif_socket.c +++ b/trunk/net/caif/caif_socket.c @@ -716,8 +716,7 @@ static int setsockopt(struct socket *sock, { struct sock *sk = sock->sk; struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); - int prio, linksel; - struct ifreq ifreq; + int linksel; if (cf_sk->sk.sk_socket->state != SS_UNCONNECTED) return -ENOPROTOOPT; @@ -735,33 +734,6 @@ static int setsockopt(struct socket *sock, release_sock(&cf_sk->sk); return 0; - case SO_PRIORITY: - if (lvl != SOL_SOCKET) - goto bad_sol; - if (ol < sizeof(int)) - return -EINVAL; - if (copy_from_user(&prio, ov, sizeof(int))) - return -EINVAL; - lock_sock(&(cf_sk->sk)); - cf_sk->conn_req.priority = prio; - release_sock(&cf_sk->sk); - return 0; - - case SO_BINDTODEVICE: - if (lvl != SOL_SOCKET) - goto bad_sol; - if (ol < sizeof(struct ifreq)) - return -EINVAL; - if (copy_from_user(&ifreq, ov, sizeof(ifreq))) - return -EFAULT; - lock_sock(&(cf_sk->sk)); - strncpy(cf_sk->conn_req.link_name, ifreq.ifr_name, - sizeof(cf_sk->conn_req.link_name)); - cf_sk->conn_req.link_name - [sizeof(cf_sk->conn_req.link_name)-1] = 0; - release_sock(&cf_sk->sk); - return 0; - case CAIFSO_REQ_PARAM: if (lvl != SOL_CAIF) goto bad_sol; @@ -880,6 +852,18 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, sock->state = SS_CONNECTING; sk->sk_state = CAIF_CONNECTING; + /* Check priority value comming from socket */ + /* if priority value is out of range it will be ajusted */ + if (cf_sk->sk.sk_priority > CAIF_PRIO_MAX) + cf_sk->conn_req.priority = CAIF_PRIO_MAX; + else if (cf_sk->sk.sk_priority < CAIF_PRIO_MIN) + cf_sk->conn_req.priority = CAIF_PRIO_MIN; + else + cf_sk->conn_req.priority = cf_sk->sk.sk_priority; + + /*ifindex = id of the interface.*/ + cf_sk->conn_req.ifindex = cf_sk->sk.sk_bound_dev_if; + dbfs_atomic_inc(&cnt.num_connect_req); cf_sk->layer.receive = caif_sktrecv_cb; err = caif_connect_client(&cf_sk->conn_req, @@ -905,6 +889,7 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, cf_sk->maxframe = mtu - (headroom + tailroom); if (cf_sk->maxframe < 1) { pr_warn("CAIF Interface MTU too small (%d)\n", dev->mtu); + err = -ENODEV; goto out; } @@ -1142,7 +1127,7 @@ static int caif_create(struct net *net, struct socket *sock, int protocol, set_rx_flow_on(cf_sk); /* Set default options on configuration */ - cf_sk->conn_req.priority = CAIF_PRIO_NORMAL; + cf_sk->sk.sk_priority= CAIF_PRIO_NORMAL; cf_sk->conn_req.link_selector = CAIF_LINK_LOW_LATENCY; cf_sk->conn_req.protocol = protocol; /* Increase the number of sockets created. */ diff --git a/trunk/net/caif/cfcnfg.c b/trunk/net/caif/cfcnfg.c index 41adafd18914..21ede141018a 100644 --- a/trunk/net/caif/cfcnfg.c +++ b/trunk/net/caif/cfcnfg.c @@ -173,18 +173,15 @@ static struct cfcnfg_phyinfo *cfcnfg_get_phyinfo(struct cfcnfg *cnfg, return NULL; } -int cfcnfg_get_named(struct cfcnfg *cnfg, char *name) + +int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi) { int i; - - /* Try to match with specified name */ - for (i = 0; i < MAX_PHY_LAYERS; i++) { - if (cnfg->phy_layers[i].frm_layer != NULL - && strcmp(cnfg->phy_layers[i].phy_layer->name, - name) == 0) - return cnfg->phy_layers[i].frm_layer->id; - } - return 0; + for (i = 0; i < MAX_PHY_LAYERS; i++) + if (cnfg->phy_layers[i].frm_layer != NULL && + cnfg->phy_layers[i].ifindex == ifi) + return i; + return -ENODEV; } int cfcnfg_disconn_adapt_layer(struct cfcnfg *cnfg, struct cflayer *adap_layer) diff --git a/trunk/net/caif/cfctrl.c b/trunk/net/caif/cfctrl.c index 08f267a109aa..3cd8f978e309 100644 --- a/trunk/net/caif/cfctrl.c +++ b/trunk/net/caif/cfctrl.c @@ -361,11 +361,10 @@ void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer) struct cfctrl_request_info *p, *tmp; struct cfctrl *ctrl = container_obj(layr); spin_lock(&ctrl->info_list_lock); - pr_warn("enter\n"); list_for_each_entry_safe(p, tmp, &ctrl->list, list) { if (p->client_layer == adap_layer) { - pr_warn("cancel req :%d\n", p->sequence_no); + pr_debug("cancel req :%d\n", p->sequence_no); list_del(&p->list); kfree(p); } diff --git a/trunk/net/caif/cfdbgl.c b/trunk/net/caif/cfdbgl.c index 496fda9ac66f..11a2af4c162a 100644 --- a/trunk/net/caif/cfdbgl.c +++ b/trunk/net/caif/cfdbgl.c @@ -12,6 +12,8 @@ #include #include +#define container_obj(layr) ((struct cfsrvl *) layr) + static int cfdbgl_receive(struct cflayer *layr, struct cfpkt *pkt); static int cfdbgl_transmit(struct cflayer *layr, struct cfpkt *pkt); @@ -38,5 +40,17 @@ static int cfdbgl_receive(struct cflayer *layr, struct cfpkt *pkt) static int cfdbgl_transmit(struct cflayer *layr, struct cfpkt *pkt) { + struct cfsrvl *service = container_obj(layr); + struct caif_payload_info *info; + int ret; + + if (!cfsrvl_ready(service, &ret)) + return ret; + + /* Add info for MUX-layer to route the packet out */ + info = cfpkt_info(pkt); + info->channel_id = service->layer.id; + info->dev_info = &service->dev_info; + return layr->dn->transmit(layr->dn, pkt); } diff --git a/trunk/net/caif/cfrfml.c b/trunk/net/caif/cfrfml.c index bde8481e8d25..e2fb5fa75795 100644 --- a/trunk/net/caif/cfrfml.c +++ b/trunk/net/caif/cfrfml.c @@ -193,7 +193,7 @@ static int cfrfml_receive(struct cflayer *layr, struct cfpkt *pkt) static int cfrfml_transmit_segment(struct cfrfml *rfml, struct cfpkt *pkt) { - caif_assert(cfpkt_getlen(pkt) >= rfml->fragment_size); + caif_assert(cfpkt_getlen(pkt) < rfml->fragment_size); /* Add info for MUX-layer to route the packet out. */ cfpkt_info(pkt)->channel_id = rfml->serv.layer.id; diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index 35dfb8318483..0dd54a69dace 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -2131,7 +2131,7 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev, } else { struct sock *sk = skb->sk; queue_index = sk_tx_queue_get(sk); - if (queue_index < 0) { + if (queue_index < 0 || queue_index >= dev->real_num_tx_queues) { queue_index = 0; if (dev->real_num_tx_queues > 1) diff --git a/trunk/net/ipv4/fib_lookup.h b/trunk/net/ipv4/fib_lookup.h index a29edf2219c8..c079cc0ec651 100644 --- a/trunk/net/ipv4/fib_lookup.h +++ b/trunk/net/ipv4/fib_lookup.h @@ -47,11 +47,8 @@ extern int fib_detect_death(struct fib_info *fi, int order, static inline void fib_result_assign(struct fib_result *res, struct fib_info *fi) { - if (res->fi != NULL) - fib_info_put(res->fi); + /* we used to play games with refcounts, but we now use RCU */ res->fi = fi; - if (fi != NULL) - atomic_inc(&fi->fib_clntref); } #endif /* _FIB_LOOKUP_H */ diff --git a/trunk/net/ipv4/inet_diag.c b/trunk/net/ipv4/inet_diag.c index ba8042665849..2ada17129fce 100644 --- a/trunk/net/ipv4/inet_diag.c +++ b/trunk/net/ipv4/inet_diag.c @@ -490,9 +490,11 @@ static int inet_csk_diag_dump(struct sock *sk, { struct inet_diag_req *r = NLMSG_DATA(cb->nlh); - if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) { + if (nlmsg_attrlen(cb->nlh, sizeof(*r))) { struct inet_diag_entry entry; - struct rtattr *bc = (struct rtattr *)(r + 1); + const struct nlattr *bc = nlmsg_find_attr(cb->nlh, + sizeof(*r), + INET_DIAG_REQ_BYTECODE); struct inet_sock *inet = inet_sk(sk); entry.family = sk->sk_family; @@ -512,7 +514,7 @@ static int inet_csk_diag_dump(struct sock *sk, entry.dport = ntohs(inet->inet_dport); entry.userlocks = sk->sk_userlocks; - if (!inet_diag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), &entry)) + if (!inet_diag_bc_run(nla_data(bc), nla_len(bc), &entry)) return 0; } @@ -527,9 +529,11 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, { struct inet_diag_req *r = NLMSG_DATA(cb->nlh); - if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) { + if (nlmsg_attrlen(cb->nlh, sizeof(*r))) { struct inet_diag_entry entry; - struct rtattr *bc = (struct rtattr *)(r + 1); + const struct nlattr *bc = nlmsg_find_attr(cb->nlh, + sizeof(*r), + INET_DIAG_REQ_BYTECODE); entry.family = tw->tw_family; #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) @@ -548,7 +552,7 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, entry.dport = ntohs(tw->tw_dport); entry.userlocks = 0; - if (!inet_diag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), &entry)) + if (!inet_diag_bc_run(nla_data(bc), nla_len(bc), &entry)) return 0; } @@ -618,7 +622,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, struct inet_diag_req *r = NLMSG_DATA(cb->nlh); struct inet_connection_sock *icsk = inet_csk(sk); struct listen_sock *lopt; - struct rtattr *bc = NULL; + const struct nlattr *bc = NULL; struct inet_sock *inet = inet_sk(sk); int j, s_j; int reqnum, s_reqnum; @@ -638,8 +642,9 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, if (!lopt || !lopt->qlen) goto out; - if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) { - bc = (struct rtattr *)(r + 1); + if (nlmsg_attrlen(cb->nlh, sizeof(*r))) { + bc = nlmsg_find_attr(cb->nlh, sizeof(*r), + INET_DIAG_REQ_BYTECODE); entry.sport = inet->inet_num; entry.userlocks = sk->sk_userlocks; } @@ -672,8 +677,8 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, &ireq->rmt_addr; entry.dport = ntohs(ireq->rmt_port); - if (!inet_diag_bc_run(RTA_DATA(bc), - RTA_PAYLOAD(bc), &entry)) + if (!inet_diag_bc_run(nla_data(bc), + nla_len(bc), &entry)) continue; } diff --git a/trunk/net/ipv4/netfilter/arp_tables.c b/trunk/net/ipv4/netfilter/arp_tables.c index 3cad2591ace0..3fac340a28d5 100644 --- a/trunk/net/ipv4/netfilter/arp_tables.c +++ b/trunk/net/ipv4/netfilter/arp_tables.c @@ -927,6 +927,7 @@ static int get_info(struct net *net, void __user *user, private = &tmp; } #endif + memset(&info, 0, sizeof(info)); info.valid_hooks = t->valid_hooks; memcpy(info.hook_entry, private->hook_entry, sizeof(info.hook_entry)); diff --git a/trunk/net/ipv4/netfilter/ip_tables.c b/trunk/net/ipv4/netfilter/ip_tables.c index d31b007a6d80..a846d633b3b6 100644 --- a/trunk/net/ipv4/netfilter/ip_tables.c +++ b/trunk/net/ipv4/netfilter/ip_tables.c @@ -1124,6 +1124,7 @@ static int get_info(struct net *net, void __user *user, private = &tmp; } #endif + memset(&info, 0, sizeof(info)); info.valid_hooks = t->valid_hooks; memcpy(info.hook_entry, private->hook_entry, sizeof(info.hook_entry)); diff --git a/trunk/net/ipv4/netfilter/nf_nat_core.c b/trunk/net/ipv4/netfilter/nf_nat_core.c index 295c97431e43..c04787ce1a71 100644 --- a/trunk/net/ipv4/netfilter/nf_nat_core.c +++ b/trunk/net/ipv4/netfilter/nf_nat_core.c @@ -47,26 +47,6 @@ __nf_nat_proto_find(u_int8_t protonum) return rcu_dereference(nf_nat_protos[protonum]); } -static const struct nf_nat_protocol * -nf_nat_proto_find_get(u_int8_t protonum) -{ - const struct nf_nat_protocol *p; - - rcu_read_lock(); - p = __nf_nat_proto_find(protonum); - if (!try_module_get(p->me)) - p = &nf_nat_unknown_protocol; - rcu_read_unlock(); - - return p; -} - -static void -nf_nat_proto_put(const struct nf_nat_protocol *p) -{ - module_put(p->me); -} - /* We keep an extra hash for each conntrack, for fast searching. */ static inline unsigned int hash_by_src(const struct net *net, u16 zone, @@ -588,6 +568,26 @@ static struct nf_ct_ext_type nat_extend __read_mostly = { #include #include +static const struct nf_nat_protocol * +nf_nat_proto_find_get(u_int8_t protonum) +{ + const struct nf_nat_protocol *p; + + rcu_read_lock(); + p = __nf_nat_proto_find(protonum); + if (!try_module_get(p->me)) + p = &nf_nat_unknown_protocol; + rcu_read_unlock(); + + return p; +} + +static void +nf_nat_proto_put(const struct nf_nat_protocol *p) +{ + module_put(p->me); +} + static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = { [CTA_PROTONAT_PORT_MIN] = { .type = NLA_U16 }, [CTA_PROTONAT_PORT_MAX] = { .type = NLA_U16 }, diff --git a/trunk/net/ipv6/netfilter/ip6_tables.c b/trunk/net/ipv6/netfilter/ip6_tables.c index 51df035897e7..455582384ece 100644 --- a/trunk/net/ipv6/netfilter/ip6_tables.c +++ b/trunk/net/ipv6/netfilter/ip6_tables.c @@ -1137,6 +1137,7 @@ static int get_info(struct net *net, void __user *user, private = &tmp; } #endif + memset(&info, 0, sizeof(info)); info.valid_hooks = t->valid_hooks; memcpy(info.hook_entry, private->hook_entry, sizeof(info.hook_entry)); diff --git a/trunk/net/ipv6/route.c b/trunk/net/ipv6/route.c index 25661f968f3f..fc328339be99 100644 --- a/trunk/net/ipv6/route.c +++ b/trunk/net/ipv6/route.c @@ -2741,6 +2741,7 @@ static void __net_exit ip6_route_net_exit(struct net *net) kfree(net->ipv6.ip6_prohibit_entry); kfree(net->ipv6.ip6_blk_hole_entry); #endif + dst_entries_destroy(&net->ipv6.ip6_dst_ops); } static struct pernet_operations ip6_route_net_ops = { @@ -2832,5 +2833,6 @@ void ip6_route_cleanup(void) xfrm6_fini(); fib6_gc_cleanup(); unregister_pernet_subsys(&ip6_route_net_ops); + dst_entries_destroy(&ip6_dst_blackhole_ops); kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep); } diff --git a/trunk/net/l2tp/l2tp_debugfs.c b/trunk/net/l2tp/l2tp_debugfs.c index 104ec3b283d4..b8dbae82fab8 100644 --- a/trunk/net/l2tp/l2tp_debugfs.c +++ b/trunk/net/l2tp/l2tp_debugfs.c @@ -249,7 +249,7 @@ static int l2tp_dfs_seq_open(struct inode *inode, struct file *file) struct seq_file *seq; int rc = -ENOMEM; - pd = kzalloc(GFP_KERNEL, sizeof(*pd)); + pd = kzalloc(sizeof(*pd), GFP_KERNEL); if (pd == NULL) goto out; diff --git a/trunk/net/netfilter/nf_conntrack_core.c b/trunk/net/netfilter/nf_conntrack_core.c index 1eacf8d9966a..27a5ea6b6a0f 100644 --- a/trunk/net/netfilter/nf_conntrack_core.c +++ b/trunk/net/netfilter/nf_conntrack_core.c @@ -1312,7 +1312,8 @@ void *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced, int nulls) if (!hash) { *vmalloced = 1; printk(KERN_WARNING "nf_conntrack: falling back to vmalloc.\n"); - hash = __vmalloc(sz, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL); + hash = __vmalloc(sz, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, + PAGE_KERNEL); } if (hash && nulls) diff --git a/trunk/net/netfilter/nf_conntrack_proto.c b/trunk/net/netfilter/nf_conntrack_proto.c index ed6d92958023..dc7bb74110df 100644 --- a/trunk/net/netfilter/nf_conntrack_proto.c +++ b/trunk/net/netfilter/nf_conntrack_proto.c @@ -292,6 +292,12 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto) for (i = 0; i < MAX_NF_CT_PROTO; i++) proto_array[i] = &nf_conntrack_l4proto_generic; + + /* Before making proto_array visible to lockless readers, + * we must make sure its content is committed to memory. + */ + smp_wmb(); + nf_ct_protos[l4proto->l3proto] = proto_array; } else if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto] != &nf_conntrack_l4proto_generic) { diff --git a/trunk/net/rds/loop.c b/trunk/net/rds/loop.c index c390156b426f..aeec1d483b17 100644 --- a/trunk/net/rds/loop.c +++ b/trunk/net/rds/loop.c @@ -134,8 +134,12 @@ static int rds_loop_conn_alloc(struct rds_connection *conn, gfp_t gfp) static void rds_loop_conn_free(void *arg) { struct rds_loop_connection *lc = arg; + unsigned long flags; + rdsdebug("lc %p\n", lc); + spin_lock_irqsave(&loop_conns_lock, flags); list_del(&lc->loop_node); + spin_unlock_irqrestore(&loop_conns_lock, flags); kfree(lc); } diff --git a/trunk/net/rds/tcp.c b/trunk/net/rds/tcp.c index 08a8c6cf2d10..8e0a32001c90 100644 --- a/trunk/net/rds/tcp.c +++ b/trunk/net/rds/tcp.c @@ -221,7 +221,13 @@ static int rds_tcp_conn_alloc(struct rds_connection *conn, gfp_t gfp) static void rds_tcp_conn_free(void *arg) { struct rds_tcp_connection *tc = arg; + unsigned long flags; rdsdebug("freeing tc %p\n", tc); + + spin_lock_irqsave(&rds_tcp_conn_lock, flags); + list_del(&tc->t_tcp_node); + spin_unlock_irqrestore(&rds_tcp_conn_lock, flags); + kmem_cache_free(rds_tcp_conn_slab, tc); } diff --git a/trunk/net/sched/cls_cgroup.c b/trunk/net/sched/cls_cgroup.c index 37dff78e9cb1..d49c40fb7e09 100644 --- a/trunk/net/sched/cls_cgroup.c +++ b/trunk/net/sched/cls_cgroup.c @@ -34,8 +34,6 @@ struct cgroup_subsys net_cls_subsys = { .populate = cgrp_populate, #ifdef CONFIG_NET_CLS_CGROUP .subsys_id = net_cls_subsys_id, -#else -#define net_cls_subsys_id net_cls_subsys.subsys_id #endif .module = THIS_MODULE, }; diff --git a/trunk/net/sched/em_text.c b/trunk/net/sched/em_text.c index 763253257411..ea8f566e720c 100644 --- a/trunk/net/sched/em_text.c +++ b/trunk/net/sched/em_text.c @@ -103,7 +103,8 @@ static int em_text_change(struct tcf_proto *tp, void *data, int len, static void em_text_destroy(struct tcf_proto *tp, struct tcf_ematch *m) { - textsearch_destroy(EM_TEXT_PRIV(m)->config); + if (EM_TEXT_PRIV(m) && EM_TEXT_PRIV(m)->config) + textsearch_destroy(EM_TEXT_PRIV(m)->config); } static int em_text_dump(struct sk_buff *skb, struct tcf_ematch *m) diff --git a/trunk/net/x25/x25_facilities.c b/trunk/net/x25/x25_facilities.c index 771bab00754b..3a8c4c419cd4 100644 --- a/trunk/net/x25/x25_facilities.c +++ b/trunk/net/x25/x25_facilities.c @@ -134,15 +134,15 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, case X25_FAC_CLASS_D: switch (*p) { case X25_FAC_CALLING_AE: - if (p[1] > X25_MAX_DTE_FACIL_LEN) - break; + if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] <= 1) + return 0; dte_facs->calling_len = p[2]; memcpy(dte_facs->calling_ae, &p[3], p[1] - 1); *vc_fac_mask |= X25_MASK_CALLING_AE; break; case X25_FAC_CALLED_AE: - if (p[1] > X25_MAX_DTE_FACIL_LEN) - break; + if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] <= 1) + return 0; dte_facs->called_len = p[2]; memcpy(dte_facs->called_ae, &p[3], p[1] - 1); *vc_fac_mask |= X25_MASK_CALLED_AE; diff --git a/trunk/net/x25/x25_in.c b/trunk/net/x25/x25_in.c index 63178961efac..f729f022be69 100644 --- a/trunk/net/x25/x25_in.c +++ b/trunk/net/x25/x25_in.c @@ -119,6 +119,8 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp &x25->vc_facil_mask); if (len > 0) skb_pull(skb, len); + else + return -1; /* * Copy any Call User Data. */