#define pr_fmt(fmt) "avm-hw-config/core: " fmt #include #include #include #include #include #include "debugfs.h" int avm_get_hw_config(unsigned int version, const char *name, int *p_value, enum _avm_hw_param *p_param) { unsigned i; if (version != AVM_HW_CONFIG_VERSION) return -EFAULT; if (!avm_current_hw_config) { avm_current_hw_config = avm_get_hw_config_table(); if (!avm_current_hw_config) { pr_alert("%s: avm_current_hw_config is not set\n", __func__); return -ENOENT; } } for (i = 0; avm_current_hw_config[i].name; i++) { pr_debug("checking avm_hw_config[%d].name='%s' vs. '%s'\n", i, avm_current_hw_config[i].name, name); if (strcmp(avm_current_hw_config[i].name, name) == 0) { pr_debug("avm_hw_config[%d].name='%s': { .value=%d, .param='%d'}\n", i, avm_current_hw_config[i].name, avm_current_hw_config[i].value, avm_current_hw_config[i].param); if (p_value) *p_value = avm_current_hw_config[i].value; if (p_param) *p_param = avm_current_hw_config[i].param; return 0; } } return -ENOENT; } EXPORT_SYMBOL(avm_get_hw_config); int avm_gpio_find_by_name(const char *name, unsigned long *flags) { const struct _avm_hw_config *config; config = avm_get_hw_config_table(); if (!config) return -ENOENT; while (1) { if (!config->name) return -ENOENT; if (!strcmp(config->name, name)) break; ++config; } if (flags) { switch (config->param) { case avm_hw_param_gpio_in_active_high: *flags = GPIOF_DIR_IN; break; case avm_hw_param_gpio_in_active_low: *flags = GPIOF_DIR_IN | GPIOF_ACTIVE_LOW; break; case avm_hw_param_gpio_out_active_low: *flags = GPIOF_ACTIVE_LOW; break; case avm_hw_param_gpio_out_active_high: default: *flags = 0; break; } if (config->preset == AVM_HWCFG_GPIO_RAW_HI) *flags |= GPIOF_INIT_HIGH; } return config->value; } EXPORT_SYMBOL(avm_gpio_find_by_name); int avm_initialize_hw_gpio(void) { unsigned i; unsigned ii; if (!avm_current_hw_config) { avm_current_hw_config = avm_get_hw_config_table(); if (!avm_current_hw_config) { pr_alert("%s: avm_current_hw_config is not set\n", __func__); return -ENOENT; } } for (i = 0; avm_current_hw_config[i].name; i++) { struct _avm_hw_config *phw_gpio = &avm_current_hw_config[i]; pr_err("%s: %s gpio_nr=%u param=%u, force_logical=%u\n", __func__, phw_gpio->name, phw_gpio->value, phw_gpio->param, phw_gpio->gpio_force_logical); /* Disable Invert gpio * The GPIO can be used in function or GPIO mode. * In GPIO mode the invert field has to be set to 0. * Currently some GPIOs are configured via bios in function mode * with enabled invert mode. */ avm_gpio_pinctrl(phw_gpio->value, INVERT_RXTX_PINCTRL, 0x0); /* set special pin-ctrls */ for(ii = 0; ii < ARRAY_SIZE(phw_gpio->pinctrl); ii++) { unsigned int ctrl = phw_gpio->pinctrl[ii]; if (!VALID_PINCTRL(ctrl)) continue; avm_gpio_pinctrl(phw_gpio->value, GET_PINCTRL(ctrl), GET_PINCTRLVAL(ctrl)); } switch (phw_gpio->param) { case avm_hw_param_no_param: case avm_hw_param_gpio_out_rgb: case avm_hw_param_gpio_out_rgb_active_low: case avm_hw_param_last_param: break; case avm_hw_param_gpio_out_active_low: avm_gpio_ctrl(phw_gpio->value, GPIO_PIN, GPIO_OUTPUT_PIN); if (phw_gpio->preset) avm_gpio_out_bit(phw_gpio->value, phw_gpio->preset == AVM_HWCFG_GPIO_RAW_HI); break; case avm_hw_param_gpio_out_active_high: avm_gpio_ctrl(phw_gpio->value, GPIO_PIN, GPIO_OUTPUT_PIN); if (phw_gpio->preset) avm_gpio_out_bit(phw_gpio->value, phw_gpio->preset == AVM_HWCFG_GPIO_RAW_HI); break; case avm_hw_param_gpio_in_active_low: avm_gpio_ctrl(phw_gpio->value, GPIO_PIN, GPIO_INPUT_PIN); break; case avm_hw_param_gpio_in_active_high: avm_gpio_ctrl(phw_gpio->value, GPIO_PIN, GPIO_INPUT_PIN); break; case avm_hw_param_in_pinmux1: avm_gpio_ctrl(phw_gpio->value, FUNCTIONAL_PIN, GPIO_INPUT_PIN); break; case avm_hw_param_in_pinmux2: avm_gpio_ctrl(phw_gpio->value, FUNCTIONAL2_PIN, GPIO_INPUT_PIN); break; case avm_hw_param_in_pinmux3: avm_gpio_ctrl(phw_gpio->value, FUNCTIONAL3_PIN, GPIO_INPUT_PIN); break; case avm_hw_param_out_pinmux1: avm_gpio_ctrl(phw_gpio->value, FUNCTIONAL_PIN, GPIO_OUTPUT_PIN); break; case avm_hw_param_out_pinmux2: avm_gpio_ctrl(phw_gpio->value, FUNCTIONAL2_PIN, GPIO_OUTPUT_PIN); break; case avm_hw_param_out_pinmux3: avm_gpio_ctrl(phw_gpio->value, FUNCTIONAL3_PIN, GPIO_OUTPUT_PIN); break; } } if (init_debugfs()) pr_err("Couldn't create debugfs entry!\n"); return 0; } subsys_initcall(avm_initialize_hw_gpio); static struct _avm_hw_config *avm_gpio_scan_table(unsigned int gpio_number) { struct _avm_hw_config *cfg_table; int i; cfg_table = avm_get_hw_config_table(); for (i = 0; cfg_table[i].name; i++) { if (cfg_table[i].value == gpio_number) return &cfg_table[i]; } return NULL; } unsigned int avm_gpio_interpret_value(unsigned int gpio_nr, int value) { struct _avm_hw_config *gpio_cfg; gpio_cfg = avm_gpio_scan_table(gpio_nr); if (gpio_cfg != NULL && gpio_cfg->gpio_force_logical && (gpio_cfg->param == AVM_DEF_HW_PARAM_GPIO_IN_ACTIVE_LOW || gpio_cfg->param == AVM_DEF_HW_PARAM_GPIO_OUT_ACTIVE_LOW)) value = !value; return value; }