#define CONFIG_MIPS_IKAN /*-----------------------------------------------------------------------------------------------*\ \*-----------------------------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*--- #define AR7GPIO_DEBUG ---*/ #undef AR7GPIO_DEBUG #if defined(AR7GPIO_DEBUG) #define DBG(...) printk(KERN_INFO __VA_ARGS__) #else /*--- #if defined(AR7GPIO_DEBUG) ---*/ #define DBG(...) #endif /*--- #else ---*/ /*--- #if defined(AR7GPIO_DEBUG) ---*/ #if defined (CONFIG_MIPS_IKAN) static spinlock_t ikan_gpio_spinlock; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void ikan_gpio_dump_registers(void) { } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void reset_registers(void) { IKS_REG_W32(0, VX185_GPIO_ALTFUNC_SEL); IKS_REG_W32(0, VX185_GPIO_ALTFUNC_VAL); IKS_REG_W32(0xffffffff, VX185_GPIO_OUTPUT_CLEAR); IKS_REG_W32(0, VX185_GPIO_MODE1); IKS_REG_W32(0, VX185_GPIO_MODE2); } #if defined(AR7GPIO_DEBUG) /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ static void gpiodump(unsigned int pin) { unsigned int mode; if(pin < 16){ mode = (IKS_REG_R32(VX185_GPIO_MODE1) >> (pin * 2) ) & 0x3; }else{ mode = (IKS_REG_R32(VX185_GPIO_MODE2) >> ((pin - 16) * 2)) & 0x3; } DBG("[GPIO]%s:%d: %s %s \n", __func__, pin, (IKS_REG_R32(VX185_GPIO_ALTFUNC_SEL) & ( 1 << pin)) ? "func" : "gpio", mode == 0 ? "in " : mode == 1 ? "out" : mode == 2 ? "od " : "os "); } #endif/*--- #if defined(AR7GPIO_DEBUG) ---*/ /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void set_gpio_mode(unsigned int pin, unsigned int mode) { unsigned int mode_reg, val; mode &= 0x3; if((pin > 31) || (mode > 3)) { printk(KERN_INFO"[GPIO] %s(%d,%d) invalid param\n", __func__, pin, mode); return; } if(pin < 16){ mode_reg = VX185_GPIO_MODE1; }else{ mode_reg = VX185_GPIO_MODE2; pin -= 16; } val = IKS_REG_R32(mode_reg); val &= ~(0x3 << (2 * pin)); val |= (mode << (2 * pin)); IKS_REG_W32(val, mode_reg); } struct _avm_hw_config *avm_get_hw_config_table(void); #define IS_GPIO_CFG(C) ((C->name[0] == 'g') && \ (C->name[1] == 'p') && \ (C->name[2] == 'i') && \ (C->name[3] == 'o') && \ (C->name[4] == '_')) void init_gpio_config(void) { struct _avm_hw_config *config; config = avm_get_hw_config_table(); if(!config) { return; // error: no hardware config found! } /*--- Reset GPIO functions: ---*/ reset_registers(); /*--- Set GPIO functions according to hardware config: ---*/ while(config->name) { if(IS_GPIO_CFG(config)) { struct _manufactor_ikanos_gpio_config gpio_cfg = config->manufactor_hw_config.manufactor_ikanos_gpio_config; /*--- configure pin mode (in, out, open drain, open source) ---*/ set_gpio_mode(config->value, gpio_cfg.mode); if(gpio_cfg.func_reg) { unsigned int val; val = IKS_REG_R32(gpio_cfg.func_reg); /*--- printk(KERN_INFO"[%s] %s on pin %d configured as function\n", __FUNCTION__, config->name, config->value); ---*/ val &= ~gpio_cfg.func_mask; val |= gpio_cfg.func_set; IKS_REG_W32(val, gpio_cfg.func_reg); } else { /*--- printk(KERN_INFO"[%s] %s on pin %d configured as GPIO\n", __FUNCTION__, config->name, config->value); ---*/ ikan_gpio_ctrl(config->value, GPIO_PIN, gpio_cfg.dir); } } config++; } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int __init ikan_gpio_init(void) { printk(KERN_INFO"[%s]\n", __func__); spin_lock_init(&ikan_gpio_spinlock); init_gpio_config(); return 0; } arch_initcall(ikan_gpio_init); /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int ikan_gpio_ctrl(unsigned int gpio_pin, enum _hw_gpio_function pin_mode, enum _hw_gpio_direction pin_dir) { unsigned int val; unsigned long flags; /*--- printk(KERN_INFO"[GPIO] %s: pin %d is %s %s\n" , __func__, gpio_pin, pin_mode == GPIO_PIN ? "gpio" : "func", pin_dir == GPIO_OUTPUT_PIN ? "output" : "input"); ---*/ if(gpio_pin > 31){ printk(KERN_ERR"[GPIO] invalid gpio pin %d\n", gpio_pin); return (-EINVAL); } spin_lock_irqsave(&ikan_gpio_spinlock, flags); val = IKS_REG_R32(VX185_GPIO_ALTFUNC_SEL); if(pin_mode == GPIO_PIN) { val &= ~(1 << gpio_pin); } else { val |= (1 << gpio_pin); } IKS_REG_W32(val, VX185_GPIO_ALTFUNC_SEL); set_gpio_mode(gpio_pin, pin_dir == GPIO_OUTPUT_PIN ? 1 : 0); /*--- gpiodump(gpio_pin); ---*/ spin_unlock_irqrestore(&ikan_gpio_spinlock, flags); return (0); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int ikan_read_irq_gpio(struct _hw_gpio_irqhandle *handle, unsigned int gpio_pin, unsigned int mask) { printk(KERN_ERR"[%s] IRQ mode not supported.\n", __func__); return -ENOTSUPP; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ struct _hw_gpio_irqhandle *ikan_gpio_request_irq(unsigned int mask, enum _hw_gpio_polarity mode, enum _hw_gpio_sensitivity edge, int (*handle_func)(unsigned int)) { printk(KERN_ERR"[%s] IRQ mode not supported.\n", __func__); return NULL; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void ikan_gpio_set_delayed_irq_mode(struct _hw_gpio_irqhandle *handle, int delayed) { printk(KERN_ERR"[%s] IRQ mode not supported.\n", __func__); return; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int ikan_gpio_enable_irq(struct _hw_gpio_irqhandle *handle) { printk(KERN_ERR"[GPIO]%s: IRQ mode not supported.\n", __func__); return -ENOTSUPP; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int ikan_gpio_disable_irq(struct _hw_gpio_irqhandle *handle) { printk(KERN_ERR"[GPIO]%s: IRQ mode not supported.\n", __func__); return -ENOTSUPP; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int ikan_gpio_out_bit(unsigned int gpio_pin, int value) { unsigned long flags; if(gpio_pin > 31){ printk(KERN_ERR"[GPIO] invalid gpio pin %d\n", gpio_pin); return (-EINVAL); } spin_lock_irqsave(&ikan_gpio_spinlock, flags); if(value){ IKS_REG_W32((1 << gpio_pin), VX185_GPIO_OUTPUT_SET); }else{ IKS_REG_W32((1 << gpio_pin), VX185_GPIO_OUTPUT_CLEAR); } DBG("[GPIO]%s pin %d -> %d\n", __FUNCTION__, gpio_pin, value); /*--- gpiodump(gpio_pin); ---*/ spin_unlock_irqrestore(&ikan_gpio_spinlock, flags); return (0); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int ikan_gpio_in_bit(unsigned int gpio_pin) { if(gpio_pin > 31){ printk(KERN_ERR"[GPIO] invalid gpio pin %d\n", gpio_pin); return (-1); } return (IKS_REG_R32(VX185_GPIO_INPUT) & (1 << gpio_pin)) ? 1 : 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ unsigned int ikan_gpio_in_value(void) { return IKS_REG_R32(VX185_GPIO_INPUT); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void ikan_gpio_set_bitmask(unsigned int mask, unsigned int value) { unsigned long flags; spin_lock_irqsave(&ikan_gpio_spinlock, flags); IKS_REG_W32((value & mask), VX185_GPIO_OUTPUT_SET); IKS_REG_W32((~value & mask), VX185_GPIO_OUTPUT_CLEAR); spin_unlock_irqrestore(&ikan_gpio_spinlock, flags); } EXPORT_SYMBOL(ikan_gpio_ctrl); EXPORT_SYMBOL(ikan_gpio_request_irq); EXPORT_SYMBOL(ikan_gpio_set_delayed_irq_mode); EXPORT_SYMBOL(ikan_gpio_enable_irq); EXPORT_SYMBOL(ikan_gpio_disable_irq); EXPORT_SYMBOL(ikan_read_irq_gpio); EXPORT_SYMBOL(ikan_gpio_out_bit); EXPORT_SYMBOL(ikan_gpio_in_bit); EXPORT_SYMBOL(ikan_gpio_in_value); EXPORT_SYMBOL(ikan_gpio_set_bitmask); #endif /*--- #if defined (CONFIG_MIPS_IKAN) ---*/