/* set pin configuration at run time caller fills pin_configuration, except sel, which will derived from func in this routine. */ int pinmux_set_pin_config(struct pin_config *config) { int ret = 0, i; void __iomem *base = g_chip_pin_desc.base; enum PIN_NAME name; if(!config) return -EINVAL; name = config->name; if(!is_ball_valid(name)) return -EINVAL; /* get the sel bits */ for (i=0; i<MAX_ALT_FUNC; i++) { if (g_chip_pin_desc.desc_tbl[name].f_tbl[i] == config->func) { config->reg.b.sel = i; break; } } if (i==MAX_ALT_FUNC) { printk (KERN_WARNING "%s no matching function for pin %u\n", __func__, config->name); return -EINVAL; } writel(config->reg.val, base + g_chip_pin_desc.desc_tbl[name].reg_offset); /* * When CONFIG_CAPRI_BSC3_PAD_CTRL_MODE is enabled, BSC3 pins are set * to GPIO_67 and GPIO_68, if there is no I2C traffic on BSC3. This * would pump lots of PINMUX change message to the console. So here * use pr_debug instead of pr_info. */ #ifndef CONFIG_CAPRI_BSC3_PAD_CTRL_MODE pr_info("[PINMUX] - write value 0x%08x to register 0x%08x\n", config->reg.val, g_chip_pin_desc.desc_tbl[name].reg_offset); #else pr_debug("[PINMUX] - write value 0x%08x to register 0x%08x\n", config->reg.val, g_chip_pin_desc.desc_tbl[name].reg_offset); #endif #ifdef CONFIG_PINMUX_VERIFY_WRITE /* Add PINMUX_VERIFY_WRITE to the boards.cfg file board of interest to enable this code */ { unsigned int rdval = readl(base + g_chip_pin_desc.desc_tbl[name].reg_offset); if (rdval != config->reg.val) { printf(KERN_ERR "%s: pin %u offset 0x%x wrote 0x%x rdval 0x%x\n", __func__, name, g_chip_pin_desc.desc_tbl[name].reg_offset, config->reg.val, rdval); return -EIO; } } #endif return ret; }
/* get pin configuration at run time caller provides pin ball name */ int pinmux_get_pin_config(struct pin_config *config) { int ret = 0; void __iomem *base = g_chip_pin_desc.base; enum PIN_NAME name; if(!config) return -EINVAL; name = config->name; if(!is_ball_valid(name)) return -EINVAL; config->reg.val = readl(base+g_chip_pin_desc.desc_tbl[name].reg_offset); /* populate func */ config->func = g_chip_pin_desc.desc_tbl[name].f_tbl[config->reg.b.sel]; return ret; }
static int bcm_modem_detect_gpio_request(enum PIN_NAME pin_cfg_name, enum PIN_FUNC pin_cfg_func) { int rc = 0; struct pin_config modem_det_pin_cfg; struct pin_config modem_det_pin_cfg_orig; unsigned int gpio_pin; enum PIN_FUNC pin_func_orig; if (is_ball_valid(pin_cfg_name)) { rc = pinmux_find_gpio(pin_cfg_name, &gpio_pin, &pin_func_orig); if (rc < 0) { pr_err("%s: Unable to find gpio pin\n", __func__); return rc; } modem_det_pin_cfg.name = pin_cfg_name; rc = pinmux_get_pin_config(&modem_det_pin_cfg); if (rc < 0) { pr_err("%s: Unable to find pin configuration\n", __func__); return rc; } /* Keep a copy of original configuration */ memcpy(&modem_det_pin_cfg_orig, &modem_det_pin_cfg, sizeof(struct pin_config)); modem_det_pin_cfg.reg.b.pull_up = 1; modem_det_pin_cfg.reg.b.pull_dn = 0; modem_det_pin_cfg.reg.b.drv_sth = DRIVE_STRENGTH_16MA; modem_det_pin_cfg.func = pin_cfg_func; rc = pinmux_set_pin_config(&modem_det_pin_cfg); if (rc < 0) { pr_err("%s: Unable to set pin configuration\n", __func__); return rc; } rc = gpio_request(gpio_pin, "modem_detect"); if (rc < 0) { pr_err("Unable to request GPIO pin %d\n", gpio_pin); goto modem_detect_pin_config_restore; } /* Set to output to charge potentially existing capacitor */ gpio_direction_output(gpio_pin, 1); mdelay(BCM_MODEM_DETECT_GPIO_CHARGE_MS); gpio_direction_input(gpio_pin); modem_present = gpio_get_value(gpio_pin); modem_detect_pin_config_restore: gpio_free(gpio_pin); pinmux_set_pin_config(&modem_det_pin_cfg_orig); } else { rc = -EINVAL; pr_err("%s: Invalid gpio pin name provided %d\n", __func__, pin_cfg_name); } return rc; }