struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
const struct samsung_pin_bank_type *bank_type = bank->type;
unsigned long reg_con, flags;
- unsigned int shift, mask, con;
+ unsigned int shift, mask, con, pin;
int ret;
ret = gpiochip_lock_as_irq(&bank->gpio_chip, irqd->hwirq);
con |= EXYNOS_PIN_FUNC_EINT << shift;
writel(con, bank->pctl_base + reg_con);
+ pin = bank->grange.pin_base + irqd->hwirq - bank->drvdata->pin_base;
+ bank->drvdata->pin_groups[pin].state[PINCFG_TYPE_FUNC] = EXYNOS_PIN_FUNC_EINT;
spin_unlock_irqrestore(&bank->slock, flags);
return 0;
data = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]);
data &= ~(mask << shift);
data |= func->val << shift;
+
writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]);
+ drvdata->pin_groups[grp->pins[0] - drvdata->pin_base].state[PINCFG_TYPE_FUNC] =
+ ((data >> shift) & mask);
+
spin_unlock_irqrestore(&bank->slock, flags);
}
if (set) {
cfg_value = PINCFG_UNPACK_VALUE(*config);
data &= ~(mask << shift);
+
data |= (cfg_value << shift);
writel(data, reg_base + cfg_reg);
+ drvdata->pin_groups[pin - drvdata->pin_base].state[cfg_type] =
+ ((data >> shift) & mask);
} else {
data >>= shift;
data &= mask;
struct samsung_pin_bank *bank = gpiochip_get_data(gc);
const struct samsung_pin_bank_type *type = bank->type;
void __iomem *reg;
- u32 data;
+ u32 data, pin;
reg = bank->pctl_base + bank->pctl_offset;
+ pin = bank->grange.pin_base + offset - bank->drvdata->pin_base;
data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]);
data &= ~(1 << offset);
if (value)
data |= 1 << offset;
writel(data, reg + type->reg_offset[PINCFG_TYPE_DAT]);
+
+ bank->drvdata->pin_groups[pin].state[PINCFG_TYPE_DAT] = value;
}
/* gpiolib gpio_set callback function */
const struct samsung_pin_bank_type *type;
struct samsung_pin_bank *bank;
void __iomem *reg;
- u32 data, mask, shift;
+ u32 pin, data, mask, shift;
bank = gpiochip_get_data(gc);
type = bank->type;
reg = bank->pctl_base + bank->pctl_offset
+ type->reg_offset[PINCFG_TYPE_FUNC];
+ pin = bank->grange.pin_base + offset - bank->drvdata->pin_base;
mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
shift = offset * type->fld_width[PINCFG_TYPE_FUNC];
data = readl(reg);
data &= ~(mask << shift);
- if (!input)
+
+ if (!input) {
data |= EXYNOS_PIN_FUNC_OUTPUT << shift;
+ bank->drvdata->pin_groups[pin].state[PINCFG_TYPE_FUNC] = EXYNOS_PIN_FUNC_OUTPUT;
+ } else
+ bank->drvdata->pin_groups[pin].state[PINCFG_TYPE_FUNC] = EXYNOS_PIN_FUNC_INPUT;
writel(data, reg);
return 0;
return 0;
}
+static int samsung_pinctrl_debug_set(struct samsung_pinctrl_drv_data *drvdata) {
+ struct samsung_pin_bank *bank;
+ void __iomem *reg_base;
+ u32 pin_offset;
+ unsigned long flags;
+ enum pincfg_type cfg_type;
+ const struct samsung_pin_bank_type *type;
+ u32 data, width, mask, shift, cfg_reg;
+ int i;
+
+ for (i = 0; i < drvdata->pctl_dev->desc->npins; i++) {
+
+ pin_to_reg_bank(drvdata, i, ®_base,
+ &pin_offset, &bank);
+ drvdata->pin_groups[i].state_num = 0;
+ for (cfg_type = 0; cfg_type < PINCFG_TYPE_NUM; cfg_type++) {
+
+ type = bank->type;
+ if (!type->fld_width[cfg_type])
+ continue;
+
+ spin_lock_irqsave(&bank->slock, flags);
+ width = type->fld_width[cfg_type];
+ cfg_reg = type->reg_offset[cfg_type];
+ mask = (1 << width) - 1;
+ shift = pin_offset * width;
+
+ data = readl(reg_base + cfg_reg);
+
+ data >>= shift;
+ data &= mask;
+
+ drvdata->pin_groups[i].state[cfg_type] = data;
+ drvdata->pin_groups[i].state_num++;
+ spin_unlock_irqrestore(&bank->slock, flags);
+ }
+ }
+
+ return 0;
+}
+
static const struct samsung_pin_ctrl *
samsung_pinctrl_get_soc_data_for_of_alias(struct platform_device *pdev)
{
/* Add to the global list */
list_add_tail(&drvdata->node, &drvdata_list);
+ samsung_pinctrl_debug_set(drvdata);
return 0;
}
struct pinctrl_desc pctl;
struct pinctrl_dev *pctl_dev;
- const struct samsung_pin_group *pin_groups;
+ struct samsung_pin_group *pin_groups;
unsigned int nr_groups;
const struct samsung_pmx_func *pmx_functions;
unsigned int nr_functions;
* @pins: the pins included in this group.
* @num_pins: number of pins included in this group.
* @func: the function number to be programmed when selected.
+ * @state: current pin group state.
*/
struct samsung_pin_group {
const char *name;
const unsigned int *pins;
u8 num_pins;
u8 func;
+ unsigned int state[PINCFG_TYPE_NUM];
+ unsigned int state_num;
};
/**