[RFC] pinctrl: sh-pfc: Improve pinmux macros documentation
diff mbox

Message ID 1443017673-12311-1-git-send-email-geert+renesas@glider.be
State New
Headers show

Commit Message

Geert Uytterhoeven Sept. 23, 2015, 2:14 p.m. UTC
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Please review and comment!

  - I still have a hard time understanding the subtilties of the various
    PINMUX_IPSR_*() macros,
  - Which macro is most appropriate for describing single-function pins:
    PINMUX_DATA() or PINMUX_IPSR_NOGP()?
    (cfr. "[RFC] pinctrl: sh-pfc: r8a7795: Add pinmux data for
     single-function pins",
     http://www.spinics.net/lists/linux-sh/msg44823.html)

Thanks!
---
 drivers/pinctrl/sh-pfc/sh_pfc.h | 77 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 76 insertions(+), 1 deletion(-)

Comments

Kuninori Morimoto Sept. 30, 2015, 12:11 a.m. UTC | #1
Hi Geert

> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
> Please review and comment!
> 
>   - I still have a hard time understanding the subtilties of the various
>     PINMUX_IPSR_*() macros,
>   - Which macro is most appropriate for describing single-function pins:
>     PINMUX_DATA() or PINMUX_IPSR_NOGP()?
>     (cfr. "[RFC] pinctrl: sh-pfc: r8a7795: Add pinmux data for
>      single-function pins",
>      http://www.spinics.net/lists/linux-sh/msg44823.html

I don't care about this, but my point was that I don't like
directly using xxx_MARK in pinmux_data[] (it looks like different style).
And it already had PINMUX_IPSR_NOGP() list in end of pinmux_data[]

> +/*
> + * Describe a pinmux configuration without GPIO function that needs
> + * configuration in a Peripheral Function Select Register (IPSR)
> + *   - ipsr: IPSR field (unused, for documentation purposes only)
> + *   - fn: Function name
> + */
>  #define PINMUX_IPSR_NOGP(ispr, fn)					\
>  	PINMUX_DATA(fn##_MARK, FN_##fn)
(snip)
> +/*
> + * Describe a pinmux configuration where ???
> + *   - ipsr: IPSR field
> + *   - fn: Function name
> + *   - ms: Configuration register selector
> + */
>  #define PINMUX_IPSR_NOGM(ispr, fn, ms)					\
>  	PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ms)

I forgot detail, but this NOGM = NOGP + MSEL
It doesn't need GP settings, but need SEL_xxx
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Laurent Pinchart Oct. 1, 2015, 2:21 p.m. UTC | #2
Hi Geert,

Thank you for the patch. This was much needed.

On Wednesday 23 September 2015 16:14:33 Geert Uytterhoeven wrote:
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
> Please review and comment!
> 
>   - I still have a hard time understanding the subtilties of the various
>     PINMUX_IPSR_*() macros,

So do we all :-)

>   - Which macro is most appropriate for describing single-function pins:
>     PINMUX_DATA() or PINMUX_IPSR_NOGP()?
>     (cfr. "[RFC] pinctrl: sh-pfc: r8a7795: Add pinmux data for
>      single-function pins",
>      http://www.spinics.net/lists/linux-sh/msg44823.html)
> 
> Thanks!
> ---
>  drivers/pinctrl/sh-pfc/sh_pfc.h | 77 +++++++++++++++++++++++++++++++++++++-
>  1 file changed, 76 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h
> b/drivers/pinctrl/sh-pfc/sh_pfc.h index e18e306b4ac276c7..434209c8e22e72fc
> 100644
> --- a/drivers/pinctrl/sh-pfc/sh_pfc.h
> +++ b/drivers/pinctrl/sh-pfc/sh_pfc.h
> @@ -95,10 +95,31 @@ struct pinmux_cfg_reg {
>  	const u8 *var_field_width;
>  };
> 
> +/*
> + * Describe a config register consisting of multiple fixed-width fields

Slightly nitpicking: instead of fixed-width I'd say

"Describe a config register consisting of several fields of the same width"

This is more important for the variable-width fields in the documentation of 
the PINMUX_CFG_REG_VAR macro, as variable-width could be understood as fields 
which length varies at runtime. For that register I would say

"Describe a config register consisting of several fields of different widths"

Feel free to ignore this comment if you think it's overkill.

> + *   - name: Register name (unused, for documentation purposes only)
> + *   - r: Physical register address
> + *   - r_width: Width of the register (in bits)
> + *   - f_width: Width of the fixed-width register fields (in bits)
> + * This macro must be followed by initialization data: For each register
> field
> + * (from left to right, i.e. MSB to LSB), 2^f_width enum IDs must be
> specified,
> + * one for each possible combination of the register field bit values.
> + */
>  #define PINMUX_CFG_REG(name, r, r_width, f_width) \
>  	.reg = r, .reg_width = r_width, .field_width = f_width,		\
>  	.enum_ids = (const u16 [(r_width / f_width) * (1 << f_width)])
> 
> +/*
> + * Describe a config register consisting of multiple variable-width fields
> + *   - name: Register name (unused, for documentation purposes only)
> + *   - r: Physical register address
> + *   - r_width: Width of the register (in bits)
> + *   - var_fw0, var_fwn...: List of widths of the register fields (in
> bits),
> + *                          From left to right (i.e. MSB to LSB)
> + * This macro must be followed by initialization data: For each register
> field
> + * (from left to right, i.e. MSB to LSB), 2^var_fwi enum IDs must be
> specified,
> + * one for each possible combination of the register field bit values.
> + */
>  #define PINMUX_CFG_REG_VAR(name, r, r_width, var_fw0, var_fwn...) \
>  	.reg = r, .reg_width = r_width,	\
>  	.var_field_width = (const u8 [r_width]) \
> @@ -111,6 +132,14 @@ struct pinmux_data_reg {
>  	const u16 *enum_ids;
>  };
> 
> +/*
> + * Describe a data register
> + *   - name: Register name (unused, for documentation purposes only)
> + *   - r: Physical register address
> + *   - r_width: Width of the register (in bits)
> + * This macro must be followed by initialization data: For each register
> bit
> + * (from left to right, i.e. MSB to LSB), one enum ID must be specified.
> + */
>  #define PINMUX_DATA_REG(name, r, r_width) \
>  	.reg = r, .reg_width = r_width,	\
>  	.enum_ids = (const u16 [r_width]) \
> @@ -119,6 +148,10 @@ struct pinmux_irq {
>  	const short *gpios;
>  };
> 
> +/*
> + * Describe the mapping from GPIOs to a single IRQ
> + *   - ids...: List of GPIOs that are mapped to the same IRQ
> + */
>  #define PINMUX_IRQ(ids...)			   \
>  	{ .gpios = (const short []) { ids, -1 } }
> 
> @@ -180,16 +213,58 @@ struct sh_pfc_soc_info {
>   * sh_pfc_soc_info pinmux_data array macros
>   */
> 
> +/*
> + * Describe generic pinmux data
> + *   - data_or_mark: *_DATA or *_MARK enum ID
> + *   - ids...: List of enum IDs to associate with data_or_mark
> + */
>  #define PINMUX_DATA(data_or_mark, ids...)	data_or_mark, ids, 0
> 
> +/*
> + * Describe a pinmux configuration without GPIO function that needs
> + * configuration in a Peripheral Function Select Register (IPSR)
> + *   - ipsr: IPSR field (unused, for documentation purposes only)
> + *   - fn: Function name
> + */
>  #define PINMUX_IPSR_NOGP(ispr, fn)					\

While you're at it, could you s/ispr/ipsr/ ?

>  	PINMUX_DATA(fn##_MARK, FN_##fn)
> +
> +/*
> + * Describe a pinmux configuration with GPIO function that needs
> configuration
> + * in a Peripheral Function Select Register (IPSR)
> + *   - ipsr: IPSR field
> + *   - fn: Function name
> + */
>  #define PINMUX_IPSR_DATA(ipsr, fn)					\
>  	PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ipsr)

This one is confusing. While ipsr refers to the name of an IPSR field, that's 
for documentation purpose only (the IPSR fields are not named in the code but 
they're mentioned in comments in the IPSR register definitions). After 
expansion FN_##ipsr refers to a field value of a GSPR register. For instance

	PINMUX_IPSR_DATA(IP0_0, D0)

will expand to

	D0_MARK, FN_D0, FN_IP0_0

When applying that configuration FN_D0 will set the IPSR bits to select the D0 
function, while FN_IP0_0 will set the GSPR bits to set the pin mux to function 
instead of GPIO.

I wonder whether we should rename the macros to make their purpose clearer. 
This one should really convey the above meaning explicitly using a name that 
shows that both a GPIO/function mux and a function selector mux are used.

> +
> +/*
> + * Describe a pinmux configuration where ???
> + *   - ipsr: IPSR field
> + *   - fn: Function name
> + *   - ms: Configuration register selector
> + */
>  #define PINMUX_IPSR_NOGM(ispr, fn, ms)					\
>  	PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ms)

MSEL adds another muxing level that muxes modules as a whole instead of 
individual pins. I'm not sure exactly how it's wired up at the hardware level. 
It would be interesting to find out the exact hardware structure of the pin 
muxes to hopefully better name (and possibly structure) the driver constructs.

PINMUX_IPSR_NOGM really means PINMUX_IPSR_NOGP_MSEL, but that would be longer.

> +/*
> + * Describe a pinmux configuration where the pinmux function has no
> + * representation in the configuration registers but instead solely
> + * depends on a group selection.
> + *   - ipsr: IPSR field
> + *   - fn: Function name
> + *   - ms: Group selector
> + */
>  #define PINMUX_IPSR_NOFN(ipsr, fn, ms)					\
>  	PINMUX_DATA(fn##_MARK, FN_##ipsr, FN_##ms)

That macro is used by EMEV2 only. Maybe we could move it there.

> +/*
> + * Describe a pinmux configuration where the pinmux function has a
> + * representation in a configuration register.
> + *   - ipsr: IPSR field
> + *   - fn: Function name
> + *   - ms: Configuration register selector
> + */
>  #define PINMUX_IPSR_MSEL(ipsr, fn, ms)					\
>  	PINMUX_DATA(fn##_MARK, FN_##ms, FN_##ipsr, FN_##fn)
> 
> @@ -322,7 +397,7 @@ struct sh_pfc_soc_info {
>  	PINMUX_GPIO_FN(GPIO_FN_##str, PINMUX_FN_BASE, str##_MARK)
> 
>  /*
> - * PORTnCR macro
> + * PORTnCR helper macro for SH-Mobile/R-Mobile
>   */
>  #define PORTCR(nr, reg)							\
>  	{								\

Patch
diff mbox

diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h
index e18e306b4ac276c7..434209c8e22e72fc 100644
--- a/drivers/pinctrl/sh-pfc/sh_pfc.h
+++ b/drivers/pinctrl/sh-pfc/sh_pfc.h
@@ -95,10 +95,31 @@  struct pinmux_cfg_reg {
 	const u8 *var_field_width;
 };
 
+/*
+ * Describe a config register consisting of multiple fixed-width fields
+ *   - name: Register name (unused, for documentation purposes only)
+ *   - r: Physical register address
+ *   - r_width: Width of the register (in bits)
+ *   - f_width: Width of the fixed-width register fields (in bits)
+ * This macro must be followed by initialization data: For each register field
+ * (from left to right, i.e. MSB to LSB), 2^f_width enum IDs must be specified,
+ * one for each possible combination of the register field bit values.
+ */
 #define PINMUX_CFG_REG(name, r, r_width, f_width) \
 	.reg = r, .reg_width = r_width, .field_width = f_width,		\
 	.enum_ids = (const u16 [(r_width / f_width) * (1 << f_width)])
 
+/*
+ * Describe a config register consisting of multiple variable-width fields
+ *   - name: Register name (unused, for documentation purposes only)
+ *   - r: Physical register address
+ *   - r_width: Width of the register (in bits)
+ *   - var_fw0, var_fwn...: List of widths of the register fields (in bits),
+ *                          From left to right (i.e. MSB to LSB)
+ * This macro must be followed by initialization data: For each register field
+ * (from left to right, i.e. MSB to LSB), 2^var_fwi enum IDs must be specified,
+ * one for each possible combination of the register field bit values.
+ */
 #define PINMUX_CFG_REG_VAR(name, r, r_width, var_fw0, var_fwn...) \
 	.reg = r, .reg_width = r_width,	\
 	.var_field_width = (const u8 [r_width]) \
@@ -111,6 +132,14 @@  struct pinmux_data_reg {
 	const u16 *enum_ids;
 };
 
+/*
+ * Describe a data register
+ *   - name: Register name (unused, for documentation purposes only)
+ *   - r: Physical register address
+ *   - r_width: Width of the register (in bits)
+ * This macro must be followed by initialization data: For each register bit
+ * (from left to right, i.e. MSB to LSB), one enum ID must be specified.
+ */
 #define PINMUX_DATA_REG(name, r, r_width) \
 	.reg = r, .reg_width = r_width,	\
 	.enum_ids = (const u16 [r_width]) \
@@ -119,6 +148,10 @@  struct pinmux_irq {
 	const short *gpios;
 };
 
+/*
+ * Describe the mapping from GPIOs to a single IRQ
+ *   - ids...: List of GPIOs that are mapped to the same IRQ
+ */
 #define PINMUX_IRQ(ids...)			   \
 	{ .gpios = (const short []) { ids, -1 } }
 
@@ -180,16 +213,58 @@  struct sh_pfc_soc_info {
  * sh_pfc_soc_info pinmux_data array macros
  */
 
+/*
+ * Describe generic pinmux data
+ *   - data_or_mark: *_DATA or *_MARK enum ID
+ *   - ids...: List of enum IDs to associate with data_or_mark
+ */
 #define PINMUX_DATA(data_or_mark, ids...)	data_or_mark, ids, 0
 
+/*
+ * Describe a pinmux configuration without GPIO function that needs
+ * configuration in a Peripheral Function Select Register (IPSR)
+ *   - ipsr: IPSR field (unused, for documentation purposes only)
+ *   - fn: Function name
+ */
 #define PINMUX_IPSR_NOGP(ispr, fn)					\
 	PINMUX_DATA(fn##_MARK, FN_##fn)
+
+/*
+ * Describe a pinmux configuration with GPIO function that needs configuration
+ * in a Peripheral Function Select Register (IPSR)
+ *   - ipsr: IPSR field
+ *   - fn: Function name
+ */
 #define PINMUX_IPSR_DATA(ipsr, fn)					\
 	PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ipsr)
+
+/*
+ * Describe a pinmux configuration where ???
+ *   - ipsr: IPSR field
+ *   - fn: Function name
+ *   - ms: Configuration register selector
+ */
 #define PINMUX_IPSR_NOGM(ispr, fn, ms)					\
 	PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ms)
+
+/*
+ * Describe a pinmux configuration where the pinmux function has no
+ * representation in the configuration registers but instead solely
+ * depends on a group selection.
+ *   - ipsr: IPSR field
+ *   - fn: Function name
+ *   - ms: Group selector
+ */
 #define PINMUX_IPSR_NOFN(ipsr, fn, ms)					\
 	PINMUX_DATA(fn##_MARK, FN_##ipsr, FN_##ms)
+
+/*
+ * Describe a pinmux configuration where the pinmux function has a
+ * representation in a configuration register.
+ *   - ipsr: IPSR field
+ *   - fn: Function name
+ *   - ms: Configuration register selector
+ */
 #define PINMUX_IPSR_MSEL(ipsr, fn, ms)					\
 	PINMUX_DATA(fn##_MARK, FN_##ms, FN_##ipsr, FN_##fn)
 
@@ -322,7 +397,7 @@  struct sh_pfc_soc_info {
 	PINMUX_GPIO_FN(GPIO_FN_##str, PINMUX_FN_BASE, str##_MARK)
 
 /*
- * PORTnCR macro
+ * PORTnCR helper macro for SH-Mobile/R-Mobile
  */
 #define PORTCR(nr, reg)							\
 	{								\