static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, int pinmux_type, int cfg_mode) { struct pinmux_cfg_reg *cr = NULL; pinmux_enum_t enum_id; struct pinmux_range *range; int in_range, pos, index; unsigned long *cntp; switch (pinmux_type) { case PINMUX_TYPE_FUNCTION: range = NULL; break; case PINMUX_TYPE_OUTPUT: range = &gpioc->output; break; case PINMUX_TYPE_INPUT: range = &gpioc->input; break; case PINMUX_TYPE_INPUT_PULLUP: range = &gpioc->input_pu; break; case PINMUX_TYPE_INPUT_PULLDOWN: range = &gpioc->input_pd; break; default: goto out_err; } pos = 0; enum_id = 0; index = 0; while (1) { pos = get_gpio_enum_id(gpioc, gpio, pos, &enum_id); if (pos <= 0) goto out_err; if (!enum_id) break; in_range = enum_in_range(enum_id, &gpioc->function); if (!in_range && range) { in_range = enum_in_range(enum_id, range); if (in_range && enum_id == range->force) continue; } if (!in_range) continue; if (get_config_reg(gpioc, enum_id, &cr, &index, &cntp) != 0) goto out_err; switch (cfg_mode) { case GPIO_CFG_DRYRUN: if (!*cntp || !check_config_reg(gpioc, cr, index)) continue; break; case GPIO_CFG_REQ: write_config_reg(gpioc, cr, index); *cntp = *cntp + 1; break; case GPIO_CFG_FREE: *cntp = *cntp - 1; break; } } return 0; out_err: return -1; }
static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, int pinmux_type, int cfg_mode) { struct pinmux_cfg_reg *cr = NULL; pinmux_enum_t enum_id; struct pinmux_range *range; int in_range, pos, field, value; unsigned long *cntp; switch (pinmux_type) { case PINMUX_TYPE_FUNCTION: range = NULL; break; case PINMUX_TYPE_OUTPUT: range = &gpioc->output; break; case PINMUX_TYPE_INPUT: range = &gpioc->input; break; case PINMUX_TYPE_INPUT_PULLUP: range = &gpioc->input_pu; break; case PINMUX_TYPE_INPUT_PULLDOWN: range = &gpioc->input_pd; break; default: goto out_err; } pos = 0; enum_id = 0; field = 0; value = 0; while (1) { pos = get_gpio_enum_id(gpioc, gpio, pos, &enum_id); if (pos <= 0) goto out_err; if (!enum_id) break; /* first check if this is a function enum */ in_range = enum_in_range(enum_id, &gpioc->function); if (!in_range) { /* not a function enum */ if (range) { /* * other range exists, so this pin is * a regular GPIO pin that now is being * bound to a specific direction. * * for this case we only allow function enums * and the enums that match the other range. */ in_range = enum_in_range(enum_id, range); /* * special case pass through for fixed * input-only or output-only pins without * function enum register association. */ if (in_range && enum_id == range->force) continue; } else { /* * no other range exists, so this pin * must then be of the function type. * * allow function type pins to select * any combination of function/in/out * in their MARK lists. */ in_range = 1; } } if (!in_range) continue; if (get_config_reg(gpioc, enum_id, &cr, &field, &value, &cntp) != 0) goto out_err; switch (cfg_mode) { case GPIO_CFG_DRYRUN: if (!*cntp || (read_config_reg(gpioc, cr, field) != value)) continue; break; case GPIO_CFG_REQ: write_config_reg(gpioc, cr, field, value); *cntp = *cntp + 1; break; case GPIO_CFG_FREE: *cntp = *cntp - 1; break; } } return 0; out_err: return -1; }