driver: pinctrl: Add Mango(SG2042) SOC pinctrl driver

This commit is contained in:
xiaoguang.xing 2023-02-16 09:59:30 +08:00 committed by Xiaoguang Xing
parent 008f09c7d0
commit 88e92ab0fb
6 changed files with 814 additions and 1 deletions

View File

@ -22,7 +22,7 @@ config PINCONF
bool "Support pin configuration controllers" if COMPILE_TEST
config GENERIC_PINCONF
bool
bool "GENERIC_PINCONF"
select PINCONF
config DEBUG_PINCTRL

View File

@ -74,6 +74,7 @@ obj-$(CONFIG_SOC_STARFIVE) += starfive/
obj-$(CONFIG_PINCTRL_STM32) += stm32/
obj-y += sunplus/
obj-$(CONFIG_PINCTRL_SUNXI) += sunxi/
obj-$(CONFIG_SOC_SOPHGO) += sophgo/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-y += ti/
obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/

View File

@ -0,0 +1,2 @@
obj-$(CONFIG_SOC_SOPHGO) += pinctrl-sophgo.o
obj-$(CONFIG_SOC_SOPHGO) += pinctrl-mango.o

View File

@ -0,0 +1,447 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/device.h>
#include <linux/of.h>
#include "../pinctrl-utils.h"
#include "pinctrl-sophgo.h"
#define DRV_PINCTRL_NAME "mango_pinctrl"
#define DRV_PINMUX_NAME "mango_pinmux"
#define FUNCTION(fname, gname, fmode) \
{ \
.name = #fname, \
.groups = gname##_group, \
.num_groups = ARRAY_SIZE(gname##_group), \
.mode = fmode, \
}
#define PIN_GROUP(gname) \
{ \
.name = #gname "_grp", \
.pins = gname##_pins, \
.num_pins = ARRAY_SIZE(gname##_pins), \
}
static const struct pinctrl_pin_desc mango_pins[] = {
PINCTRL_PIN(0, "MIO0"),
PINCTRL_PIN(1, "MIO1"),
PINCTRL_PIN(2, "MIO2"),
PINCTRL_PIN(3, "MIO3"),
PINCTRL_PIN(4, "MIO4"),
PINCTRL_PIN(5, "MIO5"),
PINCTRL_PIN(6, "MIO6"),
PINCTRL_PIN(7, "MIO7"),
PINCTRL_PIN(8, "MIO8"),
PINCTRL_PIN(9, "MIO9"),
PINCTRL_PIN(10, "MIO10"),
PINCTRL_PIN(11, "MIO11"),
PINCTRL_PIN(12, "MIO12"),
PINCTRL_PIN(13, "MIO13"),
PINCTRL_PIN(14, "MIO14"),
PINCTRL_PIN(15, "MIO15"),
PINCTRL_PIN(16, "MIO16"),
PINCTRL_PIN(17, "MIO17"),
PINCTRL_PIN(18, "MIO18"),
PINCTRL_PIN(19, "MIO19"),
PINCTRL_PIN(20, "MIO20"),
PINCTRL_PIN(21, "MIO21"),
PINCTRL_PIN(22, "MIO22"),
PINCTRL_PIN(23, "MIO23"),
PINCTRL_PIN(24, "MIO24"),
PINCTRL_PIN(25, "MIO25"),
PINCTRL_PIN(26, "MIO26"),
PINCTRL_PIN(27, "MIO27"),
PINCTRL_PIN(28, "MIO28"),
PINCTRL_PIN(29, "MIO29"),
PINCTRL_PIN(30, "MIO30"),
PINCTRL_PIN(31, "MIO31"),
PINCTRL_PIN(32, "MIO32"),
PINCTRL_PIN(33, "MIO33"),
PINCTRL_PIN(34, "MIO34"),
PINCTRL_PIN(35, "MIO35"),
PINCTRL_PIN(36, "MIO36"),
PINCTRL_PIN(37, "MIO37"),
PINCTRL_PIN(38, "MIO38"),
PINCTRL_PIN(39, "MIO39"),
PINCTRL_PIN(40, "MIO40"),
PINCTRL_PIN(41, "MIO41"),
PINCTRL_PIN(42, "MIO42"),
PINCTRL_PIN(43, "MIO43"),
PINCTRL_PIN(44, "MIO44"),
PINCTRL_PIN(45, "MIO45"),
PINCTRL_PIN(46, "MIO46"),
PINCTRL_PIN(47, "MIO47"),
PINCTRL_PIN(48, "MIO48"),
PINCTRL_PIN(49, "MIO49"),
PINCTRL_PIN(50, "MIO50"),
PINCTRL_PIN(51, "MIO51"),
PINCTRL_PIN(52, "MIO52"),
PINCTRL_PIN(53, "MIO53"),
PINCTRL_PIN(54, "MIO54"),
PINCTRL_PIN(55, "MIO55"),
PINCTRL_PIN(56, "MIO56"),
PINCTRL_PIN(57, "MIO57"),
PINCTRL_PIN(58, "MIO58"),
PINCTRL_PIN(59, "MIO59"),
PINCTRL_PIN(60, "MIO60"),
PINCTRL_PIN(61, "MIO61"),
PINCTRL_PIN(62, "MIO62"),
PINCTRL_PIN(63, "MIO63"),
PINCTRL_PIN(64, "MIO64"),
PINCTRL_PIN(65, "MIO65"),
PINCTRL_PIN(66, "MIO66"),
PINCTRL_PIN(67, "MIO67"),
PINCTRL_PIN(68, "MIO68"),
PINCTRL_PIN(69, "MIO69"),
PINCTRL_PIN(70, "MIO70"),
PINCTRL_PIN(71, "MIO71"),
PINCTRL_PIN(72, "MIO72"),
PINCTRL_PIN(73, "MIO73"),
PINCTRL_PIN(74, "MIO74"),
PINCTRL_PIN(75, "MIO75"),
PINCTRL_PIN(76, "MIO76"),
PINCTRL_PIN(77, "MIO77"),
PINCTRL_PIN(78, "MIO78"),
PINCTRL_PIN(79, "MIO79"),
PINCTRL_PIN(80, "MIO80"),
PINCTRL_PIN(81, "MIO81"),
PINCTRL_PIN(82, "MIO82"),
PINCTRL_PIN(83, "MIO83"),
PINCTRL_PIN(84, "MIO84"),
PINCTRL_PIN(85, "MIO85"),
PINCTRL_PIN(86, "MIO86"),
PINCTRL_PIN(87, "MIO87"),
PINCTRL_PIN(88, "MIO88"),
PINCTRL_PIN(89, "MIO89"),
PINCTRL_PIN(90, "MIO90"),
PINCTRL_PIN(91, "MIO91"),
PINCTRL_PIN(92, "MIO92"),
PINCTRL_PIN(93, "MIO93"),
PINCTRL_PIN(94, "MIO94"),
PINCTRL_PIN(95, "MIO95"),
PINCTRL_PIN(96, "MIO96"),
PINCTRL_PIN(97, "MIO97"),
PINCTRL_PIN(98, "MIO98"),
PINCTRL_PIN(99, "MIO99"),
PINCTRL_PIN(100, "MIO100"),
PINCTRL_PIN(101, "MIO101"),
PINCTRL_PIN(102, "MIO102"),
PINCTRL_PIN(103, "MIO103"),
PINCTRL_PIN(104, "MIO104"),
PINCTRL_PIN(105, "MIO105"),
PINCTRL_PIN(106, "MIO106"),
PINCTRL_PIN(107, "MIO107"),
PINCTRL_PIN(108, "MIO108"),
PINCTRL_PIN(109, "MIO109"),
PINCTRL_PIN(110, "MIO110"),
PINCTRL_PIN(111, "MIO111"),
PINCTRL_PIN(112, "MIO112"),
PINCTRL_PIN(113, "MIO113"),
PINCTRL_PIN(114, "MIO114"),
PINCTRL_PIN(115, "MIO115"),
PINCTRL_PIN(116, "MIO116"),
PINCTRL_PIN(117, "MIO117"),
PINCTRL_PIN(118, "MIO118"),
PINCTRL_PIN(119, "MIO119"),
PINCTRL_PIN(120, "MIO120"),
PINCTRL_PIN(121, "MIO121"),
PINCTRL_PIN(122, "MIO122"),
PINCTRL_PIN(123, "MIO123"),
PINCTRL_PIN(124, "MIO124"),
PINCTRL_PIN(125, "MIO125"),
PINCTRL_PIN(126, "MIO126"),
PINCTRL_PIN(127, "MIO127"),
PINCTRL_PIN(128, "MIO128"),
PINCTRL_PIN(129, "MIO129"),
PINCTRL_PIN(130, "MIO130"),
PINCTRL_PIN(131, "MIO131"),
PINCTRL_PIN(132, "MIO132"),
PINCTRL_PIN(133, "MIO133"),
PINCTRL_PIN(134, "MIO134"),
PINCTRL_PIN(135, "MIO135"),
PINCTRL_PIN(136, "MIO136"),
PINCTRL_PIN(137, "MIO137"),
PINCTRL_PIN(138, "MIO138"),
PINCTRL_PIN(139, "MIO139"),
PINCTRL_PIN(140, "MIO140"),
PINCTRL_PIN(141, "MIO141"),
PINCTRL_PIN(142, "MIO142"),
PINCTRL_PIN(143, "MIO143"),
PINCTRL_PIN(144, "MIO144"),
PINCTRL_PIN(145, "MIO145"),
PINCTRL_PIN(146, "MIO146"),
PINCTRL_PIN(147, "MIO147"),
PINCTRL_PIN(148, "MIO148"),
PINCTRL_PIN(149, "MIO149"),
PINCTRL_PIN(150, "MIO150"),
PINCTRL_PIN(151, "MIO151"),
PINCTRL_PIN(152, "MIO152"),
PINCTRL_PIN(153, "MIO153"),
PINCTRL_PIN(154, "MIO154"),
PINCTRL_PIN(155, "MIO155"),
PINCTRL_PIN(156, "MIO156"),
};
static const unsigned int lpc_pins[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
static const unsigned int pcie_pins[] = {13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
static const unsigned int spif_pins[] = {25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40};
static const unsigned int emmc_pins[] = {41, 42, 43, 44};
static const unsigned int sdio_pins[] = {45, 46, 47, 48};
static const unsigned int eth0_pins[] = {49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64};
static const unsigned int pwm0_pins[] = {65};
static const unsigned int pwm1_pins[] = {66};
static const unsigned int pwm2_pins[] = {67};
static const unsigned int pwm3_pins[] = {68};
static const unsigned int fan0_pins[] = {69};
static const unsigned int fan1_pins[] = {70};
static const unsigned int fan2_pins[] = {71};
static const unsigned int fan3_pins[] = {72};
static const unsigned int i2c0_pins[] = {73, 74};
static const unsigned int i2c1_pins[] = {75, 76};
static const unsigned int i2c2_pins[] = {77, 78};
static const unsigned int i2c3_pins[] = {79, 80};
static const unsigned int uart0_pins[] = {81, 82, 83, 84};
static const unsigned int uart1_pins[] = {85, 86, 87, 88};
static const unsigned int uart2_pins[] = {89, 90, 91, 92};
static const unsigned int uart3_pins[] = {93, 94, 95, 96};
static const unsigned int spi0_pins[] = {97, 98, 99, 100, 101};
static const unsigned int spi1_pins[] = {102, 103, 104, 105, 106};
static const unsigned int jtag0_pins[] = {107, 108, 109, 110, 111, 112};
static const unsigned int jtag1_pins[] = {113, 114, 115, 116, 117, 118};
static const unsigned int jtag2_pins[] = {119, 120, 121, 122, 123, 124};
// GPIO0 is pin 125
static const unsigned int dbgi2c_pins[] = {154, 155, 156};
static const char * const lpc_group[] = {"lpc_grp"};
static const char * const pcie_group[] = {"pcie_grp"};
static const char * const spif_group[] = {"spif_grp"};
static const char * const emmc_group[] = {"emmc_grp"};
static const char * const sdio_group[] = {"sdio_grp"};
static const char * const eth0_group[] = {"eth0_grp"};
static const char * const pwm0_group[] = {"pwm0_grp"};
static const char * const pwm1_group[] = {"pwm1_grp"};
static const char * const pwm2_group[] = {"pwm2_grp"};
static const char * const pwm3_group[] = {"pwm3_grp"};
static const char * const fan0_group[] = {"fan0_grp"};
static const char * const fan1_group[] = {"fan1_grp"};
static const char * const fan2_group[] = {"fan2_grp"};
static const char * const fan3_group[] = {"fan3_grp"};
static const char * const i2c0_group[] = {"i2c0_grp"};
static const char * const i2c1_group[] = {"i2c1_grp"};
static const char * const i2c2_group[] = {"i2c2_grp"};
static const char * const i2c3_group[] = {"i2c3_grp"};
static const char * const uart0_group[] = {"uart0_grp"};
static const char * const uart1_group[] = {"uart1_grp"};
static const char * const uart2_group[] = {"uart2_grp"};
static const char * const uart3_group[] = {"uart3_grp"};
static const char * const spi0_group[] = {"spi0_grp"};
static const char * const spi1_group[] = {"spi1_grp"};
static const char * const jtag0_group[] = {"jtag0_grp"};
static const char * const jtag1_group[] = {"jtag1_grp"};
static const char * const jtag2_group[] = {"jtag2_grp"};
static const char * const dbgi2c_group[] = {"dbgi2c_grp"};
static struct mango_group mango_groups[] = {
PIN_GROUP(lpc),
PIN_GROUP(pcie),
PIN_GROUP(spif),
PIN_GROUP(emmc),
PIN_GROUP(sdio),
PIN_GROUP(eth0),
PIN_GROUP(pwm0),
PIN_GROUP(pwm1),
PIN_GROUP(pwm2),
PIN_GROUP(pwm3),
PIN_GROUP(fan0),
PIN_GROUP(fan1),
PIN_GROUP(fan2),
PIN_GROUP(fan3),
PIN_GROUP(i2c0),
PIN_GROUP(i2c1),
PIN_GROUP(i2c2),
PIN_GROUP(i2c3),
PIN_GROUP(uart0),
PIN_GROUP(uart1),
PIN_GROUP(uart2),
PIN_GROUP(uart3),
PIN_GROUP(spi0),
PIN_GROUP(spi1),
PIN_GROUP(jtag0),
PIN_GROUP(jtag1),
PIN_GROUP(jtag2),
PIN_GROUP(dbgi2c),
};
static const struct mango_pmx_func mango_funcs[] = {
FUNCTION(lpc_a, lpc, FUNC_MODE0),
FUNCTION(lpc_r, lpc, FUNC_MODE1),
FUNCTION(pcie_a, pcie, FUNC_MODE0),
FUNCTION(pcie_r, pcie, FUNC_MODE1),
FUNCTION(spif_a, spif, FUNC_MODE0),
FUNCTION(spif_r, spif, FUNC_MODE1),
FUNCTION(emmc_a, emmc, FUNC_MODE0),
FUNCTION(emmc_r, emmc, FUNC_MODE1),
FUNCTION(sdio_a, sdio, FUNC_MODE0),
FUNCTION(sdio_r, sdio, FUNC_MODE1),
FUNCTION(eth0_a, eth0, FUNC_MODE1),
FUNCTION(eth0_r, eth0, FUNC_MODE0),
FUNCTION(pwm0_a, pwm0, FUNC_MODE0),
FUNCTION(pwm0_r, pwm0, FUNC_MODE1),
FUNCTION(pwm1_a, pwm1, FUNC_MODE0),
FUNCTION(pwm1_r, pwm1, FUNC_MODE1),
FUNCTION(pwm2_a, pwm2, FUNC_MODE0),
FUNCTION(pwm2_r, pwm2, FUNC_MODE1),
FUNCTION(pwm3_a, pwm3, FUNC_MODE0),
FUNCTION(pwm3_r, pwm3, FUNC_MODE1),
FUNCTION(fan0_a, fan0, FUNC_MODE1),
FUNCTION(fan0_r, fan0, FUNC_MODE0),
FUNCTION(fan1_a, fan1, FUNC_MODE1),
FUNCTION(fan1_r, fan1, FUNC_MODE0),
FUNCTION(fan2_a, fan2, FUNC_MODE1),
FUNCTION(fan2_r, fan2, FUNC_MODE0),
FUNCTION(fan3_a, fan3, FUNC_MODE1),
FUNCTION(fan3_r, fan3, FUNC_MODE0),
FUNCTION(i2c0_a, i2c0, FUNC_MODE0),
FUNCTION(i2c0_r, i2c0, FUNC_MODE1),
FUNCTION(i2c1_a, i2c1, FUNC_MODE0),
FUNCTION(i2c1_r, i2c1, FUNC_MODE1),
FUNCTION(i2c2_a, i2c2, FUNC_MODE1),
FUNCTION(i2c2_r, i2c2, FUNC_MODE0),
FUNCTION(i2c3_a, i2c3, FUNC_MODE1),
FUNCTION(i2c3_r, i2c3, FUNC_MODE0),
FUNCTION(uart0_a, uart0, FUNC_MODE0),
FUNCTION(uart0_r, uart0, FUNC_MODE1),
FUNCTION(uart1_a, uart1, FUNC_MODE0),
FUNCTION(uart1_r, uart1, FUNC_MODE1),
FUNCTION(uart2_a, uart2, FUNC_MODE1),
FUNCTION(uart2_r, uart2, FUNC_MODE0),
FUNCTION(uart3_a, uart3, FUNC_MODE1),
FUNCTION(uart3_r, uart3, FUNC_MODE0),
FUNCTION(spi0_a, spi0, FUNC_MODE1),
FUNCTION(spi0_r, spi0, FUNC_MODE0),
FUNCTION(spi1_a, spi1, FUNC_MODE0),
FUNCTION(spi1_r, spi1, FUNC_MODE1),
FUNCTION(jtag0_a, jtag0, FUNC_MODE0),
FUNCTION(jtag0_r, jtag0, FUNC_MODE1),
FUNCTION(jtag1_a, jtag1, FUNC_MODE1),
FUNCTION(jtag1_r, jtag1, FUNC_MODE0),
FUNCTION(jtag2_a, jtag2, FUNC_MODE1),
FUNCTION(jtag2_r, jtag2, FUNC_MODE0),
FUNCTION(dbgi2c_a, dbgi2c, FUNC_MODE0),
FUNCTION(dbgi2c_r, dbgi2c, FUNC_MODE1),
};
static struct device_attribute lpc_attr = __ATTR(lpc, 0664, pinmux_show, pinmux_store);
static struct device_attribute pcie_attr = __ATTR(pcie, 0664, pinmux_show, pinmux_store);
static struct device_attribute spif_attr = __ATTR(spif, 0664, pinmux_show, pinmux_store);
static struct device_attribute emmc_attr = __ATTR(emmc, 0664, pinmux_show, pinmux_store);
static struct device_attribute sdio_attr = __ATTR(sdio, 0664, pinmux_show, pinmux_store);
static struct device_attribute eth0_attr = __ATTR(eth0, 0664, pinmux_show, pinmux_store);
static struct device_attribute pwm0_attr = __ATTR(pwm0, 0664, pinmux_show, pinmux_store);
static struct device_attribute pwm1_attr = __ATTR(pwm1, 0664, pinmux_show, pinmux_store);
static struct device_attribute pwm2_attr = __ATTR(pwm2, 0664, pinmux_show, pinmux_store);
static struct device_attribute pwm3_attr = __ATTR(pwm3, 0664, pinmux_show, pinmux_store);
static struct device_attribute fan0_attr = __ATTR(fan0, 0664, pinmux_show, pinmux_store);
static struct device_attribute fan1_attr = __ATTR(fan1, 0664, pinmux_show, pinmux_store);
static struct device_attribute fan2_attr = __ATTR(fan2, 0664, pinmux_show, pinmux_store);
static struct device_attribute fan3_attr = __ATTR(fan3, 0664, pinmux_show, pinmux_store);
static struct device_attribute i2c0_attr = __ATTR(i2c0, 0664, pinmux_show, pinmux_store);
static struct device_attribute i2c1_attr = __ATTR(i2c1, 0664, pinmux_show, pinmux_store);
static struct device_attribute i2c2_attr = __ATTR(i2c2, 0664, pinmux_show, pinmux_store);
static struct device_attribute i2c3_attr = __ATTR(i2c3, 0664, pinmux_show, pinmux_store);
static struct device_attribute uart0_attr = __ATTR(uart0, 0664, pinmux_show, pinmux_store);
static struct device_attribute uart1_attr = __ATTR(uart1, 0664, pinmux_show, pinmux_store);
static struct device_attribute uart2_attr = __ATTR(uart2, 0664, pinmux_show, pinmux_store);
static struct device_attribute uart3_attr = __ATTR(uart3, 0664, pinmux_show, pinmux_store);
static struct device_attribute spi0_attr = __ATTR(spi0, 0664, pinmux_show, pinmux_store);
static struct device_attribute spi1_attr = __ATTR(spi1, 0664, pinmux_show, pinmux_store);
static struct device_attribute jtag0_attr = __ATTR(jtag0, 0664, pinmux_show, pinmux_store);
static struct device_attribute jtag1_attr = __ATTR(jtag1, 0664, pinmux_show, pinmux_store);
static struct device_attribute jtag2_attr = __ATTR(jtag2, 0664, pinmux_show, pinmux_store);
static struct device_attribute dbgi2c_attr = __ATTR(dbgi2c, 0664, pinmux_show, pinmux_store);
static struct attribute *pinmux_attrs[] = {
&lpc_attr.attr,
&pcie_attr.attr,
&spif_attr.attr,
&emmc_attr.attr,
&sdio_attr.attr,
&eth0_attr.attr,
&pwm0_attr.attr,
&pwm1_attr.attr,
&pwm2_attr.attr,
&pwm3_attr.attr,
&fan0_attr.attr,
&fan1_attr.attr,
&fan2_attr.attr,
&fan3_attr.attr,
&i2c0_attr.attr,
&i2c1_attr.attr,
&i2c2_attr.attr,
&i2c3_attr.attr,
&uart0_attr.attr,
&uart1_attr.attr,
&uart2_attr.attr,
&uart3_attr.attr,
&spi0_attr.attr,
&spi1_attr.attr,
&jtag0_attr.attr,
&jtag1_attr.attr,
&jtag2_attr.attr,
&dbgi2c_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(pinmux);
static struct class pinmux_class = {
.name = "pinmux",
.owner = THIS_MODULE,
.dev_groups = pinmux_groups,
};
static struct mango_soc_pinctrl_data mango_pinctrl_data = {
.pins = mango_pins,
.npins = ARRAY_SIZE(mango_pins),
.groups = mango_groups,
.groups_count = ARRAY_SIZE(mango_groups),
.functions = mango_funcs,
.functions_count = ARRAY_SIZE(mango_funcs),
.p_class = &pinmux_class,
};
static const struct of_device_id mango_pinctrl_of_table[] = {
{
.compatible = "sophgo, pinctrl-mango",
.data = &mango_pinctrl_data,
},
{}
};
static int mango_pinctrl_probe(struct platform_device *pdev)
{
return sophgo_pinctrl_probe(pdev);
}
static struct platform_driver mango_pinctrl_driver = {
.probe = mango_pinctrl_probe,
.driver = {
.name = DRV_PINCTRL_NAME,
.of_match_table = of_match_ptr(mango_pinctrl_of_table),
},
};
static int __init mango_pinctrl_init(void)
{
return platform_driver_register(&mango_pinctrl_driver);
}
postcore_initcall(mango_pinctrl_init);

View File

@ -0,0 +1,293 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/of_device.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include "pinctrl-sophgo.h"
static int mango_get_groups(struct pinctrl_dev *pctldev, unsigned int selector,
const char * const **groups,
unsigned int * const num_groups);
static struct mango_soc_pinctrl_data *get_pinmux_data(struct pinctrl_dev *pctldev)
{
struct mango_pinctrl *mangopctrl = pinctrl_dev_get_drvdata(pctldev);
return mangopctrl->data;
}
static int mango_get_functions_count(struct pinctrl_dev *pctldev)
{
struct mango_soc_pinctrl_data *data = get_pinmux_data(pctldev);
return data->functions_count;
}
static const char *mango_get_fname(struct pinctrl_dev *pctldev,
unsigned int selector)
{
struct mango_soc_pinctrl_data *data = get_pinmux_data(pctldev);
return data->functions[selector].name;
}
static int mango_set_mux(struct pinctrl_dev *pctldev, unsigned int selector,
unsigned int group)
{
int p;
unsigned int pidx;
u32 offset, regval, mux_offset;
struct mango_pinctrl *ctrl = pinctrl_dev_get_drvdata(pctldev);
struct mango_soc_pinctrl_data *data = get_pinmux_data(pctldev);
data->groups[group].cur_func_idx = data->functions[selector].mode;
for (p = 0; p < data->groups[group].num_pins; p++) {
pidx = data->groups[group].pins[p];
offset = (pidx >> 1) << 2;
regmap_read(ctrl->syscon_pinctl,
ctrl->top_pinctl_offset + offset, &regval);
mux_offset = ((!((pidx + 1) & 1) << 4) + 4);
regval = regval & ~(3 << mux_offset);
regval |= data->functions[selector].mode << mux_offset;
regmap_write(ctrl->syscon_pinctl,
ctrl->top_pinctl_offset + offset, regval);
regmap_read(ctrl->syscon_pinctl,
ctrl->top_pinctl_offset + offset, &regval);
dev_dbg(ctrl->dev, "%s : check new reg=0x%x val=0x%x\n",
data->groups[group].name,
ctrl->top_pinctl_offset + offset, regval);
}
return 0;
}
static const struct pinmux_ops mango_pinmux_ops = {
.get_functions_count = mango_get_functions_count,
.get_function_name = mango_get_fname,
.get_function_groups = mango_get_groups,
.set_mux = mango_set_mux,
.strict = true,
};
static int mango_pinconf_cfg_get(struct pinctrl_dev *pctldev, unsigned int pin,
unsigned long *config)
{
return 0;
}
static int mango_pinconf_cfg_set(struct pinctrl_dev *pctldev, unsigned int pin,
unsigned long *configs, unsigned int num_configs)
{
return 0;
}
static int mango_pinconf_group_set(struct pinctrl_dev *pctldev,
unsigned int selector, unsigned long *configs, unsigned int num_configs)
{
return 0;
}
static const struct pinconf_ops mango_pinconf_ops = {
.is_generic = true,
.pin_config_get = mango_pinconf_cfg_get,
.pin_config_set = mango_pinconf_cfg_set,
.pin_config_group_set = mango_pinconf_group_set,
};
static int mango_get_groups(struct pinctrl_dev *pctldev, unsigned int selector,
const char * const **groups,
unsigned int * const num_groups)
{
struct mango_soc_pinctrl_data *data = get_pinmux_data(pctldev);
*groups = data->functions[selector].groups;
*num_groups = data->functions[selector].num_groups;
return 0;
}
static int mango_get_groups_count(struct pinctrl_dev *pctldev)
{
struct mango_soc_pinctrl_data *data = get_pinmux_data(pctldev);
return data->groups_count;
}
static const char *mango_get_group_name(struct pinctrl_dev *pctldev,
unsigned int selector)
{
struct mango_soc_pinctrl_data *data = get_pinmux_data(pctldev);
return data->groups[selector].name;
}
static int mango_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector,
const unsigned int **pins,
unsigned int *num_pins)
{
struct mango_soc_pinctrl_data *data = get_pinmux_data(pctldev);
*pins = data->groups[selector].pins;
*num_pins = data->groups[selector].num_pins;
return 0;
}
static void mango_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned int offset)
{
}
static const struct pinctrl_ops mango_pctrl_ops = {
.get_groups_count = mango_get_groups_count,
.get_group_name = mango_get_group_name,
.get_group_pins = mango_get_group_pins,
.pin_dbg_show = mango_pin_dbg_show,
.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
.dt_free_map = pinctrl_utils_free_map,
};
static struct pinctrl_desc mango_desc = {
.name = "mango_pinctrl",
.pctlops = &mango_pctrl_ops,
.pmxops = &mango_pinmux_ops,
.confops = &mango_pinconf_ops,
.owner = THIS_MODULE,
};
ssize_t pinmux_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct mango_pinctrl *mangopctrl;
int p, ret, group, selector = -1;
struct mango_soc_pinctrl_data *data;
mangopctrl = dev_get_drvdata(dev);
data = (struct mango_soc_pinctrl_data *)mangopctrl->data;
for (p = 0; p < data->functions_count; p++) {
if (!strncmp(attr->attr.name, data->functions[p].name,
strlen(attr->attr.name))) {
selector = p;
break;
}
}
if (selector < 0)
return -ENXIO;
group = selector/2;
ret = snprintf(buf, 128, "%d\n", data->groups[group].cur_func_idx);
if (ret <= 0 || ret > 128) {
dev_err(dev, "snprintf failed %d\n", ret);
return -EFAULT;
}
return ret;
}
ssize_t pinmux_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
struct mango_pinctrl *mangopctrl;
int p, ret, group, selector = -1;
unsigned long user_data;
struct mango_soc_pinctrl_data *data;
ret = kstrtoul(buf, 0, &user_data);
if (ret)
return -EINVAL;
if (user_data != 0 && user_data != 1)
return -EINVAL;
mangopctrl = dev_get_drvdata(dev);
data = (struct mango_soc_pinctrl_data *)mangopctrl->data;
for (p = 0; p < data->functions_count; p++) {
if (!strncmp(attr->attr.name, data->functions[p].name,
strlen(attr->attr.name)) &&
(user_data == data->functions[p].mode)) {
selector = p;
break;
}
}
if (selector < 0)
return -ENXIO;
group = selector/2;
mango_set_mux(mangopctrl->pctl, selector, group);
dev_info(dev, "pinmux store set %s to func %d\n",
attr->attr.name, data->functions[selector].mode);
return size;
}
int sophgo_pinctrl_probe(struct platform_device *pdev)
{
struct mango_pinctrl *mangopctrl;
struct pinctrl_desc *desc;
struct mango_soc_pinctrl_data *data;
struct device *dev = &pdev->dev;
struct device *pin_dev = NULL;
struct device_node *np = dev->of_node, *np_top;
static struct regmap *syscon;
int ret;
data = (struct mango_soc_pinctrl_data *)of_device_get_match_data(&pdev->dev);
if (!data)
return -EINVAL;
mangopctrl = devm_kzalloc(&pdev->dev, sizeof(*mangopctrl), GFP_KERNEL);
if (!mangopctrl)
return -ENOMEM;
mangopctrl->dev = &pdev->dev;
np_top = of_parse_phandle(np, "subctrl-syscon", 0);
if (!np_top) {
dev_err(dev, "%s can't get subctrl-syscon node\n", __func__);
return -EINVAL;
}
syscon = syscon_node_to_regmap(np_top);
if (IS_ERR(syscon)) {
dev_err(dev, "cannot get regmap\n");
return PTR_ERR(syscon);
}
mangopctrl->syscon_pinctl = syscon;
ret = device_property_read_u32(&pdev->dev,
"top_pinctl_offset", &mangopctrl->top_pinctl_offset);
if (ret < 0) {
dev_err(dev, "cannot get top_pinctl_offset\n");
return ret;
}
desc = &mango_desc;
desc->pins = data->pins;
desc->npins = data->npins;
mangopctrl->data = (void *)data;
mangopctrl->pctl = devm_pinctrl_register(&pdev->dev, desc, mangopctrl);
if (IS_ERR(mangopctrl->pctl)) {
dev_err(&pdev->dev, "could not register Sophgo pin ctrl driver\n");
return PTR_ERR(mangopctrl->pctl);
}
platform_set_drvdata(pdev, mangopctrl);
ret = class_register(data->p_class);
if (ret < 0) {
dev_err(dev, "cannot register pinmux class\n");
return ret;
}
pin_dev = device_create(data->p_class, &pdev->dev, MKDEV(0, 0), mangopctrl, "mango_pinmux");
if (IS_ERR(pin_dev))
return PTR_ERR(pin_dev);
return 0;
}

View File

@ -0,0 +1,70 @@
#ifndef __mango_PINCTRL_CORE_H__
#define __mango_PINCTRL_CORE_H__
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include "../pinctrl-utils.h"
#include "../core.h"
enum FUNC_MODE {
FUNC_MODE0,
FUNC_MODE1,
FUNC_MODE2,
FUNC_MODE3,
FUNC_MASK,
};
struct mango_pinctrl {
struct device *dev;
struct pinctrl_dev *pctl;
u32 top_pinctl_offset;
struct regmap *syscon_pinctl;
void *data;
};
struct mango_group {
const char *name;
const unsigned int *pins;
const unsigned int num_pins;
int cur_func_idx;
struct mango_pmx_func *funcs;
};
struct mango_pmx_func {
const char *name;
const char * const *groups;
unsigned int num_groups;
enum FUNC_MODE mode;
};
struct mango_soc_pinmux_info {
const char name[16];
const char name_a[16];
const char name_r[16];
struct pinctrl_state *pinctrl_a;
struct pinctrl_state *pinctrl_r;
const unsigned int def_state; /* default state */
int (*set)(struct device *dev, unsigned int data);
};
struct mango_soc_pinctrl_data {
const struct pinctrl_pin_desc *pins;
unsigned int npins;
struct mango_group *groups;
int groups_count;
const struct mango_pmx_func *functions;
int functions_count;
struct class *p_class;
};
int sophgo_pinctrl_probe(struct platform_device *pdev);
int mango_pmux_probe(struct platform_device *pdev);
ssize_t pinmux_show(struct device *dev,
struct device_attribute *attr, char *buf);
ssize_t pinmux_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size);
#endif