static u8 dht22_sun5i_read_bit() { if (dht22_sun5i_gpio_direction != PIN_DIR_IN) { dht22_sun5i_gpio_direction = PIN_DIR_IN; PIN_DIR(PIN_DIR_IN); } PIN_DIR(0); return PIN_GET(); }
/* Init driver */ static int __init dht22_sun5i_init_driver() { int err = 0; int dht22_used = 0; script_gpio_set_t info; dht22_sun5i_proc = proc_mkdir("dht22", NULL); create_proc_read_entry("raw_data", 0444, dht22_sun5i_proc, dht22_sun5i_proc_read, NULL); err = script_parser_fetch("dht22_para", "dht22_used", &dht22_used, sizeof (dht22_used) / sizeof (int)); if (!dht22_used || err) { printk(KERN_INFO "%s: dht22-bus is not used in config\n", __FUNCTION__); return -EINVAL; } err = script_parser_fetch("dht22_para", "dht22_pin", (int *) &info, sizeof (script_gpio_set_t)); if (err) { printk(KERN_INFO "%s: can not get \"dht22_para\" \"dht22_pin\" gpio handler, already used by others?", __FUNCTION__); return -EBUSY; } dht22_sun5i_gpio_handler = gpio_request_ex("dht22_para", "dht22_pin"); dht22_sun5i_gpio_direction = PIN_DIR_OUT; PIN_DIR(PIN_DIR_OUT); return 0; }
static void dht22_sun5i_write_bit(u8 bit) { if (dht22_sun5i_gpio_direction != PIN_DIR_OUT) { dht22_sun5i_gpio_direction = PIN_DIR_OUT; PIN_DIR(PIN_DIR_OUT); } PIN_SET(bit); }
void pin_function(PinName pin, int function) { uint32_t port = 0; uint8_t bit = 0; uint8_t i = 0; uint8_t func = 0; uint8_t dir = 0; // Assert that pin is valid MBED_ASSERT(pin != NC); // Calculate pin function and pin direction func = PIN_FUNC(function); dir = PIN_DIR(function); // Calculate port and pin position port = PIN_PORT(pin); bit = PIN_POS(pin); // Set function if function is in range if (func <= PIN_FUNC_MAX) { // Disable other functions for (i = 0; i < PIN_FUNC_MAX; i++) { if (i != (func - 1)) { GPIO_DisableFuncReg((GPIO_Port)port, i, (1 << bit)); } } // Set pin function if (func) { GPIO_EnableFuncReg((GPIO_Port)port, (uint8_t)(func - 1), (1 << bit)); } } // Set direction if direction is in range switch (dir) { case PIN_INPUT: GPIO_SetInputEnableReg((GPIO_Port)port, (1 << bit), ENABLE); GPIO_SetOutputEnableReg((GPIO_Port)port, (1 << bit), DISABLE); break; case PIN_OUTPUT: GPIO_SetOutputEnableReg((GPIO_Port)port, (1 << bit), ENABLE); GPIO_SetInputEnableReg((GPIO_Port)port, (1 << bit), DISABLE); break; case PIN_INOUT: GPIO_SetOutputEnableReg((GPIO_Port)port, (1 << bit), ENABLE); GPIO_SetInputEnableReg((GPIO_Port)port, (1 << bit), ENABLE); break; default: break; } }
/** * config_pin - configure a pin's mux attributes * @cfg: pin confguration * * Configures a pin's mode (alternate function or GPIO), its pull up status, * and its sleep mode based on the specified configuration. The @cfg is * usually one of the SoC specific macros defined in mach/<soc>-pins.h. These * are constructed using, and can be further enhanced with, the macros in * plat/pincfg.h. * * If a pin's mode is set to GPIO, it is configured as an input to avoid * side-effects. The gpio can be manipulated later using standard GPIO API * calls. */ static void config_pin(pin_cfg_t cfg) { int pin = PIN_NUM(cfg); int pull = PIN_PULL(cfg); int af = PIN_ALT(cfg); int output = PIN_DIR(cfg); int val = PIN_VAL(cfg); if (output) db8500_gpio_make_output(pin, val); else { db8500_gpio_make_input(pin); db8500_gpio_set_pull(pin, pull); } gpio_set_mode(pin, af); }
static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, pin_cfg_t cfg, bool sleep, unsigned int *slpmregs) { static const char *afnames[] = { [NMK_GPIO_ALT_GPIO] = "GPIO", [NMK_GPIO_ALT_A] = "A", [NMK_GPIO_ALT_B] = "B", [NMK_GPIO_ALT_C] = "C" }; static const char *pullnames[] = { [NMK_GPIO_PULL_NONE] = "none", [NMK_GPIO_PULL_UP] = "up", [NMK_GPIO_PULL_DOWN] = "down", [3] /* illegal */ = "??" }; static const char *slpmnames[] = { [NMK_GPIO_SLPM_INPUT] = "input/wakeup", [NMK_GPIO_SLPM_NOCHANGE] = "no-change/no-wakeup", }; int pin = PIN_NUM(cfg); int pull = PIN_PULL(cfg); int af = PIN_ALT(cfg); int slpm = PIN_SLPM(cfg); int output = PIN_DIR(cfg); int val = PIN_VAL(cfg); bool glitch = af == NMK_GPIO_ALT_C; dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: af %s, pull %s, slpm %s (%s%s)\n", pin, cfg, afnames[af], pullnames[pull], slpmnames[slpm], output ? "output " : "input", output ? (val ? "high" : "low") : ""); if (sleep) { int slpm_pull = PIN_SLPM_PULL(cfg); int slpm_output = PIN_SLPM_DIR(cfg); int slpm_val = PIN_SLPM_VAL(cfg); af = NMK_GPIO_ALT_GPIO; /* * The SLPM_* values are normal values + 1 to allow zero to * mean "same as normal". */ if (slpm_pull) pull = slpm_pull - 1; if (slpm_output) output = slpm_output - 1; if (slpm_val) val = slpm_val - 1; dev_dbg(nmk_chip->chip.dev, "pin %d: sleep pull %s, dir %s, val %s\n", pin, slpm_pull ? pullnames[pull] : "same", slpm_output ? (output ? "output" : "input") : "same", slpm_val ? (val ? "high" : "low") : "same"); } if (output) __nmk_gpio_make_output(nmk_chip, offset, val); else { __nmk_gpio_make_input(nmk_chip, offset); __nmk_gpio_set_pull(nmk_chip, offset, pull); } __nmk_gpio_set_lowemi(nmk_chip, offset, PIN_LOWEMI(cfg)); /* * If the pin is switching to altfunc, and there was an interrupt * installed on it which has been lazy disabled, actually mask the * interrupt to prevent spurious interrupts that would occur while the * pin is under control of the peripheral. Only SKE does this. */ if (af != NMK_GPIO_ALT_GPIO) nmk_gpio_disable_lazy_irq(nmk_chip, offset); /* * If we've backed up the SLPM registers (glitch workaround), modify * the backups since they will be restored. */ if (slpmregs) { if (slpm == NMK_GPIO_SLPM_NOCHANGE) slpmregs[nmk_chip->bank] |= BIT(offset); else slpmregs[nmk_chip->bank] &= ~BIT(offset); } else __nmk_gpio_set_slpm(nmk_chip, offset, slpm); __nmk_gpio_set_mode_safe(nmk_chip, offset, af, glitch); }
int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin, unsigned long config) { static const char *pullnames[] = { [NMK_GPIO_PULL_NONE] = "none", [NMK_GPIO_PULL_UP] = "up", [NMK_GPIO_PULL_DOWN] = "down", [3] /* illegal */ = "??" }; static const char *slpmnames[] = { [NMK_GPIO_SLPM_INPUT] = "input/wakeup", [NMK_GPIO_SLPM_NOCHANGE] = "no-change/no-wakeup", }; struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); struct nmk_gpio_chip *nmk_chip; struct pinctrl_gpio_range *range; struct gpio_chip *chip; unsigned bit; /* * The pin config contains pin number and altfunction fields, here * we just ignore that part. It's being handled by the framework and * pinmux callback respectively. */ pin_cfg_t cfg = (pin_cfg_t) config; int pull = PIN_PULL(cfg); int slpm = PIN_SLPM(cfg); int output = PIN_DIR(cfg); int val = PIN_VAL(cfg); bool lowemi = PIN_LOWEMI(cfg); bool gpiomode = PIN_GPIOMODE(cfg); bool sleep = PIN_SLEEPMODE(cfg); range = nmk_match_gpio_range(pctldev, pin); if (!range) { dev_err(npct->dev, "invalid pin offset %d\n", pin); return -EINVAL; } if (!range->gc) { dev_err(npct->dev, "GPIO chip missing in range for pin %d\n", pin); return -EINVAL; } chip = range->gc; nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); if (sleep) { int slpm_pull = PIN_SLPM_PULL(cfg); int slpm_output = PIN_SLPM_DIR(cfg); int slpm_val = PIN_SLPM_VAL(cfg); /* All pins go into GPIO mode at sleep */ gpiomode = true; /* * The SLPM_* values are normal values + 1 to allow zero to * mean "same as normal". */ if (slpm_pull) pull = slpm_pull - 1; if (slpm_output) output = slpm_output - 1; if (slpm_val) val = slpm_val - 1; dev_dbg(nmk_chip->chip.dev, "pin %d: sleep pull %s, dir %s, val %s\n", pin, slpm_pull ? pullnames[pull] : "same", slpm_output ? (output ? "output" : "input") : "same", slpm_val ? (val ? "high" : "low") : "same"); } dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: pull %s, slpm %s (%s%s), lowemi %s\n", pin, cfg, pullnames[pull], slpmnames[slpm], output ? "output " : "input", output ? (val ? "high" : "low") : "", lowemi ? "on" : "off" ); clk_enable(nmk_chip->clk); bit = pin % NMK_GPIO_PER_CHIP; if (gpiomode) /* No glitch when going to GPIO mode */ __nmk_gpio_set_mode(nmk_chip, bit, NMK_GPIO_ALT_GPIO); if (output) __nmk_gpio_make_output(nmk_chip, bit, val); else { __nmk_gpio_make_input(nmk_chip, bit); __nmk_gpio_set_pull(nmk_chip, bit, pull); } /* TODO: isn't this only applicable on output pins? */ __nmk_gpio_set_lowemi(nmk_chip, bit, lowemi); __nmk_gpio_set_slpm(nmk_chip, bit, slpm); clk_disable(nmk_chip->clk); return 0; }
static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, pin_cfg_t cfg, bool sleep, unsigned int *slpmregs) { static const char *afnames[] = { [NMK_GPIO_ALT_GPIO] = "GPIO", [NMK_GPIO_ALT_A] = "A", [NMK_GPIO_ALT_B] = "B", [NMK_GPIO_ALT_C] = "C" }; static const char *pullnames[] = { [NMK_GPIO_PULL_NONE] = "none", [NMK_GPIO_PULL_UP] = "up", [NMK_GPIO_PULL_DOWN] = "down", [3] /* illegal */ = "??" }; static const char *slpmnames[] = { [NMK_GPIO_SLPM_INPUT] = "input/wakeup", [NMK_GPIO_SLPM_NOCHANGE] = "no-change/no-wakeup", }; int pin = PIN_NUM(cfg); int pull = PIN_PULL(cfg); int af = PIN_ALT(cfg); int slpm = PIN_SLPM(cfg); int output = PIN_DIR(cfg); int val = PIN_VAL(cfg); bool glitch = af == NMK_GPIO_ALT_C; dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: af %s, pull %s, slpm %s (%s%s)\n", pin, cfg, afnames[af], pullnames[pull], slpmnames[slpm], output ? "output " : "input", output ? (val ? "high" : "low") : ""); if (sleep) { int slpm_pull = PIN_SLPM_PULL(cfg); int slpm_output = PIN_SLPM_DIR(cfg); int slpm_val = PIN_SLPM_VAL(cfg); af = NMK_GPIO_ALT_GPIO; /* * The SLPM_* values are normal values + 1 to allow zero to * mean "same as normal". */ if (slpm_pull) pull = slpm_pull - 1; if (slpm_output) output = slpm_output - 1; if (slpm_val) val = slpm_val - 1; dev_dbg(nmk_chip->chip.dev, "pin %d: sleep pull %s, dir %s, val %s\n", pin, slpm_pull ? pullnames[pull] : "same", slpm_output ? (output ? "output" : "input") : "same", slpm_val ? (val ? "high" : "low") : "same"); } if (output) __nmk_gpio_make_output(nmk_chip, offset, val); else { __nmk_gpio_make_input(nmk_chip, offset); __nmk_gpio_set_pull(nmk_chip, offset, pull); } /* * If we've backed up the SLPM registers (glitch workaround), modify * the backups since they will be restored. */ if (slpmregs) { if (slpm == NMK_GPIO_SLPM_NOCHANGE) slpmregs[nmk_chip->bank] |= BIT(offset); else slpmregs[nmk_chip->bank] &= ~BIT(offset); } else __nmk_gpio_set_slpm(nmk_chip, offset, slpm); __nmk_gpio_set_mode_safe(nmk_chip, offset, af, glitch); }