bcm53xx: add pending pinctrl driver
It's required to support devices using adjustable SoC pins for some specific purpose (e.g. I2C, PWM, UART1). Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
This commit is contained in:
		| @@ -293,6 +293,7 @@ CONFIG_PHYLIB=y | |||||||
| # CONFIG_PHY_NS2_USB_DRD is not set | # CONFIG_PHY_NS2_USB_DRD is not set | ||||||
| CONFIG_PINCTRL=y | CONFIG_PINCTRL=y | ||||||
| # CONFIG_PINCTRL_IPROC_GPIO is not set | # CONFIG_PINCTRL_IPROC_GPIO is not set | ||||||
|  | CONFIG_PINCTRL_NS=y | ||||||
| # CONFIG_PINCTRL_NS2_MUX is not set | # CONFIG_PINCTRL_NS2_MUX is not set | ||||||
| # CONFIG_PL310_ERRATA_588369 is not set | # CONFIG_PL310_ERRATA_588369 is not set | ||||||
| # CONFIG_PL310_ERRATA_727915 is not set | # CONFIG_PL310_ERRATA_727915 is not set | ||||||
|   | |||||||
| @@ -0,0 +1,426 @@ | |||||||
|  | From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl> | ||||||
|  | Date: Wed, 26 Sep 2018 21:31:03 +0200 | ||||||
|  | Subject: [PATCH] pinctrl: bcm: add Northstar driver | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  |  | ||||||
|  | This driver provides support for Northstar mux controller. It differs | ||||||
|  | from Northstar Plus one so a new binding and driver were needed. | ||||||
|  |  | ||||||
|  | Signed-off-by: Rafał Miłecki <rafal@milecki.pl> | ||||||
|  | Signed-off-by: Linus Walleij <linus.walleij@linaro.org> | ||||||
|  | --- | ||||||
|  |  drivers/pinctrl/bcm/Kconfig      |  13 ++ | ||||||
|  |  drivers/pinctrl/bcm/Makefile     |   1 + | ||||||
|  |  drivers/pinctrl/bcm/pinctrl-ns.c | 372 +++++++++++++++++++++++++++++++++++++++ | ||||||
|  |  3 files changed, 386 insertions(+) | ||||||
|  |  create mode 100644 drivers/pinctrl/bcm/pinctrl-ns.c | ||||||
|  |  | ||||||
|  | --- a/drivers/pinctrl/bcm/Kconfig | ||||||
|  | +++ b/drivers/pinctrl/bcm/Kconfig | ||||||
|  | @@ -72,6 +72,19 @@ config PINCTRL_CYGNUS_MUX | ||||||
|  |  	  configuration, with the exception that certain individual pins | ||||||
|  |  	  can be overridden to GPIO function | ||||||
|  |   | ||||||
|  | +config PINCTRL_NS | ||||||
|  | +	bool "Broadcom Northstar pins driver" | ||||||
|  | +	depends on OF && (ARCH_BCM_5301X || COMPILE_TEST) | ||||||
|  | +	select PINMUX | ||||||
|  | +	select GENERIC_PINCONF | ||||||
|  | +	default ARCH_BCM_5301X | ||||||
|  | +	help | ||||||
|  | +	  Say yes here to enable the Broadcom NS SoC pins driver. | ||||||
|  | + | ||||||
|  | +	  The Broadcom Northstar pins driver supports muxing multi-purpose pins | ||||||
|  | +	  that can be used for various functions (e.g. SPI, I2C, UART) as well | ||||||
|  | +	  as GPIOs. | ||||||
|  | + | ||||||
|  |  config PINCTRL_NSP_GPIO | ||||||
|  |  	bool "Broadcom NSP GPIO (with PINCONF) driver" | ||||||
|  |  	depends on OF_GPIO && (ARCH_BCM_NSP || COMPILE_TEST) | ||||||
|  | --- a/drivers/pinctrl/bcm/Makefile | ||||||
|  | +++ b/drivers/pinctrl/bcm/Makefile | ||||||
|  | @@ -5,6 +5,7 @@ obj-$(CONFIG_PINCTRL_BCM281XX)		+= pinct | ||||||
|  |  obj-$(CONFIG_PINCTRL_BCM2835)		+= pinctrl-bcm2835.o | ||||||
|  |  obj-$(CONFIG_PINCTRL_IPROC_GPIO)	+= pinctrl-iproc-gpio.o | ||||||
|  |  obj-$(CONFIG_PINCTRL_CYGNUS_MUX)	+= pinctrl-cygnus-mux.o | ||||||
|  | +obj-$(CONFIG_PINCTRL_NS)		+= pinctrl-ns.o | ||||||
|  |  obj-$(CONFIG_PINCTRL_NSP_GPIO)		+= pinctrl-nsp-gpio.o | ||||||
|  |  obj-$(CONFIG_PINCTRL_NS2_MUX)		+= pinctrl-ns2-mux.o | ||||||
|  |  obj-$(CONFIG_PINCTRL_NSP_MUX)		+= pinctrl-nsp-mux.o | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/drivers/pinctrl/bcm/pinctrl-ns.c | ||||||
|  | @@ -0,0 +1,372 @@ | ||||||
|  | +// SPDX-License-Identifier: GPL-2.0 | ||||||
|  | +/* | ||||||
|  | + * Copyright (C) 2018 Rafał Miłecki <rafal@milecki.pl> | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +#include <linux/err.h> | ||||||
|  | +#include <linux/io.h> | ||||||
|  | +#include <linux/module.h> | ||||||
|  | +#include <linux/of.h> | ||||||
|  | +#include <linux/of_device.h> | ||||||
|  | +#include <linux/pinctrl/pinconf-generic.h> | ||||||
|  | +#include <linux/pinctrl/pinctrl.h> | ||||||
|  | +#include <linux/pinctrl/pinmux.h> | ||||||
|  | +#include <linux/platform_device.h> | ||||||
|  | +#include <linux/slab.h> | ||||||
|  | + | ||||||
|  | +#define FLAG_BCM4708		BIT(1) | ||||||
|  | +#define FLAG_BCM4709		BIT(2) | ||||||
|  | +#define FLAG_BCM53012		BIT(3) | ||||||
|  | + | ||||||
|  | +struct ns_pinctrl { | ||||||
|  | +	struct device *dev; | ||||||
|  | +	unsigned int chipset_flag; | ||||||
|  | +	struct pinctrl_dev *pctldev; | ||||||
|  | +	void __iomem *base; | ||||||
|  | + | ||||||
|  | +	struct pinctrl_desc pctldesc; | ||||||
|  | +	struct ns_pinctrl_group *groups; | ||||||
|  | +	unsigned int num_groups; | ||||||
|  | +	struct ns_pinctrl_function *functions; | ||||||
|  | +	unsigned int num_functions; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * Pins | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +static const struct pinctrl_pin_desc ns_pinctrl_pins[] = { | ||||||
|  | +	{ 0, "spi_clk", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +	{ 1, "spi_ss", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +	{ 2, "spi_mosi", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +	{ 3, "spi_miso", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +	{ 4, "i2c_scl", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +	{ 5, "i2c_sda", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +	{ 6, "mdc", (void *)(FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +	{ 7, "mdio", (void *)(FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +	{ 8, "pwm0", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +	{ 9, "pwm1", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +	{ 10, "pwm2", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +	{ 11, "pwm3", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +	{ 12, "uart1_rx", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +	{ 13, "uart1_tx", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +	{ 14, "uart1_cts", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +	{ 15, "uart1_rts", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +	{ 16, "uart2_rx", (void *)(FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +	{ 17, "uart2_tx", (void *)(FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +/* TODO { ??, "xtal_out", (void *)(FLAG_BCM4709) }, */ | ||||||
|  | +	{ 22, "sdio_pwr", (void *)(FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +	{ 23, "sdio_en_1p8v", (void *)(FLAG_BCM4709 | FLAG_BCM53012) }, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * Groups | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +struct ns_pinctrl_group { | ||||||
|  | +	const char *name; | ||||||
|  | +	const unsigned int *pins; | ||||||
|  | +	const unsigned int num_pins; | ||||||
|  | +	unsigned int chipsets; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static const unsigned int spi_pins[] = { 0, 1, 2, 3 }; | ||||||
|  | +static const unsigned int i2c_pins[] = { 4, 5 }; | ||||||
|  | +static const unsigned int mdio_pins[] = { 6, 7 }; | ||||||
|  | +static const unsigned int pwm0_pins[] = { 8 }; | ||||||
|  | +static const unsigned int pwm1_pins[] = { 9 }; | ||||||
|  | +static const unsigned int pwm2_pins[] = { 10 }; | ||||||
|  | +static const unsigned int pwm3_pins[] = { 11 }; | ||||||
|  | +static const unsigned int uart1_pins[] = { 12, 13, 14, 15 }; | ||||||
|  | +static const unsigned int uart2_pins[] = { 16, 17 }; | ||||||
|  | +static const unsigned int sdio_pwr_pins[] = { 22 }; | ||||||
|  | +static const unsigned int sdio_1p8v_pins[] = { 23 }; | ||||||
|  | + | ||||||
|  | +#define NS_GROUP(_name, _pins, _chipsets)		\ | ||||||
|  | +{							\ | ||||||
|  | +	.name = _name,					\ | ||||||
|  | +	.pins = _pins,					\ | ||||||
|  | +	.num_pins = ARRAY_SIZE(_pins),			\ | ||||||
|  | +	.chipsets = _chipsets,				\ | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static const struct ns_pinctrl_group ns_pinctrl_groups[] = { | ||||||
|  | +	NS_GROUP("spi_grp", spi_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), | ||||||
|  | +	NS_GROUP("i2c_grp", i2c_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), | ||||||
|  | +	NS_GROUP("mdio_grp", mdio_pins, FLAG_BCM4709 | FLAG_BCM53012), | ||||||
|  | +	NS_GROUP("pwm0_grp", pwm0_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), | ||||||
|  | +	NS_GROUP("pwm1_grp", pwm1_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), | ||||||
|  | +	NS_GROUP("pwm2_grp", pwm2_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), | ||||||
|  | +	NS_GROUP("pwm3_grp", pwm3_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), | ||||||
|  | +	NS_GROUP("uart1_grp", uart1_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), | ||||||
|  | +	NS_GROUP("uart2_grp", uart2_pins, FLAG_BCM4709 | FLAG_BCM53012), | ||||||
|  | +	NS_GROUP("sdio_pwr_grp", sdio_pwr_pins, FLAG_BCM4709 | FLAG_BCM53012), | ||||||
|  | +	NS_GROUP("sdio_1p8v_grp", sdio_1p8v_pins, FLAG_BCM4709 | FLAG_BCM53012), | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * Functions | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +struct ns_pinctrl_function { | ||||||
|  | +	const char *name; | ||||||
|  | +	const char * const *groups; | ||||||
|  | +	const unsigned int num_groups; | ||||||
|  | +	unsigned int chipsets; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static const char * const spi_groups[] = { "spi_grp" }; | ||||||
|  | +static const char * const i2c_groups[] = { "i2c_grp" }; | ||||||
|  | +static const char * const mdio_groups[] = { "mdio_grp" }; | ||||||
|  | +static const char * const pwm_groups[] = { "pwm0_grp", "pwm1_grp", "pwm2_grp", | ||||||
|  | +					   "pwm3_grp" }; | ||||||
|  | +static const char * const uart1_groups[] = { "uart1_grp" }; | ||||||
|  | +static const char * const uart2_groups[] = { "uart2_grp" }; | ||||||
|  | +static const char * const sdio_groups[] = { "sdio_pwr_grp", "sdio_1p8v_grp" }; | ||||||
|  | + | ||||||
|  | +#define NS_FUNCTION(_name, _groups, _chipsets)		\ | ||||||
|  | +{							\ | ||||||
|  | +	.name = _name,					\ | ||||||
|  | +	.groups = _groups,				\ | ||||||
|  | +	.num_groups = ARRAY_SIZE(_groups),		\ | ||||||
|  | +	.chipsets = _chipsets,				\ | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static const struct ns_pinctrl_function ns_pinctrl_functions[] = { | ||||||
|  | +	NS_FUNCTION("spi", spi_groups, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), | ||||||
|  | +	NS_FUNCTION("i2c", i2c_groups, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), | ||||||
|  | +	NS_FUNCTION("mdio", mdio_groups, FLAG_BCM4709 | FLAG_BCM53012), | ||||||
|  | +	NS_FUNCTION("pwm", pwm_groups, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), | ||||||
|  | +	NS_FUNCTION("uart1", uart1_groups, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012), | ||||||
|  | +	NS_FUNCTION("uart2", uart2_groups, FLAG_BCM4709 | FLAG_BCM53012), | ||||||
|  | +	NS_FUNCTION("sdio", sdio_groups, FLAG_BCM4709 | FLAG_BCM53012), | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * Groups code | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +static int ns_pinctrl_get_groups_count(struct pinctrl_dev *pctrl_dev) | ||||||
|  | +{ | ||||||
|  | +	struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); | ||||||
|  | + | ||||||
|  | +	return ns_pinctrl->num_groups; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static const char *ns_pinctrl_get_group_name(struct pinctrl_dev *pctrl_dev, | ||||||
|  | +					     unsigned int selector) | ||||||
|  | +{ | ||||||
|  | +	struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); | ||||||
|  | + | ||||||
|  | +	return ns_pinctrl->groups[selector].name; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int ns_pinctrl_get_group_pins(struct pinctrl_dev *pctrl_dev, | ||||||
|  | +				     unsigned int selector, | ||||||
|  | +				     const unsigned int **pins, | ||||||
|  | +				     unsigned int *num_pins) | ||||||
|  | +{ | ||||||
|  | +	struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); | ||||||
|  | + | ||||||
|  | +	*pins = ns_pinctrl->groups[selector].pins; | ||||||
|  | +	*num_pins = ns_pinctrl->groups[selector].num_pins; | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static const struct pinctrl_ops ns_pinctrl_ops = { | ||||||
|  | +	.get_groups_count = ns_pinctrl_get_groups_count, | ||||||
|  | +	.get_group_name = ns_pinctrl_get_group_name, | ||||||
|  | +	.get_group_pins = ns_pinctrl_get_group_pins, | ||||||
|  | +	.dt_node_to_map = pinconf_generic_dt_node_to_map_group, | ||||||
|  | +	.dt_free_map = pinconf_generic_dt_free_map, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * Functions code | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +static int ns_pinctrl_get_functions_count(struct pinctrl_dev *pctrl_dev) | ||||||
|  | +{ | ||||||
|  | +	struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); | ||||||
|  | + | ||||||
|  | +	return ns_pinctrl->num_functions; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static const char *ns_pinctrl_get_function_name(struct pinctrl_dev *pctrl_dev, | ||||||
|  | +						unsigned int selector) | ||||||
|  | +{ | ||||||
|  | +	struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); | ||||||
|  | + | ||||||
|  | +	return ns_pinctrl->functions[selector].name; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int ns_pinctrl_get_function_groups(struct pinctrl_dev *pctrl_dev, | ||||||
|  | +					  unsigned int selector, | ||||||
|  | +					  const char * const **groups, | ||||||
|  | +					  unsigned * const num_groups) | ||||||
|  | +{ | ||||||
|  | +	struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); | ||||||
|  | + | ||||||
|  | +	*groups = ns_pinctrl->functions[selector].groups; | ||||||
|  | +	*num_groups = ns_pinctrl->functions[selector].num_groups; | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int ns_pinctrl_set_mux(struct pinctrl_dev *pctrl_dev, | ||||||
|  | +			      unsigned int func_select, | ||||||
|  | +			      unsigned int grp_select) | ||||||
|  | +{ | ||||||
|  | +	struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); | ||||||
|  | +	u32 unset = 0; | ||||||
|  | +	u32 tmp; | ||||||
|  | +	int i; | ||||||
|  | + | ||||||
|  | +	for (i = 0; i < ns_pinctrl->groups[grp_select].num_pins; i++) { | ||||||
|  | +		int pin_number = ns_pinctrl->groups[grp_select].pins[i]; | ||||||
|  | + | ||||||
|  | +		unset |= BIT(pin_number); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	tmp = readl(ns_pinctrl->base); | ||||||
|  | +	tmp &= ~unset; | ||||||
|  | +	writel(tmp, ns_pinctrl->base); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static const struct pinmux_ops ns_pinctrl_pmxops = { | ||||||
|  | +	.get_functions_count = ns_pinctrl_get_functions_count, | ||||||
|  | +	.get_function_name = ns_pinctrl_get_function_name, | ||||||
|  | +	.get_function_groups = ns_pinctrl_get_function_groups, | ||||||
|  | +	.set_mux = ns_pinctrl_set_mux, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +/* | ||||||
|  | + * Controller code | ||||||
|  | + */ | ||||||
|  | + | ||||||
|  | +static struct pinctrl_desc ns_pinctrl_desc = { | ||||||
|  | +	.name = "pinctrl-ns", | ||||||
|  | +	.pctlops = &ns_pinctrl_ops, | ||||||
|  | +	.pmxops = &ns_pinctrl_pmxops, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static const struct of_device_id ns_pinctrl_of_match_table[] = { | ||||||
|  | +	{ .compatible = "brcm,bcm4708-pinmux", .data = (void *)FLAG_BCM4708, }, | ||||||
|  | +	{ .compatible = "brcm,bcm4709-pinmux", .data = (void *)FLAG_BCM4709, }, | ||||||
|  | +	{ .compatible = "brcm,bcm53012-pinmux", .data = (void *)FLAG_BCM53012, }, | ||||||
|  | +	{ } | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static int ns_pinctrl_probe(struct platform_device *pdev) | ||||||
|  | +{ | ||||||
|  | +	struct device *dev = &pdev->dev; | ||||||
|  | +	const struct of_device_id *of_id; | ||||||
|  | +	struct ns_pinctrl *ns_pinctrl; | ||||||
|  | +	struct pinctrl_desc *pctldesc; | ||||||
|  | +	struct pinctrl_pin_desc *pin; | ||||||
|  | +	struct ns_pinctrl_group *group; | ||||||
|  | +	struct ns_pinctrl_function *function; | ||||||
|  | +	struct resource *res; | ||||||
|  | +	int i; | ||||||
|  | + | ||||||
|  | +	ns_pinctrl = devm_kzalloc(dev, sizeof(*ns_pinctrl), GFP_KERNEL); | ||||||
|  | +	if (!ns_pinctrl) | ||||||
|  | +		return -ENOMEM; | ||||||
|  | +	pctldesc = &ns_pinctrl->pctldesc; | ||||||
|  | +	platform_set_drvdata(pdev, ns_pinctrl); | ||||||
|  | + | ||||||
|  | +	/* Set basic properties */ | ||||||
|  | + | ||||||
|  | +	ns_pinctrl->dev = dev; | ||||||
|  | + | ||||||
|  | +	of_id = of_match_device(ns_pinctrl_of_match_table, dev); | ||||||
|  | +	if (!of_id) | ||||||
|  | +		return -EINVAL; | ||||||
|  | +	ns_pinctrl->chipset_flag = (unsigned int)of_id->data; | ||||||
|  | + | ||||||
|  | +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||||||
|  | +					   "cru_gpio_control"); | ||||||
|  | +	ns_pinctrl->base = devm_ioremap_resource(dev, res); | ||||||
|  | +	if (IS_ERR(ns_pinctrl->base)) { | ||||||
|  | +		dev_err(dev, "Failed to map pinctrl regs\n"); | ||||||
|  | +		return PTR_ERR(ns_pinctrl->base); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	memcpy(pctldesc, &ns_pinctrl_desc, sizeof(*pctldesc)); | ||||||
|  | + | ||||||
|  | +	/* Set pinctrl properties */ | ||||||
|  | + | ||||||
|  | +	pctldesc->pins = devm_kcalloc(dev, ARRAY_SIZE(ns_pinctrl_pins), | ||||||
|  | +				      sizeof(struct pinctrl_pin_desc), | ||||||
|  | +				      GFP_KERNEL); | ||||||
|  | +	if (!pctldesc->pins) | ||||||
|  | +		return -ENOMEM; | ||||||
|  | +	for (i = 0, pin = (struct pinctrl_pin_desc *)&pctldesc->pins[0]; | ||||||
|  | +	     i < ARRAY_SIZE(ns_pinctrl_pins); i++) { | ||||||
|  | +		const struct pinctrl_pin_desc *src = &ns_pinctrl_pins[i]; | ||||||
|  | +		unsigned int chipsets = (unsigned int)src->drv_data; | ||||||
|  | + | ||||||
|  | +		if (chipsets & ns_pinctrl->chipset_flag) { | ||||||
|  | +			memcpy(pin++, src, sizeof(*src)); | ||||||
|  | +			pctldesc->npins++; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	ns_pinctrl->groups = devm_kcalloc(dev, ARRAY_SIZE(ns_pinctrl_groups), | ||||||
|  | +					  sizeof(struct ns_pinctrl_group), | ||||||
|  | +					  GFP_KERNEL); | ||||||
|  | +	if (!ns_pinctrl->groups) | ||||||
|  | +		return -ENOMEM; | ||||||
|  | +	for (i = 0, group = &ns_pinctrl->groups[0]; | ||||||
|  | +	     i < ARRAY_SIZE(ns_pinctrl_groups); i++) { | ||||||
|  | +		const struct ns_pinctrl_group *src = &ns_pinctrl_groups[i]; | ||||||
|  | + | ||||||
|  | +		if (src->chipsets & ns_pinctrl->chipset_flag) { | ||||||
|  | +			memcpy(group++, src, sizeof(*src)); | ||||||
|  | +			ns_pinctrl->num_groups++; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	ns_pinctrl->functions = devm_kcalloc(dev, | ||||||
|  | +					     ARRAY_SIZE(ns_pinctrl_functions), | ||||||
|  | +					     sizeof(struct ns_pinctrl_function), | ||||||
|  | +					     GFP_KERNEL); | ||||||
|  | +	if (!ns_pinctrl->functions) | ||||||
|  | +		return -ENOMEM; | ||||||
|  | +	for (i = 0, function = &ns_pinctrl->functions[0]; | ||||||
|  | +	     i < ARRAY_SIZE(ns_pinctrl_functions); i++) { | ||||||
|  | +		const struct ns_pinctrl_function *src = &ns_pinctrl_functions[i]; | ||||||
|  | + | ||||||
|  | +		if (src->chipsets & ns_pinctrl->chipset_flag) { | ||||||
|  | +			memcpy(function++, src, sizeof(*src)); | ||||||
|  | +			ns_pinctrl->num_functions++; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* Register */ | ||||||
|  | + | ||||||
|  | +	ns_pinctrl->pctldev = devm_pinctrl_register(dev, pctldesc, ns_pinctrl); | ||||||
|  | +	if (IS_ERR(ns_pinctrl->pctldev)) { | ||||||
|  | +		dev_err(dev, "Failed to register pinctrl\n"); | ||||||
|  | +		return PTR_ERR(ns_pinctrl->pctldev); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static struct platform_driver ns_pinctrl_driver = { | ||||||
|  | +	.probe = ns_pinctrl_probe, | ||||||
|  | +	.driver = { | ||||||
|  | +		.name = "ns-pinmux", | ||||||
|  | +		.of_match_table = ns_pinctrl_of_match_table, | ||||||
|  | +	}, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +module_platform_driver(ns_pinctrl_driver); | ||||||
|  | + | ||||||
|  | +MODULE_AUTHOR("Rafał Miłecki"); | ||||||
|  | +MODULE_LICENSE("GPL v2"); | ||||||
|  | +MODULE_DEVICE_TABLE(of, ns_pinctrl_of_match_table); | ||||||
		Reference in New Issue
	
	Block a user
	 Rafał Miłecki
					Rafał Miłecki