Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7afeca1a authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge branch 'spear/pinctrl' into next/pinctrl



* spear/pinctrl:
  pinctrl: (cosmetic) fix two entries in DocBook comments
  pinctrl: add more info to error msgs in pin_request
  CLKDEV: provide helpers for common clock framework
  pinctrl: add pinctrl-mxs support
  pinctrl: pinctrl-imx: add imx6q pinctrl driver
  pinctrl: pinctrl-imx: add imx pinctrl core driver
  dt: add of_get_child_count helper function
  pinctrl: support gpio request deferred probing
  pinctrl: add pinctrl_provide_dummies interface for platforms to use
  pinctrl: enhance reporting of errors when loading from DT
  pinctrl: add kerneldoc for pinctrl_ops device tree functions
  pinctrl: propagate map validation errors
  pinctrl: fix dangling comment
  pinctrl: fix signed vs unsigned conditionals inside pinmux_map_to_setting
  ARM: 7392/1: CLKDEV: Optimize clk_find()
  ARM: 7376/1: clkdev: Implement managed clk_get()

This just adds more dependencies that are required in order not to
break the spear pinctrl support.

Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 4a0dfe69 366695ff
Loading
Loading
Loading
Loading
+95 −0
Original line number Diff line number Diff line
* Freescale IOMUX Controller (IOMUXC) for i.MX

The IOMUX Controller (IOMUXC), together with the IOMUX, enables the IC
to share one PAD to several functional blocks. The sharing is done by
multiplexing the PAD input/output signals. For each PAD there are up to
8 muxing options (called ALT modes). Since different modules require
different PAD settings (like pull up, keeper, etc) the IOMUXC controls
also the PAD settings parameters.

Please refer to pinctrl-bindings.txt in this directory for details of the
common pinctrl bindings used by client devices, including the meaning of the
phrase "pin configuration node".

Freescale IMX pin configuration node is a node of a group of pins which can be
used for a specific device or function. This node represents both mux and config
of the pins in that group. The 'mux' selects the function mode(also named mux
mode) this pin can work on and the 'config' configures various pad settings
such as pull-up, open drain, drive strength, etc.

Required properties for iomux controller:
- compatible: "fsl,<soc>-iomuxc"
  Please refer to each fsl,<soc>-pinctrl.txt binding doc for supported SoCs.

Required properties for pin configuration node:
- fsl,pins: two integers array, represents a group of pins mux and config
  setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
  pin working on a specific function, CONFIG is the pad setting value like
  pull-up on this pin. Please refer to fsl,<soc>-pinctrl.txt for the valid
  pins and functions of each SoC.

Bits used for CONFIG:
NO_PAD_CTL(1 << 31): indicate this pin does not need config.

SION(1 << 30): Software Input On Field.
Force the selected mux mode input path no matter of MUX_MODE functionality.
By default the input path is determined by functionality of the selected
mux mode (regular).

Other bits are used for PAD setting.
Please refer to each fsl,<soc>-pinctrl,txt binding doc for SoC specific part
of bits definitions.

NOTE:
Some requirements for using fsl,imx-pinctrl binding:
1. We have pin function node defined under iomux controller node to represent
   what pinmux functions this SoC supports.
2. The pin configuration node intends to work on a specific function should
   to be defined under that specific function node.
   The function node's name should represent well about what function
   this group of pins in this pin configuration node are working on.
3. The driver can use the function node's name and pin configuration node's
   name describe the pin function and group hierarchy.
   For example, Linux IMX pinctrl driver takes the function node's name
   as the function name and pin configuration node's name as group name to
   create the map table.
4. Each pin configuration node should have a phandle, devices can set pins
   configurations by referring to the phandle of that pin configuration node.

Examples:
usdhc@0219c000 { /* uSDHC4 */
	fsl,card-wired;
	vmmc-supply = <&reg_3p3v>;
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_usdhc4_1>;
};

iomuxc@020e0000 {
	compatible = "fsl,imx6q-iomuxc";
	reg = <0x020e0000 0x4000>;

	/* shared pinctrl settings */
	usdhc4 {
		pinctrl_usdhc4_1: usdhc4grp-1 {
			fsl,pins = <1386 0x17059	/* MX6Q_PAD_SD4_CMD__USDHC4_CMD */
				    1392 0x10059	/* MX6Q_PAD_SD4_CLK__USDHC4_CLK	*/
				    1462 0x17059	/* MX6Q_PAD_SD4_DAT0__USDHC4_DAT0 */
				    1470 0x17059	/* MX6Q_PAD_SD4_DAT1__USDHC4_DAT1 */
				    1478 0x17059	/* MX6Q_PAD_SD4_DAT2__USDHC4_DAT2 */
				    1486 0x17059	/* MX6Q_PAD_SD4_DAT3__USDHC4_DAT3 */
				    1493 0x17059	/* MX6Q_PAD_SD4_DAT4__USDHC4_DAT4 */
				    1501 0x17059	/* MX6Q_PAD_SD4_DAT5__USDHC4_DAT5 */
				    1509 0x17059	/* MX6Q_PAD_SD4_DAT6__USDHC4_DAT6 */
				    1517 0x17059>;	/* MX6Q_PAD_SD4_DAT7__USDHC4_DAT7 */
		};
	};
	....
};
Refer to the IOMUXC controller chapter in imx6q datasheet,
0x17059 means enable hysteresis, 47KOhm Pull Up, 50Mhz speed,
80Ohm driver strength and Fast Slew Rate.
User should refer to each SoC spec to set the correct value.

