Lines Matching +full:pin +full:- +full:val

6  * Maxime Ripard <maxime.ripard@free-electrons.com>
28 #include <linux/pinctrl/pinconf-generic.h>
34 #include <dt-bindings/pinctrl/sun4i-a10.h>
37 #include "pinctrl-sunxi.h"
52 * - Mux config
53 * - Data value
54 * - Drive level
55 * - Pull direction
60 * They take a pin number which is relative to the start of the current device.
63 u32 pin, u32 *reg, u32 *shift, u32 *mask) in sunxi_mux_reg() argument
65 u32 bank = pin / PINS_PER_BANK; in sunxi_mux_reg()
66 u32 offset = pin % PINS_PER_BANK * MUX_FIELD_WIDTH; in sunxi_mux_reg()
68 *reg = bank * pctl->bank_mem_size + MUX_REGS_OFFSET + in sunxi_mux_reg()
71 *mask = (BIT(MUX_FIELD_WIDTH) - 1) << *shift; in sunxi_mux_reg()
75 u32 pin, u32 *reg, u32 *shift, u32 *mask) in sunxi_data_reg() argument
77 u32 bank = pin / PINS_PER_BANK; in sunxi_data_reg()
78 u32 offset = pin % PINS_PER_BANK * DATA_FIELD_WIDTH; in sunxi_data_reg()
80 *reg = bank * pctl->bank_mem_size + DATA_REGS_OFFSET + in sunxi_data_reg()
83 *mask = (BIT(DATA_FIELD_WIDTH) - 1) << *shift; in sunxi_data_reg()
87 u32 pin, u32 *reg, u32 *shift, u32 *mask) in sunxi_dlevel_reg() argument
89 u32 bank = pin / PINS_PER_BANK; in sunxi_dlevel_reg()
90 u32 offset = pin % PINS_PER_BANK * pctl->dlevel_field_width; in sunxi_dlevel_reg()
92 *reg = bank * pctl->bank_mem_size + DLEVEL_REGS_OFFSET + in sunxi_dlevel_reg()
95 *mask = (BIT(pctl->dlevel_field_width) - 1) << *shift; in sunxi_dlevel_reg()
99 u32 pin, u32 *reg, u32 *shift, u32 *mask) in sunxi_pull_reg() argument
101 u32 bank = pin / PINS_PER_BANK; in sunxi_pull_reg()
102 u32 offset = pin % PINS_PER_BANK * PULL_FIELD_WIDTH; in sunxi_pull_reg()
104 *reg = bank * pctl->bank_mem_size + pctl->pull_regs_offset + in sunxi_pull_reg()
107 *mask = (BIT(PULL_FIELD_WIDTH) - 1) << *shift; in sunxi_pull_reg()
115 for (i = 0; i < pctl->ngroups; i++) { in sunxi_pinctrl_find_group_by_name()
116 struct sunxi_pinctrl_group *grp = pctl->groups + i; in sunxi_pinctrl_find_group_by_name()
118 if (!strcmp(grp->name, group)) in sunxi_pinctrl_find_group_by_name()
129 struct sunxi_pinctrl_function *func = pctl->functions; in sunxi_pinctrl_find_function_by_name()
132 for (i = 0; i < pctl->nfunctions; i++) { in sunxi_pinctrl_find_function_by_name()
150 for (i = 0; i < pctl->desc->npins; i++) { in sunxi_pinctrl_desc_find_function_by_name()
151 const struct sunxi_desc_pin *pin = pctl->desc->pins + i; in sunxi_pinctrl_desc_find_function_by_name() local
153 if (!strcmp(pin->pin.name, pin_name)) { in sunxi_pinctrl_desc_find_function_by_name()
154 struct sunxi_desc_function *func = pin->functions; in sunxi_pinctrl_desc_find_function_by_name()
156 while (func->name) { in sunxi_pinctrl_desc_find_function_by_name()
157 if (!strcmp(func->name, func_name) && in sunxi_pinctrl_desc_find_function_by_name()
158 (!func->variant || in sunxi_pinctrl_desc_find_function_by_name()
159 func->variant & pctl->variant)) in sunxi_pinctrl_desc_find_function_by_name()
177 for (i = 0; i < pctl->desc->npins; i++) { in sunxi_pinctrl_desc_find_function_by_pin()
178 const struct sunxi_desc_pin *pin = pctl->desc->pins + i; in sunxi_pinctrl_desc_find_function_by_pin() local
180 if (pin->pin.number == pin_num) { in sunxi_pinctrl_desc_find_function_by_pin()
181 struct sunxi_desc_function *func = pin->functions; in sunxi_pinctrl_desc_find_function_by_pin()
183 while (func->name) { in sunxi_pinctrl_desc_find_function_by_pin()
184 if (!strcmp(func->name, func_name)) in sunxi_pinctrl_desc_find_function_by_pin()
199 return pctl->ngroups; in sunxi_pctrl_get_groups_count()
207 return pctl->groups[group].name; in sunxi_pctrl_get_group_name()
217 *pins = (unsigned *)&pctl->groups[group].pin; in sunxi_pctrl_get_group_pins()
225 return of_find_property(node, "bias-pull-up", NULL) || in sunxi_pctrl_has_bias_prop()
226 of_find_property(node, "bias-pull-down", NULL) || in sunxi_pctrl_has_bias_prop()
227 of_find_property(node, "bias-disable", NULL) || in sunxi_pctrl_has_bias_prop()
233 return of_find_property(node, "drive-strength", NULL) || in sunxi_pctrl_has_drive_prop()
239 u32 val; in sunxi_pctrl_parse_bias_prop() local
242 if (of_find_property(node, "bias-pull-up", NULL)) in sunxi_pctrl_parse_bias_prop()
245 if (of_find_property(node, "bias-pull-down", NULL)) in sunxi_pctrl_parse_bias_prop()
248 if (of_find_property(node, "bias-disable", NULL)) in sunxi_pctrl_parse_bias_prop()
252 if (of_property_read_u32(node, "allwinner,pull", &val)) in sunxi_pctrl_parse_bias_prop()
253 return -EINVAL; in sunxi_pctrl_parse_bias_prop()
255 switch (val) { in sunxi_pctrl_parse_bias_prop()
264 return -EINVAL; in sunxi_pctrl_parse_bias_prop()
269 u32 val; in sunxi_pctrl_parse_drive_prop() local
272 if (!of_property_read_u32(node, "drive-strength", &val)) { in sunxi_pctrl_parse_drive_prop()
274 if (val < 10) in sunxi_pctrl_parse_drive_prop()
275 return -EINVAL; in sunxi_pctrl_parse_drive_prop()
278 if (val > 40) in sunxi_pctrl_parse_drive_prop()
279 val = 40; in sunxi_pctrl_parse_drive_prop()
282 return rounddown(val, 10); in sunxi_pctrl_parse_drive_prop()
286 if (of_property_read_u32(node, "allwinner,drive", &val)) in sunxi_pctrl_parse_drive_prop()
287 return -EINVAL; in sunxi_pctrl_parse_drive_prop()
289 return (val + 1) * 10; in sunxi_pctrl_parse_drive_prop()
352 return ERR_PTR(-ENOMEM); in sunxi_pctrl_build_pin_config()
405 dev_err(pctl->dev, "missing function property in node %pOFn\n", in sunxi_pctrl_dt_node_to_map()
407 return -EINVAL; in sunxi_pctrl_dt_node_to_map()
412 dev_err(pctl->dev, "missing pins property in node %pOFn\n", in sunxi_pctrl_dt_node_to_map()
414 return -EINVAL; in sunxi_pctrl_dt_node_to_map()
418 * We have two maps for each pin: one for the function, one in sunxi_pctrl_dt_node_to_map()
427 return -ENOMEM; in sunxi_pctrl_dt_node_to_map()
440 dev_err(pctl->dev, "unknown pin %s", group); in sunxi_pctrl_dt_node_to_map()
445 grp->name, in sunxi_pctrl_dt_node_to_map()
447 dev_err(pctl->dev, "unsupported function %s on pin %s", in sunxi_pctrl_dt_node_to_map()
475 return -ENOMEM; in sunxi_pctrl_dt_node_to_map()
491 /* pin config is never in the first map */ in sunxi_pctrl_dt_free_map()
497 * All the maps share the same pin config, in sunxi_pctrl_dt_free_map()
516 u32 pin, enum pin_config_param param, in sunxi_pconf_reg() argument
521 sunxi_dlevel_reg(pctl, pin, reg, shift, mask); in sunxi_pconf_reg()
527 sunxi_pull_reg(pctl, pin, reg, shift, mask); in sunxi_pconf_reg()
531 return -ENOTSUPP; in sunxi_pconf_reg()
537 static int sunxi_pconf_get(struct pinctrl_dev *pctldev, unsigned pin, in sunxi_pconf_get() argument
542 u32 reg, shift, mask, val; in sunxi_pconf_get() local
546 pin -= pctl->desc->pin_base; in sunxi_pconf_get()
548 ret = sunxi_pconf_reg(pctl, pin, param, &reg, &shift, &mask); in sunxi_pconf_get()
552 val = (readl(pctl->membase + reg) & mask) >> shift; in sunxi_pconf_get()
556 arg = (val + 1) * 10; in sunxi_pconf_get()
560 if (val != SUN4I_PINCTRL_PULL_UP) in sunxi_pconf_get()
561 return -EINVAL; in sunxi_pconf_get()
562 arg = 1; /* hardware is weak pull-up */ in sunxi_pconf_get()
566 if (val != SUN4I_PINCTRL_PULL_DOWN) in sunxi_pconf_get()
567 return -EINVAL; in sunxi_pconf_get()
568 arg = 1; /* hardware is weak pull-down */ in sunxi_pconf_get()
572 if (val != SUN4I_PINCTRL_NO_PULL) in sunxi_pconf_get()
573 return -EINVAL; in sunxi_pconf_get()
580 return -ENOTSUPP; in sunxi_pconf_get()
593 struct sunxi_pinctrl_group *g = &pctl->groups[group]; in sunxi_pconf_group_get()
595 /* We only support 1 pin per group. Chain it to the pin callback */ in sunxi_pconf_group_get()
596 return sunxi_pconf_get(pctldev, g->pin, config); in sunxi_pconf_group_get()
599 static int sunxi_pconf_set(struct pinctrl_dev *pctldev, unsigned pin, in sunxi_pconf_set() argument
605 pin -= pctl->desc->pin_base; in sunxi_pconf_set()
608 u32 arg, reg, shift, mask, val; in sunxi_pconf_set() local
616 ret = sunxi_pconf_reg(pctl, pin, param, &reg, &shift, &mask); in sunxi_pconf_set()
623 return -EINVAL; in sunxi_pconf_set()
631 val = arg / 10 - 1; in sunxi_pconf_set()
634 val = 0; in sunxi_pconf_set()
638 return -EINVAL; in sunxi_pconf_set()
639 val = 1; in sunxi_pconf_set()
643 return -EINVAL; in sunxi_pconf_set()
644 val = 2; in sunxi_pconf_set()
649 return -ENOTSUPP; in sunxi_pconf_set()
652 raw_spin_lock_irqsave(&pctl->lock, flags); in sunxi_pconf_set()
653 writel((readl(pctl->membase + reg) & ~mask) | val << shift, in sunxi_pconf_set()
654 pctl->membase + reg); in sunxi_pconf_set()
655 raw_spin_unlock_irqrestore(&pctl->lock, flags); in sunxi_pconf_set()
665 struct sunxi_pinctrl_group *g = &pctl->groups[group]; in sunxi_pconf_group_set()
667 /* We only support 1 pin per group. Chain it to the pin callback */ in sunxi_pconf_group_set()
668 return sunxi_pconf_set(pctldev, g->pin, configs, num_configs); in sunxi_pconf_group_set()
680 unsigned pin, in sunxi_pinctrl_set_io_bias_cfg() argument
685 u32 val, reg; in sunxi_pinctrl_set_io_bias_cfg() local
688 if (!pctl->desc->io_bias_cfg_variant) in sunxi_pinctrl_set_io_bias_cfg()
699 pin -= pctl->desc->pin_base; in sunxi_pinctrl_set_io_bias_cfg()
700 bank = pin / PINS_PER_BANK; in sunxi_pinctrl_set_io_bias_cfg()
702 switch (pctl->desc->io_bias_cfg_variant) { in sunxi_pinctrl_set_io_bias_cfg()
709 val = 0x0; /* 1.8V */ in sunxi_pinctrl_set_io_bias_cfg()
711 val = 0x6; /* 2.5V */ in sunxi_pinctrl_set_io_bias_cfg()
713 val = 0x9; /* 2.8V */ in sunxi_pinctrl_set_io_bias_cfg()
715 val = 0xA; /* 3.0V */ in sunxi_pinctrl_set_io_bias_cfg()
717 val = 0xD; /* 3.3V */ in sunxi_pinctrl_set_io_bias_cfg()
719 reg = readl(pctl->membase + sunxi_grp_config_reg(pin)); in sunxi_pinctrl_set_io_bias_cfg()
721 writel(reg | val, pctl->membase + sunxi_grp_config_reg(pin)); in sunxi_pinctrl_set_io_bias_cfg()
724 val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0; in sunxi_pinctrl_set_io_bias_cfg()
726 raw_spin_lock_irqsave(&pctl->lock, flags); in sunxi_pinctrl_set_io_bias_cfg()
727 reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG); in sunxi_pinctrl_set_io_bias_cfg()
729 writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG); in sunxi_pinctrl_set_io_bias_cfg()
730 raw_spin_unlock_irqrestore(&pctl->lock, flags); in sunxi_pinctrl_set_io_bias_cfg()
734 val = uV <= 1800000 ? 1 : 0; in sunxi_pinctrl_set_io_bias_cfg()
736 raw_spin_lock_irqsave(&pctl->lock, flags); in sunxi_pinctrl_set_io_bias_cfg()
737 reg = readl(pctl->membase + PIO_POW_MOD_SEL_REG); in sunxi_pinctrl_set_io_bias_cfg()
739 writel(reg | val << bank, pctl->membase + PIO_POW_MOD_SEL_REG); in sunxi_pinctrl_set_io_bias_cfg()
740 raw_spin_unlock_irqrestore(&pctl->lock, flags); in sunxi_pinctrl_set_io_bias_cfg()
743 return -EINVAL; in sunxi_pinctrl_set_io_bias_cfg()
751 return pctl->nfunctions; in sunxi_pmx_get_funcs_cnt()
759 return pctl->functions[function].name; in sunxi_pmx_get_func_name()
769 *groups = pctl->functions[function].groups; in sunxi_pmx_get_func_groups()
770 *num_groups = pctl->functions[function].ngroups; in sunxi_pmx_get_func_groups()
776 unsigned pin, in sunxi_pmx_set() argument
783 pin -= pctl->desc->pin_base; in sunxi_pmx_set()
784 sunxi_mux_reg(pctl, pin, &reg, &shift, &mask); in sunxi_pmx_set()
786 raw_spin_lock_irqsave(&pctl->lock, flags); in sunxi_pmx_set()
788 writel((readl(pctl->membase + reg) & ~mask) | config << shift, in sunxi_pmx_set()
789 pctl->membase + reg); in sunxi_pmx_set()
791 raw_spin_unlock_irqrestore(&pctl->lock, flags); in sunxi_pmx_set()
799 struct sunxi_pinctrl_group *g = pctl->groups + group; in sunxi_pmx_set_mux()
800 struct sunxi_pinctrl_function *func = pctl->functions + function; in sunxi_pmx_set_mux()
803 g->name, in sunxi_pmx_set_mux()
804 func->name); in sunxi_pmx_set_mux()
807 return -EINVAL; in sunxi_pmx_set_mux()
809 sunxi_pmx_set(pctldev, g->pin, desc->muxval); in sunxi_pmx_set_mux()
831 return -EINVAL; in sunxi_pmx_gpio_set_direction()
833 sunxi_pmx_set(pctldev, offset, desc->muxval); in sunxi_pmx_gpio_set_direction()
842 unsigned short bank_offset = bank - pctl->desc->pin_base / in sunxi_pmx_request()
844 struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank_offset]; in sunxi_pmx_request()
845 struct regulator *reg = s_reg->regulator; in sunxi_pmx_request()
850 refcount_inc(&s_reg->refcount); in sunxi_pmx_request()
854 snprintf(supply, sizeof(supply), "vcc-p%c", 'a' + bank); in sunxi_pmx_request()
855 reg = regulator_get(pctl->dev, supply); in sunxi_pmx_request()
857 return dev_err_probe(pctl->dev, PTR_ERR(reg), in sunxi_pmx_request()
863 dev_err(pctl->dev, in sunxi_pmx_request()
870 s_reg->regulator = reg; in sunxi_pmx_request()
871 refcount_set(&s_reg->refcount, 1); in sunxi_pmx_request()
876 regulator_put(s_reg->regulator); in sunxi_pmx_request()
885 unsigned short bank_offset = bank - pctl->desc->pin_base / in sunxi_pmx_free()
887 struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank_offset]; in sunxi_pmx_free()
889 if (!refcount_dec_and_test(&s_reg->refcount)) in sunxi_pmx_free()
892 regulator_disable(s_reg->regulator); in sunxi_pmx_free()
893 regulator_put(s_reg->regulator); in sunxi_pmx_free()
894 s_reg->regulator = NULL; in sunxi_pmx_free()
915 return sunxi_pmx_gpio_set_direction(pctl->pctl_dev, NULL, in sunxi_pinctrl_gpio_direction_input()
916 chip->base + offset, true); in sunxi_pinctrl_gpio_direction_input()
922 bool set_mux = pctl->desc->irq_read_needs_mux && in sunxi_pinctrl_gpio_get()
924 u32 pin = offset + chip->base; in sunxi_pinctrl_gpio_get() local
925 u32 reg, shift, mask, val; in sunxi_pinctrl_gpio_get() local
930 sunxi_pmx_set(pctl->pctl_dev, pin, SUN4I_FUNC_INPUT); in sunxi_pinctrl_gpio_get()
932 val = (readl(pctl->membase + reg) & mask) >> shift; in sunxi_pinctrl_gpio_get()
935 sunxi_pmx_set(pctl->pctl_dev, pin, SUN4I_FUNC_IRQ); in sunxi_pinctrl_gpio_get()
937 return val; in sunxi_pinctrl_gpio_get()
944 u32 reg, shift, mask, val; in sunxi_pinctrl_gpio_set() local
949 raw_spin_lock_irqsave(&pctl->lock, flags); in sunxi_pinctrl_gpio_set()
951 val = readl(pctl->membase + reg); in sunxi_pinctrl_gpio_set()
954 val |= mask; in sunxi_pinctrl_gpio_set()
956 val &= ~mask; in sunxi_pinctrl_gpio_set()
958 writel(val, pctl->membase + reg); in sunxi_pinctrl_gpio_set()
960 raw_spin_unlock_irqrestore(&pctl->lock, flags); in sunxi_pinctrl_gpio_set()
969 return sunxi_pmx_gpio_set_direction(pctl->pctl_dev, NULL, in sunxi_pinctrl_gpio_direction_output()
970 chip->base + offset, false); in sunxi_pinctrl_gpio_direction_output()
977 int pin, base; in sunxi_pinctrl_gpio_of_xlate() local
979 base = PINS_PER_BANK * gpiospec->args[0]; in sunxi_pinctrl_gpio_of_xlate()
980 pin = base + gpiospec->args[1]; in sunxi_pinctrl_gpio_of_xlate()
982 if (pin > gc->ngpio) in sunxi_pinctrl_gpio_of_xlate()
983 return -EINVAL; in sunxi_pinctrl_gpio_of_xlate()
986 *flags = gpiospec->args[2]; in sunxi_pinctrl_gpio_of_xlate()
988 return pin; in sunxi_pinctrl_gpio_of_xlate()
995 unsigned pinnum = pctl->desc->pin_base + offset; in sunxi_pinctrl_gpio_to_irq()
998 if (offset >= chip->ngpio) in sunxi_pinctrl_gpio_to_irq()
999 return -ENXIO; in sunxi_pinctrl_gpio_to_irq()
1003 return -EINVAL; in sunxi_pinctrl_gpio_to_irq()
1005 irqnum = desc->irqbank * IRQ_PER_BANK + desc->irqnum; in sunxi_pinctrl_gpio_to_irq()
1007 dev_dbg(chip->parent, "%s: request IRQ for GPIO %d, return %d\n", in sunxi_pinctrl_gpio_to_irq()
1008 chip->label, offset + chip->base, irqnum); in sunxi_pinctrl_gpio_to_irq()
1010 return irq_find_mapping(pctl->domain, irqnum); in sunxi_pinctrl_gpio_to_irq()
1020 pctl->irq_array[d->hwirq], "irq"); in sunxi_pinctrl_irq_request_resources()
1022 return -EINVAL; in sunxi_pinctrl_irq_request_resources()
1024 ret = gpiochip_lock_as_irq(pctl->chip, in sunxi_pinctrl_irq_request_resources()
1025 pctl->irq_array[d->hwirq] - pctl->desc->pin_base); in sunxi_pinctrl_irq_request_resources()
1027 dev_err(pctl->dev, "unable to lock HW IRQ %lu for IRQ\n", in sunxi_pinctrl_irq_request_resources()
1033 sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq], func->muxval); in sunxi_pinctrl_irq_request_resources()
1042 gpiochip_unlock_as_irq(pctl->chip, in sunxi_pinctrl_irq_release_resources()
1043 pctl->irq_array[d->hwirq] - pctl->desc->pin_base); in sunxi_pinctrl_irq_release_resources()
1049 u32 reg = sunxi_irq_cfg_reg(pctl->desc, d->hwirq); in sunxi_pinctrl_irq_set_type()
1050 u8 index = sunxi_irq_cfg_offset(d->hwirq); in sunxi_pinctrl_irq_set_type()
1072 return -EINVAL; in sunxi_pinctrl_irq_set_type()
1075 raw_spin_lock_irqsave(&pctl->lock, flags); in sunxi_pinctrl_irq_set_type()
1084 regval = readl(pctl->membase + reg); in sunxi_pinctrl_irq_set_type()
1086 writel(regval | (mode << index), pctl->membase + reg); in sunxi_pinctrl_irq_set_type()
1088 raw_spin_unlock_irqrestore(&pctl->lock, flags); in sunxi_pinctrl_irq_set_type()
1096 u32 status_reg = sunxi_irq_status_reg(pctl->desc, d->hwirq); in sunxi_pinctrl_irq_ack()
1097 u8 status_idx = sunxi_irq_status_offset(d->hwirq); in sunxi_pinctrl_irq_ack()
1100 writel(1 << status_idx, pctl->membase + status_reg); in sunxi_pinctrl_irq_ack()
1106 u32 reg = sunxi_irq_ctrl_reg(pctl->desc, d->hwirq); in sunxi_pinctrl_irq_mask()
1107 u8 idx = sunxi_irq_ctrl_offset(d->hwirq); in sunxi_pinctrl_irq_mask()
1109 u32 val; in sunxi_pinctrl_irq_mask() local
1111 raw_spin_lock_irqsave(&pctl->lock, flags); in sunxi_pinctrl_irq_mask()
1114 val = readl(pctl->membase + reg); in sunxi_pinctrl_irq_mask()
1115 writel(val & ~(1 << idx), pctl->membase + reg); in sunxi_pinctrl_irq_mask()
1117 raw_spin_unlock_irqrestore(&pctl->lock, flags); in sunxi_pinctrl_irq_mask()
1123 u32 reg = sunxi_irq_ctrl_reg(pctl->desc, d->hwirq); in sunxi_pinctrl_irq_unmask()
1124 u8 idx = sunxi_irq_ctrl_offset(d->hwirq); in sunxi_pinctrl_irq_unmask()
1126 u32 val; in sunxi_pinctrl_irq_unmask() local
1128 raw_spin_lock_irqsave(&pctl->lock, flags); in sunxi_pinctrl_irq_unmask()
1131 val = readl(pctl->membase + reg); in sunxi_pinctrl_irq_unmask()
1132 writel(val | (1 << idx), pctl->membase + reg); in sunxi_pinctrl_irq_unmask()
1134 raw_spin_unlock_irqrestore(&pctl->lock, flags); in sunxi_pinctrl_irq_unmask()
1146 u8 bank = d->hwirq / IRQ_PER_BANK; in sunxi_pinctrl_irq_set_wake()
1148 return irq_set_irq_wake(pctl->irq[bank], on); in sunxi_pinctrl_irq_set_wake()
1188 struct sunxi_pinctrl *pctl = d->host_data; in sunxi_pinctrl_irq_of_xlate()
1190 int pin, base; in sunxi_pinctrl_irq_of_xlate() local
1193 return -EINVAL; in sunxi_pinctrl_irq_of_xlate()
1196 pin = pctl->desc->pin_base + base + intspec[1]; in sunxi_pinctrl_irq_of_xlate()
1198 desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, pin, "irq"); in sunxi_pinctrl_irq_of_xlate()
1200 return -EINVAL; in sunxi_pinctrl_irq_of_xlate()
1202 *out_hwirq = desc->irqbank * PINS_PER_BANK + desc->irqnum; in sunxi_pinctrl_irq_of_xlate()
1217 unsigned long bank, reg, val; in sunxi_pinctrl_irq_handler() local
1219 for (bank = 0; bank < pctl->desc->irq_banks; bank++) in sunxi_pinctrl_irq_handler()
1220 if (irq == pctl->irq[bank]) in sunxi_pinctrl_irq_handler()
1223 WARN_ON(bank == pctl->desc->irq_banks); in sunxi_pinctrl_irq_handler()
1227 reg = sunxi_irq_status_reg_from_bank(pctl->desc, bank); in sunxi_pinctrl_irq_handler()
1228 val = readl(pctl->membase + reg); in sunxi_pinctrl_irq_handler()
1230 if (val) { in sunxi_pinctrl_irq_handler()
1233 for_each_set_bit(irqoffset, &val, IRQ_PER_BANK) in sunxi_pinctrl_irq_handler()
1234 generic_handle_domain_irq(pctl->domain, in sunxi_pinctrl_irq_handler()
1244 struct sunxi_pinctrl_function *func = pctl->functions; in sunxi_pinctrl_add_function()
1246 while (func->name) { in sunxi_pinctrl_add_function()
1248 if (strcmp(func->name, name) == 0) { in sunxi_pinctrl_add_function()
1249 func->ngroups++; in sunxi_pinctrl_add_function()
1250 return -EEXIST; in sunxi_pinctrl_add_function()
1255 func->name = name; in sunxi_pinctrl_add_function()
1256 func->ngroups = 1; in sunxi_pinctrl_add_function()
1258 pctl->nfunctions++; in sunxi_pinctrl_add_function()
1280 pctl->groups = devm_kcalloc(&pdev->dev, in sunxi_pinctrl_build_state()
1281 pctl->desc->npins, sizeof(*pctl->groups), in sunxi_pinctrl_build_state()
1283 if (!pctl->groups) in sunxi_pinctrl_build_state()
1284 return -ENOMEM; in sunxi_pinctrl_build_state()
1286 for (i = 0; i < pctl->desc->npins; i++) { in sunxi_pinctrl_build_state()
1287 const struct sunxi_desc_pin *pin = pctl->desc->pins + i; in sunxi_pinctrl_build_state() local
1288 struct sunxi_pinctrl_group *group = pctl->groups + pctl->ngroups; in sunxi_pinctrl_build_state()
1290 if (pin->variant && !(pctl->variant & pin->variant)) in sunxi_pinctrl_build_state()
1293 group->name = pin->pin.name; in sunxi_pinctrl_build_state()
1294 group->pin = pin->pin.number; in sunxi_pinctrl_build_state()
1297 pctl->ngroups++; in sunxi_pinctrl_build_state()
1303 * special functions per pin, plus one entry for the sentinel. in sunxi_pinctrl_build_state()
1306 pctl->functions = kcalloc(7 * pctl->ngroups + 4, in sunxi_pinctrl_build_state()
1307 sizeof(*pctl->functions), in sunxi_pinctrl_build_state()
1309 if (!pctl->functions) in sunxi_pinctrl_build_state()
1310 return -ENOMEM; in sunxi_pinctrl_build_state()
1313 for (i = 0; i < pctl->desc->npins; i++) { in sunxi_pinctrl_build_state()
1314 const struct sunxi_desc_pin *pin = pctl->desc->pins + i; in sunxi_pinctrl_build_state() local
1317 if (pin->variant && !(pctl->variant & pin->variant)) in sunxi_pinctrl_build_state()
1320 for (func = pin->functions; func->name; func++) { in sunxi_pinctrl_build_state()
1321 if (func->variant && !(pctl->variant & func->variant)) in sunxi_pinctrl_build_state()
1325 if (!strcmp(func->name, "irq")) { in sunxi_pinctrl_build_state()
1326 int irqnum = func->irqnum + func->irqbank * IRQ_PER_BANK; in sunxi_pinctrl_build_state()
1327 pctl->irq_array[irqnum] = pin->pin.number; in sunxi_pinctrl_build_state()
1330 sunxi_pinctrl_add_function(pctl, func->name); in sunxi_pinctrl_build_state()
1335 ptr = krealloc(pctl->functions, in sunxi_pinctrl_build_state()
1336 pctl->nfunctions * sizeof(*pctl->functions), in sunxi_pinctrl_build_state()
1339 kfree(pctl->functions); in sunxi_pinctrl_build_state()
1340 pctl->functions = NULL; in sunxi_pinctrl_build_state()
1341 return -ENOMEM; in sunxi_pinctrl_build_state()
1343 pctl->functions = ptr; in sunxi_pinctrl_build_state()
1345 for (i = 0; i < pctl->desc->npins; i++) { in sunxi_pinctrl_build_state()
1346 const struct sunxi_desc_pin *pin = pctl->desc->pins + i; in sunxi_pinctrl_build_state() local
1349 if (pin->variant && !(pctl->variant & pin->variant)) in sunxi_pinctrl_build_state()
1352 for (func = pin->functions; func->name; func++) { in sunxi_pinctrl_build_state()
1356 if (func->variant && !(pctl->variant & func->variant)) in sunxi_pinctrl_build_state()
1360 func->name); in sunxi_pinctrl_build_state()
1362 kfree(pctl->functions); in sunxi_pinctrl_build_state()
1363 return -EINVAL; in sunxi_pinctrl_build_state()
1366 if (!func_item->groups) { in sunxi_pinctrl_build_state()
1367 func_item->groups = in sunxi_pinctrl_build_state()
1368 devm_kcalloc(&pdev->dev, in sunxi_pinctrl_build_state()
1369 func_item->ngroups, in sunxi_pinctrl_build_state()
1370 sizeof(*func_item->groups), in sunxi_pinctrl_build_state()
1372 if (!func_item->groups) { in sunxi_pinctrl_build_state()
1373 kfree(pctl->functions); in sunxi_pinctrl_build_state()
1374 return -ENOMEM; in sunxi_pinctrl_build_state()
1378 func_grp = func_item->groups; in sunxi_pinctrl_build_state()
1382 *func_grp = pin->pin.name; in sunxi_pinctrl_build_state()
1395 best_diff = abs(freq - clock); in sunxi_pinctrl_get_debounce_div()
1399 int cur_diff = abs(freq - (clock >> i)); in sunxi_pinctrl_get_debounce_div()
1425 if (!of_find_property(node, "input-debounce", NULL)) in sunxi_pinctrl_setup_debounce()
1428 losc = devm_clk_get(pctl->dev, "losc"); in sunxi_pinctrl_setup_debounce()
1432 hosc = devm_clk_get(pctl->dev, "hosc"); in sunxi_pinctrl_setup_debounce()
1436 for (i = 0; i < pctl->desc->irq_banks; i++) { in sunxi_pinctrl_setup_debounce()
1440 ret = of_property_read_u32_index(node, "input-debounce", in sunxi_pinctrl_setup_debounce()
1466 pctl->membase + in sunxi_pinctrl_setup_debounce()
1467 sunxi_irq_debounce_reg_from_bank(pctl->desc, i)); in sunxi_pinctrl_setup_debounce()
1477 struct device_node *node = pdev->dev.of_node; in sunxi_pinctrl_init_with_variant()
1485 pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL); in sunxi_pinctrl_init_with_variant()
1487 return -ENOMEM; in sunxi_pinctrl_init_with_variant()
1490 raw_spin_lock_init(&pctl->lock); in sunxi_pinctrl_init_with_variant()
1492 pctl->membase = devm_platform_ioremap_resource(pdev, 0); in sunxi_pinctrl_init_with_variant()
1493 if (IS_ERR(pctl->membase)) in sunxi_pinctrl_init_with_variant()
1494 return PTR_ERR(pctl->membase); in sunxi_pinctrl_init_with_variant()
1496 pctl->dev = &pdev->dev; in sunxi_pinctrl_init_with_variant()
1497 pctl->desc = desc; in sunxi_pinctrl_init_with_variant()
1498 pctl->variant = variant; in sunxi_pinctrl_init_with_variant()
1499 if (pctl->variant >= PINCTRL_SUN20I_D1) { in sunxi_pinctrl_init_with_variant()
1500 pctl->bank_mem_size = D1_BANK_MEM_SIZE; in sunxi_pinctrl_init_with_variant()
1501 pctl->pull_regs_offset = D1_PULL_REGS_OFFSET; in sunxi_pinctrl_init_with_variant()
1502 pctl->dlevel_field_width = D1_DLEVEL_FIELD_WIDTH; in sunxi_pinctrl_init_with_variant()
1504 pctl->bank_mem_size = BANK_MEM_SIZE; in sunxi_pinctrl_init_with_variant()
1505 pctl->pull_regs_offset = PULL_REGS_OFFSET; in sunxi_pinctrl_init_with_variant()
1506 pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH; in sunxi_pinctrl_init_with_variant()
1509 pctl->irq_array = devm_kcalloc(&pdev->dev, in sunxi_pinctrl_init_with_variant()
1510 IRQ_PER_BANK * pctl->desc->irq_banks, in sunxi_pinctrl_init_with_variant()
1511 sizeof(*pctl->irq_array), in sunxi_pinctrl_init_with_variant()
1513 if (!pctl->irq_array) in sunxi_pinctrl_init_with_variant()
1514 return -ENOMEM; in sunxi_pinctrl_init_with_variant()
1518 dev_err(&pdev->dev, "dt probe failed: %d\n", ret); in sunxi_pinctrl_init_with_variant()
1522 pins = devm_kcalloc(&pdev->dev, in sunxi_pinctrl_init_with_variant()
1523 pctl->desc->npins, sizeof(*pins), in sunxi_pinctrl_init_with_variant()
1526 return -ENOMEM; in sunxi_pinctrl_init_with_variant()
1528 for (i = 0, pin_idx = 0; i < pctl->desc->npins; i++) { in sunxi_pinctrl_init_with_variant()
1529 const struct sunxi_desc_pin *pin = pctl->desc->pins + i; in sunxi_pinctrl_init_with_variant() local
1531 if (pin->variant && !(pctl->variant & pin->variant)) in sunxi_pinctrl_init_with_variant()
1534 pins[pin_idx++] = pin->pin; in sunxi_pinctrl_init_with_variant()
1537 pctrl_desc = devm_kzalloc(&pdev->dev, in sunxi_pinctrl_init_with_variant()
1541 return -ENOMEM; in sunxi_pinctrl_init_with_variant()
1543 pctrl_desc->name = dev_name(&pdev->dev); in sunxi_pinctrl_init_with_variant()
1544 pctrl_desc->owner = THIS_MODULE; in sunxi_pinctrl_init_with_variant()
1545 pctrl_desc->pins = pins; in sunxi_pinctrl_init_with_variant()
1546 pctrl_desc->npins = pctl->ngroups; in sunxi_pinctrl_init_with_variant()
1547 pctrl_desc->confops = &sunxi_pconf_ops; in sunxi_pinctrl_init_with_variant()
1548 pctrl_desc->pctlops = &sunxi_pctrl_ops; in sunxi_pinctrl_init_with_variant()
1550 pmxops = devm_kmemdup(&pdev->dev, &sunxi_pmx_ops, sizeof(sunxi_pmx_ops), in sunxi_pinctrl_init_with_variant()
1553 return -ENOMEM; in sunxi_pinctrl_init_with_variant()
1555 if (desc->disable_strict_mode) in sunxi_pinctrl_init_with_variant()
1556 pmxops->strict = false; in sunxi_pinctrl_init_with_variant()
1558 pctrl_desc->pmxops = pmxops; in sunxi_pinctrl_init_with_variant()
1560 pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, pctrl_desc, pctl); in sunxi_pinctrl_init_with_variant()
1561 if (IS_ERR(pctl->pctl_dev)) { in sunxi_pinctrl_init_with_variant()
1562 dev_err(&pdev->dev, "couldn't register pinctrl driver\n"); in sunxi_pinctrl_init_with_variant()
1563 return PTR_ERR(pctl->pctl_dev); in sunxi_pinctrl_init_with_variant()
1566 pctl->chip = devm_kzalloc(&pdev->dev, sizeof(*pctl->chip), GFP_KERNEL); in sunxi_pinctrl_init_with_variant()
1567 if (!pctl->chip) in sunxi_pinctrl_init_with_variant()
1568 return -ENOMEM; in sunxi_pinctrl_init_with_variant()
1570 last_pin = pctl->desc->pins[pctl->desc->npins - 1].pin.number; in sunxi_pinctrl_init_with_variant()
1571 pctl->chip->owner = THIS_MODULE; in sunxi_pinctrl_init_with_variant()
1572 pctl->chip->request = gpiochip_generic_request; in sunxi_pinctrl_init_with_variant()
1573 pctl->chip->free = gpiochip_generic_free; in sunxi_pinctrl_init_with_variant()
1574 pctl->chip->set_config = gpiochip_generic_config; in sunxi_pinctrl_init_with_variant()
1575 pctl->chip->direction_input = sunxi_pinctrl_gpio_direction_input; in sunxi_pinctrl_init_with_variant()
1576 pctl->chip->direction_output = sunxi_pinctrl_gpio_direction_output; in sunxi_pinctrl_init_with_variant()
1577 pctl->chip->get = sunxi_pinctrl_gpio_get; in sunxi_pinctrl_init_with_variant()
1578 pctl->chip->set = sunxi_pinctrl_gpio_set; in sunxi_pinctrl_init_with_variant()
1579 pctl->chip->of_xlate = sunxi_pinctrl_gpio_of_xlate; in sunxi_pinctrl_init_with_variant()
1580 pctl->chip->to_irq = sunxi_pinctrl_gpio_to_irq; in sunxi_pinctrl_init_with_variant()
1581 pctl->chip->of_gpio_n_cells = 3; in sunxi_pinctrl_init_with_variant()
1582 pctl->chip->can_sleep = false; in sunxi_pinctrl_init_with_variant()
1583 pctl->chip->ngpio = round_up(last_pin, PINS_PER_BANK) - in sunxi_pinctrl_init_with_variant()
1584 pctl->desc->pin_base; in sunxi_pinctrl_init_with_variant()
1585 pctl->chip->label = dev_name(&pdev->dev); in sunxi_pinctrl_init_with_variant()
1586 pctl->chip->parent = &pdev->dev; in sunxi_pinctrl_init_with_variant()
1587 pctl->chip->base = pctl->desc->pin_base; in sunxi_pinctrl_init_with_variant()
1589 ret = gpiochip_add_data(pctl->chip, pctl); in sunxi_pinctrl_init_with_variant()
1593 for (i = 0; i < pctl->desc->npins; i++) { in sunxi_pinctrl_init_with_variant()
1594 const struct sunxi_desc_pin *pin = pctl->desc->pins + i; in sunxi_pinctrl_init_with_variant() local
1596 ret = gpiochip_add_pin_range(pctl->chip, dev_name(&pdev->dev), in sunxi_pinctrl_init_with_variant()
1597 pin->pin.number - pctl->desc->pin_base, in sunxi_pinctrl_init_with_variant()
1598 pin->pin.number, 1); in sunxi_pinctrl_init_with_variant()
1604 clk = devm_clk_get(&pdev->dev, ret == 1 ? NULL : "apb"); in sunxi_pinctrl_init_with_variant()
1614 pctl->irq = devm_kcalloc(&pdev->dev, in sunxi_pinctrl_init_with_variant()
1615 pctl->desc->irq_banks, in sunxi_pinctrl_init_with_variant()
1616 sizeof(*pctl->irq), in sunxi_pinctrl_init_with_variant()
1618 if (!pctl->irq) { in sunxi_pinctrl_init_with_variant()
1619 ret = -ENOMEM; in sunxi_pinctrl_init_with_variant()
1623 for (i = 0; i < pctl->desc->irq_banks; i++) { in sunxi_pinctrl_init_with_variant()
1624 pctl->irq[i] = platform_get_irq(pdev, i); in sunxi_pinctrl_init_with_variant()
1625 if (pctl->irq[i] < 0) { in sunxi_pinctrl_init_with_variant()
1626 ret = pctl->irq[i]; in sunxi_pinctrl_init_with_variant()
1631 pctl->domain = irq_domain_add_linear(node, in sunxi_pinctrl_init_with_variant()
1632 pctl->desc->irq_banks * IRQ_PER_BANK, in sunxi_pinctrl_init_with_variant()
1635 if (!pctl->domain) { in sunxi_pinctrl_init_with_variant()
1636 dev_err(&pdev->dev, "Couldn't register IRQ domain\n"); in sunxi_pinctrl_init_with_variant()
1637 ret = -ENOMEM; in sunxi_pinctrl_init_with_variant()
1641 for (i = 0; i < (pctl->desc->irq_banks * IRQ_PER_BANK); i++) { in sunxi_pinctrl_init_with_variant()
1642 int irqno = irq_create_mapping(pctl->domain, i); in sunxi_pinctrl_init_with_variant()
1651 for (i = 0; i < pctl->desc->irq_banks; i++) { in sunxi_pinctrl_init_with_variant()
1653 writel(0, pctl->membase + in sunxi_pinctrl_init_with_variant()
1654 sunxi_irq_ctrl_reg_from_bank(pctl->desc, i)); in sunxi_pinctrl_init_with_variant()
1656 pctl->membase + in sunxi_pinctrl_init_with_variant()
1657 sunxi_irq_status_reg_from_bank(pctl->desc, i)); in sunxi_pinctrl_init_with_variant()
1659 irq_set_chained_handler_and_data(pctl->irq[i], in sunxi_pinctrl_init_with_variant()
1666 dev_info(&pdev->dev, "initialized sunXi PIO driver\n"); in sunxi_pinctrl_init_with_variant()
1673 gpiochip_remove(pctl->chip); in sunxi_pinctrl_init_with_variant()