diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index f71fefff400f..bd0308825ba5 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -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 diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 89bfa01b5231..909c761d7c06 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -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/ diff --git a/drivers/pinctrl/sophgo/Makefile b/drivers/pinctrl/sophgo/Makefile new file mode 100644 index 000000000000..230ba9f55248 --- /dev/null +++ b/drivers/pinctrl/sophgo/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_SOC_SOPHGO) += pinctrl-sophgo.o +obj-$(CONFIG_SOC_SOPHGO) += pinctrl-mango.o diff --git a/drivers/pinctrl/sophgo/pinctrl-mango.c b/drivers/pinctrl/sophgo/pinctrl-mango.c new file mode 100644 index 000000000000..43dda6429a2b --- /dev/null +++ b/drivers/pinctrl/sophgo/pinctrl-mango.c @@ -0,0 +1,447 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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, + ð0_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); + diff --git a/drivers/pinctrl/sophgo/pinctrl-sophgo.c b/drivers/pinctrl/sophgo/pinctrl-sophgo.c new file mode 100644 index 000000000000..4d5738786e9a --- /dev/null +++ b/drivers/pinctrl/sophgo/pinctrl-sophgo.c @@ -0,0 +1,293 @@ +#include +#include +#include +#include +#include +#include + +#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, ®val); + 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, ®val); + 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; +} + diff --git a/drivers/pinctrl/sophgo/pinctrl-sophgo.h b/drivers/pinctrl/sophgo/pinctrl-sophgo.h new file mode 100644 index 000000000000..f3a30f0275b1 --- /dev/null +++ b/drivers/pinctrl/sophgo/pinctrl-sophgo.h @@ -0,0 +1,70 @@ +#ifndef __mango_PINCTRL_CORE_H__ +#define __mango_PINCTRL_CORE_H__ + +#include +#include +#include +#include +#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