TODO: when dtc macro support is available, we can change above raw data
to dt macro which can get better readability in dts file.
+1628 −0

File added.

Preview size limit exceeded, changes collapsed.

+918 −0

File added.

Preview size limit exceeded, changes collapsed.

+4 −0
Original line number Diff line number Diff line
@@ -277,6 +277,10 @@ REGULATOR
  devm_regulator_put()
  devm_regulator_bulk_get()

CLOCK
  devm_clk_get()
  devm_clk_put()

PINCTRL
  devm_pinctrl_get()
  devm_pinctrl_put()
+132 −10
Original line number Diff line number Diff line
@@ -35,7 +35,12 @@ static DEFINE_MUTEX(clocks_mutex);
static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
{
	struct clk_lookup *p, *cl = NULL;
	int match, best = 0;
	int match, best_found = 0, best_possible = 0;

	if (dev_id)
		best_possible += 2;
	if (con_id)
		best_possible += 1;

	list_for_each_entry(p, &clocks, node) {
		match = 0;
@@ -50,10 +55,10 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
			match += 1;
		}

		if (match > best) {
		if (match > best_found) {
			cl = p;
			if (match != 3)
				best = match;
			if (match != best_possible)
				best_found = match;
			else
				break;
		}
@@ -89,6 +94,51 @@ void clk_put(struct clk *clk)
}
EXPORT_SYMBOL(clk_put);

static void devm_clk_release(struct device *dev, void *res)
{
	clk_put(*(struct clk **)res);
}

struct clk *devm_clk_get(struct device *dev, const char *id)
{
	struct clk **ptr, *clk;

	ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
	if (!ptr)
		return ERR_PTR(-ENOMEM);

	clk = clk_get(dev, id);
	if (!IS_ERR(clk)) {
		*ptr = clk;
		devres_add(dev, ptr);
	} else {
		devres_free(ptr);
	}

	return clk;
}
EXPORT_SYMBOL(devm_clk_get);

static int devm_clk_match(struct device *dev, void *res, void *data)
{
	struct clk **c = res;
	if (!c || !*c) {
		WARN_ON(!c || !*c);
		return 0;
	}
	return *c == data;
}

void devm_clk_put(struct device *dev, struct clk *clk)
{
	int ret;

	ret = devres_destroy(dev, devm_clk_release, devm_clk_match, clk);

	WARN_ON(ret);
}
EXPORT_SYMBOL(devm_clk_put);

void clkdev_add(struct clk_lookup *cl)
{
	mutex_lock(&clocks_mutex);
@@ -116,8 +166,9 @@ struct clk_lookup_alloc {
	char	con_id[MAX_CON_ID];
};

struct clk_lookup * __init_refok
clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
static struct clk_lookup * __init_refok
vclkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt,
	va_list ap)
{
	struct clk_lookup_alloc *cla;

@@ -132,16 +183,25 @@ clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
	}

	if (dev_fmt) {
		va_list ap;

		va_start(ap, dev_fmt);
		vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap);
		cla->cl.dev_id = cla->dev_id;
		va_end(ap);
	}

	return &cla->cl;
}

struct clk_lookup * __init_refok
clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
{
	struct clk_lookup *cl;
	va_list ap;

	va_start(ap, dev_fmt);
	cl = vclkdev_alloc(clk, con_id, dev_fmt, ap);
	va_end(ap);

	return cl;
}
EXPORT_SYMBOL(clkdev_alloc);

int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
@@ -173,3 +233,65 @@ void clkdev_drop(struct clk_lookup *cl)
	kfree(cl);
}
EXPORT_SYMBOL(clkdev_drop);

/**
 * clk_register_clkdev - register one clock lookup for a struct clk
 * @clk: struct clk to associate with all clk_lookups
 * @con_id: connection ID string on device
 * @dev_id: format string describing device name
 *
 * con_id or dev_id may be NULL as a wildcard, just as in the rest of
 * clkdev.
 *
 * To make things easier for mass registration, we detect error clks
 * from a previous clk_register() call, and return the error code for
 * those.  This is to permit this function to be called immediately
 * after clk_register().
 */
int clk_register_clkdev(struct clk *clk, const char *con_id,
	const char *dev_fmt, ...)
{
	struct clk_lookup *cl;
	va_list ap;

	if (IS_ERR(clk))
		return PTR_ERR(clk);

	va_start(ap, dev_fmt);
	cl = vclkdev_alloc(clk, con_id, dev_fmt, ap);
	va_end(ap);

	if (!cl)
		return -ENOMEM;

	clkdev_add(cl);

	return 0;
}

/**
 * clk_register_clkdevs - register a set of clk_lookup for a struct clk
 * @clk: struct clk to associate with all clk_lookups
 * @cl: array of clk_lookup structures with con_id and dev_id pre-initialized
 * @num: number of clk_lookup structures to register
 *
 * To make things easier for mass registration, we detect error clks
 * from a previous clk_register() call, and return the error code for
 * those.  This is to permit this function to be called immediately
 * after clk_register().
 */
int clk_register_clkdevs(struct clk *clk, struct clk_lookup *cl, size_t num)
{
	unsigned i;

	if (IS_ERR(clk))
		return PTR_ERR(clk);

	for (i = 0; i < num; i++, cl++) {
		cl->clk = clk;
		clkdev_add(cl);
	}

	return 0;
}
EXPORT_SYMBOL(clk_register_clkdevs);
Loading