#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_DAVINCI_GPIO_SHIFT_REGISTER static int gpio_shift_register_init(void); #endif /*--- #ifdef CONFIG_DAVINCI_GPIO_SHIFT_REGISTER ---*/ /* create a non-inlined version */ static struct gpio_controller *__iomem gpio2controller(unsigned gpio) { return gpio_to_controller(gpio); } /*--------------------------------------------------------------------------*/ /* * Assuming the pin is muxed as a gpio output, set its output value. */ int __gpio_set(unsigned gpio, int value) { struct gpio_controller *__iomem g = gpio2controller(gpio); if (!g) return -EINVAL; __raw_writel(gpio_mask(gpio), value ? &g->set_data : &g->clr_data); return 0; } EXPORT_SYMBOL(__gpio_set); /* * Read the pin's value (works even if it's not set up as output); * returns zero/nonzero. * * Note that changes are synched to the GPIO clock, so reading values back * right after you've set them may give old values. */ int __gpio_get(unsigned gpio) { struct gpio_controller *__iomem g = gpio2controller(gpio); if (!g) return -EINVAL; return !!(gpio_mask(gpio) & __raw_readl(&g->in_data)); } EXPORT_SYMBOL(__gpio_get); /*--------------------------------------------------------------------------*/ /* * We expect board setup code to handle all gpio direction setup, * so there's no need to let driver modules do it. * * That same board setup code must also set PINMUX0 and PINMUX1 as * needed, and enable the GPIO clock. */ int /* __init */ gpio_set_direction(unsigned gpio, int is_in) { struct gpio_controller *__iomem g = gpio2controller(gpio); u32 temp; u32 mask; if (!g) return -EINVAL; g = gpio_to_controller(gpio); mask = gpio_mask(gpio); temp = __raw_readl(&g->dir); if (is_in) temp |= mask; else temp &= ~mask; __raw_writel(temp, &g->dir); return 0; } EXPORT_SYMBOL(gpio_set_direction); /*--------------------------------------------------------------------------*/ /* * We expect irqs will normally be set up as input pins, but they can also be * used as output pins ... which is convenient for testing. * * NOTE: GPIO0..GPIO7 also have direct INTC hookups, which work in addition * to their GPIOBNK0 irq (but with a bit less overhead). But we don't have * a good way to hook those up ... * * All those INTC hookups (GPIO0..GPIO7 plus five IRQ banks) can also * serve as EDMA event triggers. */ #define irq2gpio(irq) ((irq) - DAVINCI_N_AINTC_IRQ) static void gpio_irq_disable(unsigned irq) { struct gpio_controller *__iomem g = get_irq_chipdata(irq); u32 mask = gpio_mask(irq2gpio(irq)); __raw_writel(mask, &g->clr_falling); __raw_writel(mask, &g->clr_rising); } static void gpio_irq_enable(unsigned irq) { struct gpio_controller *__iomem g = get_irq_chipdata(irq); u32 mask = gpio_mask(irq2gpio(irq)); if (irq_desc[irq].status & IRQ_TYPE_EDGE_FALLING) __raw_writel(mask, &g->set_falling); if (irq_desc[irq].status & IRQ_TYPE_EDGE_RISING) __raw_writel(mask, &g->set_rising); } static int gpio_irq_type(unsigned irq, unsigned trigger) { struct gpio_controller *__iomem g = get_irq_chipdata(irq); unsigned mask = gpio_mask(irq2gpio(irq)); if (trigger & ~(IRQ_TYPE_EDGE_FALLING|IRQ_TYPE_EDGE_RISING)) return -EINVAL; irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK; irq_desc[irq].status |= trigger; __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING) ? &g->set_falling : &g->clr_falling); __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING) ? &g->set_rising : &g->clr_rising); return 0; } static struct irq_chip gpio_irqchip = { .name = "GPIO", .enable = gpio_irq_enable, .disable = gpio_irq_disable, .set_type = gpio_irq_type, // .set_wake = ... }; static void gpio_irq_handler(unsigned irq, struct irqdesc *desc) { struct gpio_controller *__iomem g = get_irq_chipdata(irq); u32 mask = 0xffff; /* we only care about one bank */ if (irq & 1) mask <<= 16; /* temporarily mask (level sensitive) parent IRQ */ desc->chip->ack(irq); for (;;) { u32 status; struct irqdesc *gpio; int n; /* ack any irqs */ status = __raw_readl(&g->intstat) & mask; if (!status) break; __raw_writel(status, &g->intstat); if (irq & 1) status >>= 16; /* now demux them to the right lowlevel handler */ n = (int) get_irq_data(irq); gpio = &irq_desc[n]; while (status) { if (status & 1) gpio->handle_irq(n, gpio); n++; gpio++; status >>= 1; } } desc->chip->unmask(irq); /* now it may re-trigger */ } /* * NOTE: for suspend/resume, probably best to make a sysdev (and class) * with its suspend/resume calls hooking into the results of the set_wake() * calls ... so if no gpios are wakeup events the clock can be disabled, * with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0 * can be set appropriately for GPIOV33 pins. */ static int __init davinci_gpio_irq_setup(void) { static const char __initdata err1[] = KERN_ERR "Error %ld getting gpio clock?\n"; static const char __initdata info1[] = KERN_INFO "DaVinci: %d gpio irqs\n"; unsigned gpio, irq, bank; struct clk *clk; clk = clk_get(NULL, "gpio"); if (IS_ERR(clk)) { printk(err1, PTR_ERR(clk)); return 0; } clk_enable(clk); for (gpio = 0, irq = DAVINCI_GPIO_IRQ(0), bank = IRQ_GPIOBNK0; gpio < DAVINCI_N_GPIO; bank++) { struct gpio_controller *__iomem g = gpio2controller(gpio); unsigned i; __raw_writel(~0, &g->clr_falling); __raw_writel(~0, &g->clr_rising); /* set up all irqs in this bank */ set_irq_chained_handler(bank, gpio_irq_handler); set_irq_chipdata(bank, g); set_irq_data(bank, (void *) irq); for (i = 0; i < 16 && gpio < DAVINCI_N_GPIO; i++, irq++, gpio++) { set_irq_chip(irq, &gpio_irqchip); set_irq_chipdata(irq, g); set_irq_handler(irq, do_simple_IRQ); set_irq_flags(irq, IRQF_VALID); } } /* BINTEN -- per-bank interrupt enable. genirq would also let these * bits be set/cleared dynamically. */ __raw_writel(0x1f, (void *__iomem) IO_ADDRESS(DAVINCI_GPIO_BASE + 0x08)); printk(info1, irq - DAVINCI_GPIO_IRQ(0)); return 0; } arch_initcall(davinci_gpio_irq_setup); /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void davinci_gpio_init(void) { #ifdef CONFIG_DAVINCI_GPIO_SHIFT_REGISTER gpio_shift_register_init(); #endif /*--- #ifdef CONFIG_DAVINCI_GPIO_SHIFT_REGISTER ---*/ return; } extern void board_setup_gpio(char *text, unsigned int gpio); int davinci_gpio_ctrl(unsigned int gpio_pin, enum _hw_gpio_function pin_mode, enum _hw_gpio_direction pin_dir) { #if 0 struct resource *my_resource; my_resource = (struct resource *)kmalloc(sizeof(struct resource) + 40, GFP_ATOMIC); if(my_resource) { memset(my_resource, 0, sizeof(struct resource)); my_resource->name = (char *)((unsigned int)my_resource + sizeof(struct resource)); if(pin_mode == GPIO_PIN) { strcpy(my_resource->name, "GPIO pin"); } else { strcpy(my_resource->name, "GPIO function"); } if(request_resource(&gpio_resource, my_resource)) { printk(KERN_WARNING "WARNING: gpio %u my be allocated already\n", gpio_pin); kfree(my_resource); } } else #endif if(pin_mode == GPIO_PIN) { board_setup_gpio("[davinci_gpio_ctrl]", gpio_pin); } return gpio_set_direction(gpio_pin, pin_dir == GPIO_INPUT_PIN ? 1 : 0); } int davinci_gpio_out_bit(unsigned int gpio_pin, int value) { if(value) return gpio_set(gpio_pin); return gpio_clear(gpio_pin); } int davinci_gpio_in_bit(unsigned int gpio_pin) { return gpio_get_value(gpio_pin); } unsigned long long davinci_gpio_in_value(void) { printk(KERN_ERR "[davinci_gpio_in_value] not supported\n"); return 0; } void davinci_gpio_set_bitmask(unsigned long long mask, unsigned long value) { unsigned int i; for(i = 0 ; i < sizeof(mask) * 8 ; i++) { if(mask & ((unsigned long long)1 << i)) davinci_gpio_out_bit(i, (value >> i) & 0x01); } } #ifdef CONFIG_DAVINCI_GPIO_SHIFT_REGISTER /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static struct resource my_shift_register_resource[] = { #if CONFIG_DAVINCI_GPIO_SHIFT_REGISTER_COUNT >= 1 { .name = "shift register bit clock 0", .start = CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA0_CLOCK, .end = CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA0_CLOCK, .flags = IORESOURCE_IO }, #endif /*--- #if CONFIG_DAVINCI_GPIO_SHIFT_REGISTER_COUNT >= 1 ---*/ #if CONFIG_DAVINCI_GPIO_SHIFT_REGISTER_COUNT >= 2 { .name = "shift register bit clock 1", .start = CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA1_CLOCK, .end = CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA1_CLOCK, .flags = IORESOURCE_IO }, #endif /*--- #if CONFIG_DAVINCI_GPIO_SHIFT_REGISTER_COUNT >= 2 ---*/ { .name = "shift register store clock", .start = CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_STORAGE_CLOCK, .end = CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_STORAGE_CLOCK, .flags = IORESOURCE_IO }, #if CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_MASTER_RESET != -1 { .name = "shift register master reset", .start = CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_MASTER_RESET, .end = CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_MASTER_RESET, .flags = IORESOURCE_IO }, #endif /*--- #if CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_MASTER_RESET != -1 ---*/ { .name = "shift register bit data", .start = CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA, .end = CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA, .flags = IORESOURCE_IO } }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static unsigned int gpio_shift_register_contence = 0; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static int gpio_shift_register_init(void) { int i; if(davinci_revision[1] == 1) { for(i = 0 ; i < sizeof(my_shift_register_resource) / sizeof(my_shift_register_resource[0]) ; i++) { if(request_resource(&gpio_resource, &my_shift_register_resource[i])) { printk(KERN_ERR "ERROR: shift register: could not allocate gpio %d for %s\n", my_shift_register_resource[i].name, my_shift_register_resource[i].start); return 1; } } #if CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_MASTER_RESET != -1 davinci_gpio_ctrl(CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_MASTER_RESET, GPIO_PIN, GPIO_OUTPUT_PIN); #endif /*--- #if CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_MASTER_RESET != -1 ---*/ davinci_gpio_ctrl(CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA0_CLOCK , GPIO_PIN, GPIO_OUTPUT_PIN); #if CONFIG_DAVINCI_GPIO_SHIFT_REGISTER_COUNT >= 2 davinci_gpio_ctrl(CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA1_CLOCK , GPIO_PIN, GPIO_OUTPUT_PIN); #endif /*--- #if CONFIG_DAVINCI_GPIO_SHIFT_REGISTER_COUNT >= 2 ---*/ davinci_gpio_ctrl(CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_STORAGE_CLOCK, GPIO_PIN, GPIO_OUTPUT_PIN); davinci_gpio_ctrl(CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA, GPIO_PIN, GPIO_OUTPUT_PIN); } else { printk(KERN_WARNING "no shift register support on first davinci hardware\n"); } return 0; } arch_initcall(gpio_shift_register_init); /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void gpio_shift_register_load(unsigned int mask, unsigned int values) { struct gpio_controller *GPIO1 = (struct gpio_controller *)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10); struct gpio_controller *GPIO2 = (struct gpio_controller *)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38); unsigned int i; struct _shift_register_bits { volatile unsigned int *p_set_shift_clock[2]; volatile unsigned int *p_set_store_clock; volatile unsigned int *p_set_shift_data; volatile unsigned int *p_clear_shift_clock[2]; volatile unsigned int *p_clear_store_clock; volatile unsigned int *p_clear_shift_data; unsigned int shift_clock[2]; unsigned int store_clock; unsigned int shift_data; }; static struct _shift_register_bits shift_register_bits; unsigned int shift_register; static int init_done = 0; if(davinci_revision[1] != 1) { return; } if(init_done == 0) { init_done = 1; #if CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA0_CLOCK > 32 shift_register_bits.p_set_shift_clock[0] = &GPIO2->set_data; shift_register_bits.p_clear_shift_clock[0] = &GPIO2->clr_data; shift_register_bits.shift_clock[0] = 1 << (CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA0_CLOCK - 32); #else /*--- #if CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA0_CLOCK > 32 ---*/ shift_register_bits.p_set_shift_clock[0] = &GPIO1->set_data; shift_register_bits.p_clear_shift_clock[0] = &GPIO1->clr_data; shift_register_bits.shift_clock[0] = 1 << (CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA0_CLOCK - 0); #endif /*--- #else ---*/ /*--- #if CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA0_CLOCK > 32 ---*/ printk(KERN_NOTICE "CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA0_CLOCK : set 0x%p, clr 0x%p: 0x%x\n", shift_register_bits.p_set_shift_clock[0], shift_register_bits.p_clear_shift_clock[0], shift_register_bits.shift_clock[0]); #if CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA1_CLOCK > 32 shift_register_bits.p_set_shift_clock[1] = &GPIO2->set_data; shift_register_bits.p_clear_shift_clock[1] = &GPIO2->clr_data; shift_register_bits.shift_clock[1] = 1 << (CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA1_CLOCK - 32); #else /*--- #if CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA1_CLOCK > 32 ---*/ shift_register_bits.p_set_shift_clock[1] = &GPIO1->set_data; shift_register_bits.p_clear_shift_clock[1] = &GPIO1->clr_data; shift_register_bits.shift_clock[1] = 1 << (CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA1_CLOCK - 0); #endif /*--- #else ---*/ /*--- #if CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA1_CLOCK > 32 ---*/ printk(KERN_NOTICE "CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA1_CLOCK : set 0x%p, clr 0x%p: 0x%x\n", shift_register_bits.p_set_shift_clock[1], shift_register_bits.p_clear_shift_clock[1], shift_register_bits.shift_clock[1]); #if CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_STORAGE_CLOCK > 32 shift_register_bits.p_set_store_clock = &GPIO2->set_data; shift_register_bits.p_clear_store_clock = &GPIO2->clr_data; shift_register_bits.store_clock = 1 << (CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_STORAGE_CLOCK - 32); #else /*--- #if CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_STORAGE_CLOCK > 32 ---*/ shift_register_bits.p_set_store_clock = &GPIO1->set_data; shift_register_bits.p_clear_store_clock = &GPIO1->clr_data; shift_register_bits.store_clock = 1 << (CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_STORAGE_CLOCK - 0); #endif /*--- #else ---*/ /*--- #if CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_STORAGE_CLOCK > 32 ---*/ printk(KERN_NOTICE "CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_STORAGE_CLOCK : set 0x%p, clr 0x%p: 0x%x\n", shift_register_bits.p_set_store_clock, shift_register_bits.p_clear_store_clock, shift_register_bits.store_clock); #if CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA > 32 shift_register_bits.p_set_shift_data = &GPIO2->set_data; shift_register_bits.p_clear_shift_data = &GPIO2->clr_data; shift_register_bits.shift_data = 1 << (CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA - 32); #else /*--- #if CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA > 32 ---*/ shift_register_bits.p_set_shift_data = &GPIO1->set_data; shift_register_bits.p_clear_shift_data = &GPIO1->clr_data; shift_register_bits.shift_data = 1 << (CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA - 0); #endif /*--- #else ---*/ /*--- #if CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA > 32 ---*/ printk(KERN_NOTICE "CONFIG_GPIO_OUTPUT_SHIFT_REGISTER_DATA: set 0x%p, clr 0x%p: 0x%x\n", shift_register_bits.p_set_shift_data, shift_register_bits.p_clear_shift_data, shift_register_bits.shift_data); } gpio_shift_register_contence &= ~mask; gpio_shift_register_contence |= mask & values; if(mask & 0xFFFF) { shift_register = 0; /*--- printk("[gpio_shift_register_load] mask 0x%x value 0x%x gpio_shift_register_contence 0x%x\n", ---*/ /*--- mask, values, gpio_shift_register_contence); ---*/ *(shift_register_bits.p_clear_shift_clock[shift_register]) = shift_register_bits.shift_clock[shift_register]; *(shift_register_bits.p_clear_store_clock) = shift_register_bits.store_clock; for(mask = gpio_shift_register_contence >> (16 * shift_register), i = CONFIG_DAVINCI_GPIO_SHIFT_REGISTER_WIDTH ; i ; i-- ) { *(shift_register_bits.p_clear_shift_clock[shift_register]) = shift_register_bits.shift_clock[shift_register]; /*------------------------------------------------------------------------------*\ * LED shift Register invertrierte Logic !! \*------------------------------------------------------------------------------*/ if(mask & (1 << (i - 1))) *(shift_register_bits.p_set_shift_data) = shift_register_bits.shift_data; else *(shift_register_bits.p_clear_shift_data) = shift_register_bits.shift_data; *(shift_register_bits.p_set_shift_clock[shift_register]) = shift_register_bits.shift_clock[shift_register]; } *(shift_register_bits.p_set_store_clock) = shift_register_bits.store_clock; *(shift_register_bits.p_clear_store_clock) = shift_register_bits.store_clock; *(shift_register_bits.p_clear_shift_clock[shift_register]) = shift_register_bits.shift_clock[shift_register]; } if(mask & 0xFFFF0000) { shift_register = 1; /*--- printk("[gpio_shift_register_load] mask 0x%x value 0x%x gpio_shift_register_contence 0x%x\n", ---*/ /*--- mask, values, gpio_shift_register_contence); ---*/ *(shift_register_bits.p_clear_shift_clock[shift_register]) = shift_register_bits.shift_clock[shift_register]; *(shift_register_bits.p_clear_store_clock) = shift_register_bits.store_clock; for(mask = gpio_shift_register_contence >> (16 * shift_register), i = CONFIG_DAVINCI_GPIO_SHIFT_REGISTER_WIDTH ; i ; i-- ) { *(shift_register_bits.p_clear_shift_clock[shift_register]) = shift_register_bits.shift_clock[shift_register]; if(mask & (1 << (i - 1))) *(shift_register_bits.p_set_shift_data) = shift_register_bits.shift_data; else *(shift_register_bits.p_clear_shift_data) = shift_register_bits.shift_data; *(shift_register_bits.p_set_shift_clock[shift_register]) = shift_register_bits.shift_clock[shift_register]; } *(shift_register_bits.p_set_store_clock) = shift_register_bits.store_clock; *(shift_register_bits.p_clear_store_clock) = shift_register_bits.store_clock; *(shift_register_bits.p_clear_shift_clock[shift_register]) = shift_register_bits.shift_clock[shift_register]; } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ EXPORT_SYMBOL(gpio_shift_register_load); #endif /*--- #ifdef CONFIG_DAVINCI_GPIO_SHIFT_REGISTER ---*/ EXPORT_SYMBOL(davinci_gpio_ctrl); EXPORT_SYMBOL(davinci_gpio_out_bit); EXPORT_SYMBOL(davinci_gpio_in_bit); EXPORT_SYMBOL(davinci_gpio_in_value); EXPORT_SYMBOL(davinci_gpio_set_bitmask);