* this program. If not, see <http://www.gnu.org/licenses/>.
*/
- #include <linux/module.h>
+ #include <linux/init.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
BERLIN_PINCTRL_GROUP("SCRD0_CRD_PRES", 0xc, 0x3, 0x15,
BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO20 */
BERLIN_PINCTRL_FUNCTION(0x1, "scrd0"), /* crd pres */
- BERLIN_PINCTRL_FUNCTION(0x1, "sd1a")), /* DAT3 */
+ BERLIN_PINCTRL_FUNCTION(0x3, "sd1a")), /* DAT3 */
BERLIN_PINCTRL_GROUP("SPI1_SS0n", 0xc, 0x3, 0x18,
BERLIN_PINCTRL_FUNCTION(0x0, "spi1"), /* SS0n */
BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* GPIO37 */
},
{}
};
- MODULE_DEVICE_TABLE(of, berlin4ct_pinctrl_match);
static int berlin4ct_pinctrl_probe(struct platform_device *pdev)
{
.of_match_table = berlin4ct_pinctrl_match,
},
};
- module_platform_driver(berlin4ct_pinctrl_driver);
-
- MODULE_AUTHOR("Jisheng Zhang <jszhang@marvell.com>");
- MODULE_DESCRIPTION("Marvell berlin4ct pinctrl driver");
- MODULE_LICENSE("GPL");
+ builtin_platform_driver(berlin4ct_pinctrl_driver);
int reg)
{
struct byt_community *comm = byt_get_community(vg, offset);
- u32 reg_offset = 0;
+ u32 reg_offset;
if (!comm)
return NULL;
offset -= comm->pin_base;
- if (reg == BYT_INT_STAT_REG)
+ switch (reg) {
+ case BYT_INT_STAT_REG:
reg_offset = (offset / 32) * 4;
- else
+ break;
+ case BYT_DEBOUNCE_REG:
+ reg_offset = 0;
+ break;
+ default:
reg_offset = comm->pad_map[offset] * 16;
+ break;
+ }
return comm->reg_base + reg_offset + reg;
}
debounce = readl(db_reg);
debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
+ if (arg)
+ conf |= BYT_DEBOUNCE_EN;
+ else
+ conf &= ~BYT_DEBOUNCE_EN;
+
switch (arg) {
- case 0:
- conf &= BYT_DEBOUNCE_EN;
- break;
case 375:
debounce |= BYT_DEBOUNCE_PULSE_375US;
break;
debounce |= BYT_DEBOUNCE_PULSE_24MS;
break;
default:
- ret = -EINVAL;
+ if (arg)
+ ret = -EINVAL;
+ break;
}
if (!ret)
val & BYT_INPUT_EN ? " " : "in",
val & BYT_OUTPUT_EN ? " " : "out",
val & BYT_LEVEL ? "hi" : "lo",
- comm->pad_map[i], comm->pad_map[i] * 32,
+ comm->pad_map[i], comm->pad_map[i] * 16,
conf0 & 0x7,
conf0 & BYT_TRIG_NEG ? " fall" : " ",
conf0 & BYT_TRIG_POS ? " rise" : " ",
continue;
}
+ raw_spin_lock(&vg->lock);
pending = readl(reg);
+ raw_spin_unlock(&vg->lock);
for_each_set_bit(pin, &pending, 32) {
virq = irq_find_mapping(vg->chip.irqdomain, base + pin);
generic_handle_irq(virq);
vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio,
sizeof(*vg->saved_context), GFP_KERNEL);
#endif
- ret = gpiochip_add_data(gc, vg);
+ ret = devm_gpiochip_add_data(&vg->pdev->dev, gc, vg);
if (ret) {
dev_err(&vg->pdev->dev, "failed adding byt-gpio chip\n");
return ret;
0, 0, vg->soc_data->npins);
if (ret) {
dev_err(&vg->pdev->dev, "failed to add GPIO pin range\n");
- goto fail;
+ return ret;
}
/* set up interrupts */
handle_bad_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(&vg->pdev->dev, "failed to add irqchip\n");
- goto fail;
+ return ret;
}
gpiochip_set_chained_irqchip(gc, &byt_irqchip,
byt_gpio_irq_handler);
}
- return ret;
-
- fail:
- gpiochip_remove(&vg->chip);
-
return ret;
}
vg->pctl_desc.pins = vg->soc_data->pins;
vg->pctl_desc.npins = vg->soc_data->npins;
- vg->pctl_dev = pinctrl_register(&vg->pctl_desc, &pdev->dev, vg);
+ vg->pctl_dev = devm_pinctrl_register(&pdev->dev, &vg->pctl_desc, vg);
if (IS_ERR(vg->pctl_dev)) {
dev_err(&pdev->dev, "failed to register pinctrl driver\n");
return PTR_ERR(vg->pctl_dev);
raw_spin_lock_init(&vg->lock);
ret = byt_gpio_probe(vg);
- if (ret) {
- pinctrl_unregister(vg->pctl_dev);
+ if (ret)
return ret;
- }
platform_set_drvdata(pdev, vg);
pm_runtime_enable(&pdev->dev);
enum pin_config_param param;
unsigned long flags;
u32 offset, shift, mask, reg;
- u16 arg, val;
+ u32 arg, val;
int ret;
param = pinconf_to_config_param(configs[i]);
val = arg / 10 - 1;
break;
case PIN_CONFIG_BIAS_DISABLE:
- val = 0;
- break;
+ continue;
case PIN_CONFIG_BIAS_PULL_UP:
if (arg == 0)
return -EINVAL;
struct sunxi_pinctrl *pctl = platform_get_drvdata(pdev);
int i;
- pctl->ngroups = pctl->desc->npins;
+ /*
+ * Allocate groups
+ *
+ * We assume that the number of groups is the number of pins
+ * given in the data array.
- /* Allocate groups */
+ * This will not always be true, since some pins might not be
+ * available in the current variant, but fortunately for us,
+ * this means that the number of pins is the maximum group
+ * number we will ever see.
+ */
pctl->groups = devm_kzalloc(&pdev->dev,
- pctl->ngroups * sizeof(*pctl->groups),
+ pctl->desc->npins * sizeof(*pctl->groups),
GFP_KERNEL);
if (!pctl->groups)
return -ENOMEM;
for (i = 0; i < pctl->desc->npins; i++) {
const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
- struct sunxi_pinctrl_group *group = pctl->groups + i;
+ struct sunxi_pinctrl_group *group = pctl->groups + pctl->ngroups;
+
+ if (pin->variant && !(pctl->variant & pin->variant))
+ continue;
group->name = pin->pin.name;
group->pin = pin->pin.number;
+
+ /* And now we count the actual number of pins / groups */
+ pctl->ngroups++;
}
/*
* we'll reallocate that later anyway
*/
pctl->functions = devm_kzalloc(&pdev->dev,
- pctl->desc->npins * sizeof(*pctl->functions),
- GFP_KERNEL);
+ pctl->ngroups * sizeof(*pctl->functions),
+ GFP_KERNEL);
if (!pctl->functions)
return -ENOMEM;
/* Count functions and their associated groups */
for (i = 0; i < pctl->desc->npins; i++) {
const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
- struct sunxi_desc_function *func = pin->functions;
+ struct sunxi_desc_function *func;
+
+ if (pin->variant && !(pctl->variant & pin->variant))
+ continue;
+
+ for (func = pin->functions; func->name; func++) {
+ if (func->variant && !(pctl->variant & func->variant))
+ continue;
- while (func->name) {
/* Create interrupt mapping while we're at it */
if (!strcmp(func->name, "irq")) {
int irqnum = func->irqnum + func->irqbank * IRQ_PER_BANK;
}
sunxi_pinctrl_add_function(pctl, func->name);
- func++;
}
}
+ /* And now allocated and fill the array for real */
pctl->functions = krealloc(pctl->functions,
- pctl->nfunctions * sizeof(*pctl->functions),
- GFP_KERNEL);
+ pctl->nfunctions * sizeof(*pctl->functions),
+ GFP_KERNEL);
+ if (!pctl->functions) {
+ kfree(pctl->functions);
+ return -ENOMEM;
+ }
for (i = 0; i < pctl->desc->npins; i++) {
const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
- struct sunxi_desc_function *func = pin->functions;
+ struct sunxi_desc_function *func;
- while (func->name) {
+ if (pin->variant && !(pctl->variant & pin->variant))
+ continue;
+
+ for (func = pin->functions; func->name; func++) {
struct sunxi_pinctrl_function *func_item;
const char **func_grp;
+ if (func->variant && !(pctl->variant & func->variant))
+ continue;
+
func_item = sunxi_pinctrl_find_function_by_name(pctl,
func->name);
if (!func_item)
func_grp++;
*func_grp = pin->pin.name;
- func++;
}
}
return 0;
}
- int sunxi_pinctrl_init(struct platform_device *pdev,
- const struct sunxi_pinctrl_desc *desc)
+ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
+ const struct sunxi_pinctrl_desc *desc,
+ unsigned long variant)
{
struct device_node *node = pdev->dev.of_node;
struct pinctrl_desc *pctrl_desc;
struct pinctrl_pin_desc *pins;
struct sunxi_pinctrl *pctl;
struct resource *res;
- int i, ret, last_pin;
+ int i, ret, last_pin, pin_idx;
struct clk *clk;
pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
pctl->dev = &pdev->dev;
pctl->desc = desc;
+ pctl->variant = variant;
pctl->irq_array = devm_kcalloc(&pdev->dev,
IRQ_PER_BANK * pctl->desc->irq_banks,
if (!pins)
return -ENOMEM;
- for (i = 0; i < pctl->desc->npins; i++)
- pins[i] = pctl->desc->pins[i].pin;
+ for (i = 0, pin_idx = 0; i < pctl->desc->npins; i++) {
+ const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
+
+ if (pin->variant && !(pctl->variant & pin->variant))
+ continue;
+
+ pins[pin_idx++] = pin->pin;
+ }
pctrl_desc = devm_kzalloc(&pdev->dev,
sizeof(*pctrl_desc),
pctrl_desc->name = dev_name(&pdev->dev);
pctrl_desc->owner = THIS_MODULE;
pctrl_desc->pins = pins;
- pctrl_desc->npins = pctl->desc->npins;
+ pctrl_desc->npins = pctl->ngroups;
pctrl_desc->confops = &sunxi_pconf_ops;
pctrl_desc->pctlops = &sunxi_pctrl_ops;
pctrl_desc->pmxops = &sunxi_pmx_ops;