blob: d3b3c595d9589e10fece63b3ce43448d36c33f45 [file] [log] [blame] [edit]
/*
* Copyright (C) 2016 IBM Corp.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/bitops.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/string.h>
#include <linux/types.h>
#include "core.h"
#include "pinctrl-utils.h"
#include "pinctrl-aspeed.h"
#define AST2500_NR_PINS 228
#define SCU80 0x80
#define SCU90 0x90
#define SCU94 0x94
#define COND1 FUNC_DESC_BIT(SCU90, 6, 0)
#define COND2 { SCU94, GENMASK(1, 0), 0, 0 }
FUNC_EXPR_DECL_SINGLE(I2C9, FUNC_DESC_SET(SCU90, 22), COND1);
#define C14 4
FUNC_EXPR_DECL_SINGLE(TIMER5, FUNC_DESC_SET(SCU80, 4), COND1);
MS_PIN_DECL(C14, GPIOA4, I2C9, TIMER5);
FUNC_GROUP_DECL(TIMER5, C14);
#define A13 5
FUNC_EXPR_DECL_SINGLE(TIMER6, FUNC_DESC_SET(SCU80, 5), COND1);
MS_PIN_DECL(A13, GPIOA4, I2C9, TIMER6);
FUNC_GROUP_DECL(TIMER6, A13);
FUNC_GROUP_DECL(I2C9, C14, A13);
FUNC_EXPR_DECL_SINGLE(I2C4, FUNC_DESC_SET(SCU90, 17));
#define A9 130
SS_PIN_DECL(A9, GPIOQ2, I2C4);
#define B9 131
SS_PIN_DECL(B9, GPIOQ3, I2C4);
FUNC_GROUP_DECL(I2C4, A9, B9);
/* I2C3 */
FUNC_EXPR_DECL_SINGLE(I2C3, FUNC_DESC_SET(SCU90, 16), COND1);
#define A11 128
SS_PIN_DECL(A11, GPIOQ0, I2C3);
#define A10 129
SS_PIN_DECL(A10, GPIOQ1, I2C3);
FUNC_GROUP_DECL(I2C3, A11, A10);
static struct pinctrl_pin_desc ast2500_pins[AST2500_NR_PINS] = {
ASPEED_PINCTRL_PIN(C14),
ASPEED_PINCTRL_PIN(A13),
ASPEED_PINCTRL_PIN(A11),
ASPEED_PINCTRL_PIN(A10),
ASPEED_PINCTRL_PIN(A9),
ASPEED_PINCTRL_PIN(B9),
};
static const struct aspeed_pin_group ast2500_groups[] = {
ASPEED_PINCTRL_GROUP(I2C9),
ASPEED_PINCTRL_GROUP(I2C4),
ASPEED_PINCTRL_GROUP(I2C3),
};
static const struct aspeed_pin_function ast2500_functions[] = {
ASPEED_PINCTRL_FUNC(I2C9),
ASPEED_PINCTRL_FUNC(I2C4),
ASPEED_PINCTRL_FUNC(I2C3),
};
static struct aspeed_pinctrl_data ast2500_pinctrl = {
.pins = ast2500_pins,
.npins = ARRAY_SIZE(ast2500_pins),
.groups = ast2500_groups,
.ngroups = ARRAY_SIZE(ast2500_groups),
.functions = ast2500_functions,
.nfunctions = ARRAY_SIZE(ast2500_functions),
};
static struct pinmux_ops ast2500_pinmux_ops = {
.get_functions_count = aspeed_pinmux_get_fn_count,
.get_function_name = aspeed_pinmux_get_fn_name,
.get_function_groups = aspeed_pinmux_get_fn_groups,
.set_mux = aspeed_pinmux_set_mux,
.gpio_request_enable = aspeed_gpio_request_enable,
.strict = true,
};
static struct pinctrl_ops ast2500_pinctrl_ops = {
.get_groups_count = aspeed_pinctrl_get_groups_count,
.get_group_name = aspeed_pinctrl_get_group_name,
.get_group_pins = aspeed_pinctrl_get_group_pins,
.pin_dbg_show = aspeed_pinctrl_pin_dbg_show,
.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
.dt_free_map = pinctrl_utils_dt_free_map,
};
static struct pinconf_ops ast2500_pinconf_ops = {
.pin_config_get = aspeed_pin_config_get,
.pin_config_set = aspeed_pin_config_set,
};
static struct pinctrl_desc ast2500_pinctrl_desc = {
.name = "pinctrl-ast2500",
.pins = ast2500_pins,
.npins = ARRAY_SIZE(ast2500_pins),
.pctlops = &ast2500_pinctrl_ops,
.pmxops = &ast2500_pinmux_ops,
.confops = &ast2500_pinconf_ops,
.owner = THIS_MODULE,
};
static struct pinctrl_gpio_range ast2500_gpios = {
.name = "ast2500-pctrl-gpio-range",
/* HACK: this is even auto-assigned by the GPIO subsystem, so there are
* no guarantees. BUT. It seems to pick 320 consistently.
*/
.base = 320,
.npins = ARRAY_SIZE(ast2500_pins),
};
static int __init ast2500_pinctrl_probe(struct platform_device *pdev)
{
struct aspeed_pinctrl_data *pdata = &ast2500_pinctrl;
struct resource *res;
struct pinctrl_dev *pctl;
int i;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pdata->reg_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(pdata->reg_base))
return PTR_ERR(pdata->reg_base);
/* We allocated space for all pins, make sure we initialise all pin
* numbers. Those pins we haven't defined won't yet have had their
* number initialised, and it's effectively a no-op for those which
* have.
*/
for (i = 0; i < ARRAY_SIZE(ast2500_pins); i++)
ast2500_pins[i].number = i;
pctl = pinctrl_register(&ast2500_pinctrl_desc, &pdev->dev, pdata);
if (IS_ERR(pctl)) {
dev_err(&pdev->dev, "Failed to register pinctrl\n");
return PTR_ERR(pctl);
}
platform_set_drvdata(pdev, pdata);
/* grange.name = "exynos5440-pctrl-gpio-range"; */
pinctrl_add_gpio_range(pctl, &ast2500_gpios);
return 0;
}
static const struct of_device_id ast2500_pinctrl_of_match[] = {
{ .compatible = "aspeed,ast2500-pinctrl", },
{ },
};
static struct platform_driver ast2500_pinctrl_driver = {
.driver = {
.name = "pinctrl-ast2500",
.of_match_table = ast2500_pinctrl_of_match,
},
};
module_platform_driver_probe(ast2500_pinctrl_driver, ast2500_pinctrl_probe);
MODULE_AUTHOR("Andrew Jeffery <andrew@aj.id.au>");
MODULE_DESCRIPTION("ASPEED AST2500 pinctrl driver");
MODULE_LICENSE("GPL v2");