static void sh_pfc_write_config_reg(struct sh_pfc *pfc, const struct pinmux_cfg_reg *crp, unsigned int field, u32 value) { void __iomem *mapped_reg; unsigned int pos; u32 mask, data; sh_pfc_config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos); dev_dbg(pfc->dev, "write_reg addr = %x, value = 0x%x, field = %u, " "r_width = %u, f_width = %u\n", crp->reg, value, field, crp->reg_width, crp->field_width); mask = ~(mask << pos); value = value << pos; data = sh_pfc_read_raw_reg(mapped_reg, crp->reg_width); data &= mask; data |= value; if (pfc->info->unlock_reg) sh_pfc_write_raw_reg( sh_pfc_phys_to_virt(pfc, pfc->info->unlock_reg), 32, ~data); sh_pfc_write_raw_reg(mapped_reg, crp->reg_width, data); }
void sh_pfc_write(struct sh_pfc *pfc, u32 reg, u32 data) { void __iomem *unlock_reg = (void __iomem *)(uintptr_t)pfc->info->unlock_reg; if (pfc->info->unlock_reg) sh_pfc_write_raw_reg(unlock_reg, 32, ~data); sh_pfc_write_raw_reg((void __iomem *)(uintptr_t)reg, 32, data); }
static void gpio_write_data_reg(struct sh_pfc_chip *chip, const struct pinmux_data_reg *dreg, u32 value) { phys_addr_t address = dreg->reg; void __iomem *mem = address - chip->mem->phys + chip->mem->virt; sh_pfc_write_raw_reg(mem, dreg->reg_width, value); }
static int sh_pfc_pinconf_set_drive_strength(struct sh_pfc *pfc, unsigned int pin, u16 strength) { unsigned int offset; unsigned int size; unsigned int step; void __iomem *reg; void __iomem *unlock_reg = (void __iomem *)(uintptr_t)pfc->info->unlock_reg; u32 val; reg = sh_pfc_pinconf_find_drive_strength_reg(pfc, pin, &offset, &size); if (!reg) return -EINVAL; step = size == 2 ? 6 : 3; if (strength < step || strength > 24) return -EINVAL; /* Convert the value from mA based on a full drive strength value of * 24mA. We can make the full value configurable later if needed. */ strength = strength / step - 1; val = sh_pfc_read_raw_reg(reg, 32); val &= ~GENMASK(offset + size - 1, offset); val |= strength << offset; if (unlock_reg) sh_pfc_write_raw_reg(unlock_reg, 32, ~val); sh_pfc_write_raw_reg(reg, 32, val); return 0; }
static int sh_pfc_pinconf_set(struct sh_pfc_pinctrl *pmx, unsigned _pin, unsigned int param, unsigned int arg) { struct sh_pfc *pfc = pmx->pfc; void __iomem *pocctrl; void __iomem *unlock_reg = (void __iomem *)(uintptr_t)pfc->info->unlock_reg; u32 addr, val; int bit, ret; if (!sh_pfc_pinconf_validate(pfc, _pin, param)) return -ENOTSUPP; switch (param) { case PIN_CONFIG_BIAS_PULL_UP: case PIN_CONFIG_BIAS_PULL_DOWN: case PIN_CONFIG_BIAS_DISABLE: if (!pfc->info->ops || !pfc->info->ops->set_bias) return -ENOTSUPP; pfc->info->ops->set_bias(pfc, _pin, param); break; case PIN_CONFIG_DRIVE_STRENGTH: ret = sh_pfc_pinconf_set_drive_strength(pfc, _pin, arg); if (ret < 0) return ret; break; case PIN_CONFIG_POWER_SOURCE: if (!pfc->info->ops || !pfc->info->ops->pin_to_pocctrl) return -ENOTSUPP; bit = pfc->info->ops->pin_to_pocctrl(pfc, _pin, &addr); if (bit < 0) { printf("invalid pin %#x", _pin); return bit; } if (arg != 1800 && arg != 3300) return -EINVAL; pocctrl = (void __iomem *)(uintptr_t)addr; val = sh_pfc_read_raw_reg(pocctrl, 32); if (arg == 3300) val |= BIT(bit); else val &= ~BIT(bit); if (unlock_reg) sh_pfc_write_raw_reg(unlock_reg, 32, ~val); sh_pfc_write_raw_reg(pocctrl, 32, val); break; default: return -ENOTSUPP; } return 0; }