/** * gpio drive strength slector */ int gpio_drive_slector(unsigned gpio, enum GPIODriveSlector slector) { struct rk_gpio_bank *bank = rk_gpio_get_bank(gpio); void __iomem *base; u32 val; if (bank == NULL) { return -1; } gpio = (gpio & RK_GPIO_PIN_MASK) >> RK_GPIO_PIN_OFFSET; if (gpio >= bank->ngpio) { return -1; } #if (CONFIG_RKCHIPTYPE == CONFIG_RK3288) /* * drive slector * 2'b00: 2mA * 2'b01: 4mA * 2'b10: 8mA * 2'b11: 12mA */ switch (slector) { case GPIODrv2mA: val = 0; break; case GPIODrv4mA: val = 1; break; case GPIODrv8mA: val = 2; break; case GPIODrv12mA: val = 3; break; default: return -EINVAL; } if (bank->id == 0) { /* gpio0, pmu control */ if (gpio < (8+8+3)) { /* gpio0_a0-a8, gpio0_b0-b8, gpio0_c0-c2 */ base = (void __iomem *)(RKIO_PMU_PHYS + PMU_GPIO0A_DRV + ((gpio / 8) * 4)); gpio = (gpio % 8) * 2; __raw_writel((0x3 << (16 + gpio)) | (val << gpio), base); } } else { /* gpio1-gpio8, grf control */ base = (void __iomem *)((RKIO_GRF_PHYS + (GRF_GPIO1D_E - 0xC) + (bank->id - 1) * 16) + ((gpio / 8) * 4)); gpio = (7 - (gpio % 8)) * 2; __raw_writel((0x3 << (16 + gpio)) | (val << gpio), base); } #else /* check chip if support gpio drive slector */ #endif return 0; }
/** * Get value of the specified gpio */ int gpio_get_value(unsigned gpio) { struct rk_gpio_bank *bank = rk_gpio_get_bank(gpio); if (bank == NULL) { return -1; } gpio = (gpio & RK_GPIO_PIN_MASK) >> RK_GPIO_PIN_OFFSET; if (gpio >= bank->ngpio) { return -1; } return rk_gpio_get_pin_level(bank->regbase, offset_to_bit(gpio)); }
/** * Set gpio direction as input */ int gpio_direction_input(unsigned gpio) { struct rk_gpio_bank *bank = rk_gpio_get_bank(gpio); if (bank == NULL) return -1; gpio = (gpio & RK_GPIO_PIN_MASK) >> RK_GPIO_PIN_OFFSET; if (gpio >= bank->ngpio) return -1; rk_gpio_set_pin_direction(bank->regbase, offset_to_bit(gpio), GPIO_IN); return 0; }
/** * Set gpio pull up or down mode */ int gpio_pull_updown(unsigned gpio, enum GPIOPullType type) { struct rk_gpio_bank *bank = rk_gpio_get_bank(gpio); void __iomem *base; u32 val; if (bank == NULL) { return -1; } gpio = (gpio & RK_GPIO_PIN_MASK) >> RK_GPIO_PIN_OFFSET; if (gpio >= bank->ngpio) { return -1; } #if defined(CONFIG_RKCHIP_RK3188) /* * pull setting * 2'b00: Z(Noraml operaton) * 2'b01: weak 1(pull-up) * 2'b10: weak 0(pull-down) * 2'b11: Repeater(Bus keeper) */ switch (type) { case PullDisable: val = 0; break; case GPIOPullUp: val = 1; break; case GPIOPullDown: val = 2; break; default: return -EINVAL; } if (bank->id == 0 && gpio < 12) { base = (void __iomem *)(RKIO_PMU_PHYS + PMU_GPIO0A_PULL + ((gpio / 8) * 4)); gpio = (gpio % 8) * 2; __raw_writel((0x3 << (16 + gpio)) | (val << gpio), base); } else { base = (void __iomem *)(RKIO_GRF_PHYS + GRF_GPIO0B_PULL - 4 + bank->id * 16 + ((gpio / 8) * 4)); gpio = (7 - (gpio % 8)) * 2; __raw_writel((0x3 << (16 + gpio)) | (val << gpio), base); } #elif defined(CONFIG_RKCHIP_RK3288) /* * pull setting * 2'b00: Z(Noraml operaton) * 2'b01: weak 1(pull-up) * 2'b10: weak 0(pull-down) * 2'b11: Repeater(Bus keeper) */ switch (type) { case PullDisable: val = 0; break; case GPIOPullUp: val = 1; break; case GPIOPullDown: val = 2; break; default: return -EINVAL; } if (bank->id == 0) { /* gpio0, pmu control */ if (gpio < (8+8+3)) { /* gpio0_a0-a8, gpio0_b0-b8, gpio0_c0-c2 */ base = (void __iomem *)(RKIO_PMU_PHYS + PMU_GPIO0A_PULL + ((gpio / 8) * 4)); gpio = (gpio % 8) * 2; __raw_writel((0x3 << (16 + gpio)) | (val << gpio), base); } } else { /* gpio1-gpio8, grf control */ base = (void __iomem *)((RKIO_GRF_PHYS + (GRF_GPIO1D_P - 0xC) + (bank->id - 1) * 16) + ((gpio / 8) * 4)); gpio = (7 - (gpio % 8)) * 2; __raw_writel((0x3 << (16 + gpio)) | (val << gpio), base); } #elif defined(CONFIG_RKCHIP_RK3368) /* * pull setting * 2'b00: Z(Noraml operaton) * 2'b01: weak 1(pull-up) * 2'b10: weak 0(pull-down) * 2'b11: Repeater(Bus keeper) */ switch (type) { case PullDisable: val = 0; break; case GPIOPullUp: val = 1; break; case GPIOPullDown: val = 2; break; default: return -EINVAL; } if (bank->id == 0) { /* gpio0, pmu grf control */ base = (void __iomem *)(unsigned long)(RKIO_PMU_GRF_PHYS + PMU_GRF_GPIO0A_P + ((gpio / 8) * 4)); gpio = (7 - (gpio % 8)) * 2; __raw_writel((0x3 << (16 + gpio)) | (val << gpio), base); } else { /* gpio1-gpio3, grf control */ base = (void __iomem *)(unsigned long)(RKIO_GRF_PHYS + GRF_GPIO1A_P + (bank->id - 1) * 16 + ((gpio / 8) * 4)); gpio = (7 - (gpio % 8)) * 2; __raw_writel((0x3 << (16 + gpio)) | (val << gpio), base); } #elif defined(CONFIG_RKCHIP_RK3168) /* rk3168 do nothing */ #elif defined(CONFIG_RKCHIP_RK3066) || defined(CONFIG_RKCHIP_RK3036) \ || defined(CONFIG_RKCHIP_RK3126) || defined(CONFIG_RKCHIP_RK3128) /* RK30XX && RK292X */ /* * Values written to this register independently * control Pullup/Pulldown or not for the * corresponding data bit in GPIO. * 0: pull up/down enable, PAD type will decide * to be up or down, not related with this value * 1: pull up/down disable */ val = (type == PullDisable) ? 1 : 0; base = (void __iomem *)(RKIO_GRF_PHYS + GRF_GPIO0L_PULL + bank->id * 8 + ((gpio / 16) * 4)); gpio = gpio % 16; __raw_writel((1 << (16 + gpio)) | (val << gpio), base); #else #error "PLS config platform for gpio driver." #endif return 0; }