Message ID | 20230331112941.823410-4-danishanwar@ti.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Introduce PRU platform consumer API | expand |
On Fri, Mar 31, 2023 at 04:59:40PM +0530, MD Danish Anwar wrote: > From: Suman Anna <s-anna@ti.com> > > Add two new generic API pruss_cfg_read() and pruss_cfg_update() to > the PRUSS platform driver to read and program respectively a register > within the PRUSS CFG sub-module represented by a syscon driver. These > APIs are internal to PRUSS driver. > > Add two new helper functions pruss_cfg_get_gpmux() & pruss_cfg_set_gpmux() > to get and set the GP MUX mode for programming the PRUSS internal wrapper > mux functionality as needed by usecases. > > Various useful registers and macros for certain register bit-fields and > their values have also been added. > > Signed-off-by: Suman Anna <s-anna@ti.com> > Co-developed-by: Grzegorz Jaszczyk <grzegorz.jaszczyk@linaro.org> > Signed-off-by: Grzegorz Jaszczyk <grzegorz.jaszczyk@linaro.org> > Signed-off-by: Puranjay Mohan <p-mohan@ti.com> > Reviewed-by: Roger Quadros <rogerq@kernel.org> > Reviewed-by: Tony Lindgren <tony@atomide.com> > Signed-off-by: MD Danish Anwar <danishanwar@ti.com> ... > diff --git a/drivers/soc/ti/pruss.h b/drivers/soc/ti/pruss.h > new file mode 100644 > index 000000000000..4626d5f6b874 > --- /dev/null > +++ b/drivers/soc/ti/pruss.h > @@ -0,0 +1,112 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* > + * PRU-ICSS Subsystem user interfaces > + * > + * Copyright (C) 2015-2023 Texas Instruments Incorporated - http://www.ti.com > + * MD Danish Anwar <danishanwar@ti.com> > + */ > + > +#ifndef _SOC_TI_PRUSS_H_ > +#define _SOC_TI_PRUSS_H_ > + > +#include <linux/bits.h> > +#include <linux/regmap.h> > + > +/* > + * PRU_ICSS_CFG registers > + * SYSCFG, ISRP, ISP, IESP, IECP, SCRP applicable on AMxxxx devices only > + */ > +#define PRUSS_CFG_REVID 0x00 > +#define PRUSS_CFG_SYSCFG 0x04 > +#define PRUSS_CFG_GPCFG(x) (0x08 + (x) * 4) > +#define PRUSS_CFG_CGR 0x10 > +#define PRUSS_CFG_ISRP 0x14 > +#define PRUSS_CFG_ISP 0x18 > +#define PRUSS_CFG_IESP 0x1C > +#define PRUSS_CFG_IECP 0x20 > +#define PRUSS_CFG_SCRP 0x24 > +#define PRUSS_CFG_PMAO 0x28 > +#define PRUSS_CFG_MII_RT 0x2C > +#define PRUSS_CFG_IEPCLK 0x30 > +#define PRUSS_CFG_SPP 0x34 > +#define PRUSS_CFG_PIN_MX 0x40 > + > +/* PRUSS_GPCFG register bits */ > +#define PRUSS_GPCFG_PRU_GPO_SH_SEL BIT(25) > + > +#define PRUSS_GPCFG_PRU_DIV1_SHIFT 20 > +#define PRUSS_GPCFG_PRU_DIV1_MASK GENMASK(24, 20) There seems to be some redundancy in the encoding of '20' above. I suspect this could be avoided by only defining ..._MASK and using it with FIELD_SET() and FIELD_PREP(). > + > +#define PRUSS_GPCFG_PRU_DIV0_SHIFT 15 > +#define PRUSS_GPCFG_PRU_DIV0_MASK GENMASK(15, 19) Perhaps this should be GENMASK(19, 15) ? > + > +#define PRUSS_GPCFG_PRU_GPO_MODE BIT(14) > +#define PRUSS_GPCFG_PRU_GPO_MODE_DIRECT 0 > +#define PRUSS_GPCFG_PRU_GPO_MODE_SERIAL BIT(14) Likewise, I suspect the awkwardness of using 0 to mean not BIT 14 could be avoided through use of FIELD_SET() and FIELD_PREP(). But maybe it doesn't help. > + > +#define PRUSS_GPCFG_PRU_GPI_SB BIT(13) > + > +#define PRUSS_GPCFG_PRU_GPI_DIV1_SHIFT 8 > +#define PRUSS_GPCFG_PRU_GPI_DIV1_MASK GENMASK(12, 8) > + > +#define PRUSS_GPCFG_PRU_GPI_DIV0_SHIFT 3 > +#define PRUSS_GPCFG_PRU_GPI_DIV0_MASK GENMASK(7, 3) > + > +#define PRUSS_GPCFG_PRU_GPI_CLK_MODE_POSITIVE 0 > +#define PRUSS_GPCFG_PRU_GPI_CLK_MODE_NEGATIVE BIT(2) > +#define PRUSS_GPCFG_PRU_GPI_CLK_MODE BIT(2) > + > +#define PRUSS_GPCFG_PRU_GPI_MODE_MASK GENMASK(1, 0) > +#define PRUSS_GPCFG_PRU_GPI_MODE_SHIFT 0 > + > +#define PRUSS_GPCFG_PRU_MUX_SEL_SHIFT 26 > +#define PRUSS_GPCFG_PRU_MUX_SEL_MASK GENMASK(29, 26) > + > +/* PRUSS_MII_RT register bits */ > +#define PRUSS_MII_RT_EVENT_EN BIT(0) > + > +/* PRUSS_SPP register bits */ > +#define PRUSS_SPP_XFER_SHIFT_EN BIT(1) > +#define PRUSS_SPP_PRU1_PAD_HP_EN BIT(0) > +#define PRUSS_SPP_RTU_XFR_SHIFT_EN BIT(3) ...
Hi Simon, On 01/04/23 19:37, Simon Horman wrote: > On Fri, Mar 31, 2023 at 04:59:40PM +0530, MD Danish Anwar wrote: >> From: Suman Anna <s-anna@ti.com> >> >> Add two new generic API pruss_cfg_read() and pruss_cfg_update() to >> the PRUSS platform driver to read and program respectively a register >> within the PRUSS CFG sub-module represented by a syscon driver. These >> APIs are internal to PRUSS driver. >> >> Add two new helper functions pruss_cfg_get_gpmux() & pruss_cfg_set_gpmux() >> to get and set the GP MUX mode for programming the PRUSS internal wrapper >> mux functionality as needed by usecases. >> >> Various useful registers and macros for certain register bit-fields and >> their values have also been added. >> >> Signed-off-by: Suman Anna <s-anna@ti.com> >> Co-developed-by: Grzegorz Jaszczyk <grzegorz.jaszczyk@linaro.org> >> Signed-off-by: Grzegorz Jaszczyk <grzegorz.jaszczyk@linaro.org> >> Signed-off-by: Puranjay Mohan <p-mohan@ti.com> >> Reviewed-by: Roger Quadros <rogerq@kernel.org> >> Reviewed-by: Tony Lindgren <tony@atomide.com> >> Signed-off-by: MD Danish Anwar <danishanwar@ti.com> > > ... > >> diff --git a/drivers/soc/ti/pruss.h b/drivers/soc/ti/pruss.h >> new file mode 100644 >> index 000000000000..4626d5f6b874 >> --- /dev/null >> +++ b/drivers/soc/ti/pruss.h >> @@ -0,0 +1,112 @@ >> +/* SPDX-License-Identifier: GPL-2.0-only */ >> +/* >> + * PRU-ICSS Subsystem user interfaces >> + * >> + * Copyright (C) 2015-2023 Texas Instruments Incorporated - http://www.ti.com >> + * MD Danish Anwar <danishanwar@ti.com> >> + */ >> + >> +#ifndef _SOC_TI_PRUSS_H_ >> +#define _SOC_TI_PRUSS_H_ >> + >> +#include <linux/bits.h> >> +#include <linux/regmap.h> >> + >> +/* >> + * PRU_ICSS_CFG registers >> + * SYSCFG, ISRP, ISP, IESP, IECP, SCRP applicable on AMxxxx devices only >> + */ >> +#define PRUSS_CFG_REVID 0x00 >> +#define PRUSS_CFG_SYSCFG 0x04 >> +#define PRUSS_CFG_GPCFG(x) (0x08 + (x) * 4) >> +#define PRUSS_CFG_CGR 0x10 >> +#define PRUSS_CFG_ISRP 0x14 >> +#define PRUSS_CFG_ISP 0x18 >> +#define PRUSS_CFG_IESP 0x1C >> +#define PRUSS_CFG_IECP 0x20 >> +#define PRUSS_CFG_SCRP 0x24 >> +#define PRUSS_CFG_PMAO 0x28 >> +#define PRUSS_CFG_MII_RT 0x2C >> +#define PRUSS_CFG_IEPCLK 0x30 >> +#define PRUSS_CFG_SPP 0x34 >> +#define PRUSS_CFG_PIN_MX 0x40 >> + >> +/* PRUSS_GPCFG register bits */ >> +#define PRUSS_GPCFG_PRU_GPO_SH_SEL BIT(25) >> + >> +#define PRUSS_GPCFG_PRU_DIV1_SHIFT 20 >> +#define PRUSS_GPCFG_PRU_DIV1_MASK GENMASK(24, 20) > > There seems to be some redundancy in the encoding of '20' above. > I suspect this could be avoided by only defining ..._MASK > and using it with FIELD_SET() and FIELD_PREP(). > >> + >> +#define PRUSS_GPCFG_PRU_DIV0_SHIFT 15 >> +#define PRUSS_GPCFG_PRU_DIV0_MASK GENMASK(15, 19) > > Perhaps this should be GENMASK(19, 15) ? > yes this should have been GENMASK(15, 19). But this macro is not used anywhere so I'll just drop it. >> + >> +#define PRUSS_GPCFG_PRU_GPO_MODE BIT(14) >> +#define PRUSS_GPCFG_PRU_GPO_MODE_DIRECT 0 >> +#define PRUSS_GPCFG_PRU_GPO_MODE_SERIAL BIT(14) > > Likewise, I suspect the awkwardness of using 0 to mean not BIT 14 > could be avoided through use of FIELD_SET() and FIELD_PREP(). > But maybe it doesn't help. > This Macro is not used anywhere in code. I'll just drop them. >> + >> +#define PRUSS_GPCFG_PRU_GPI_SB BIT(13) >> + >> +#define PRUSS_GPCFG_PRU_GPI_DIV1_SHIFT 8 >> +#define PRUSS_GPCFG_PRU_GPI_DIV1_MASK GENMASK(12, 8) >> + >> +#define PRUSS_GPCFG_PRU_GPI_DIV0_SHIFT 3 >> +#define PRUSS_GPCFG_PRU_GPI_DIV0_MASK GENMASK(7, 3) >> + >> +#define PRUSS_GPCFG_PRU_GPI_CLK_MODE_POSITIVE 0 >> +#define PRUSS_GPCFG_PRU_GPI_CLK_MODE_NEGATIVE BIT(2) >> +#define PRUSS_GPCFG_PRU_GPI_CLK_MODE BIT(2) >> + All these above macros are not used anywhere in the driver code. Also in the planned upcoming driver series, there are no APIs that will use these macros. I'll be dropping all these redundant macros. The below macros are used in driver so I'll keep them as it is. >> +#define PRUSS_GPCFG_PRU_GPI_MODE_MASK GENMASK(1, 0) >> +#define PRUSS_GPCFG_PRU_GPI_MODE_SHIFT 0 >> + >> +#define PRUSS_GPCFG_PRU_MUX_SEL_SHIFT 26 >> +#define PRUSS_GPCFG_PRU_MUX_SEL_MASK GENMASK(29, 26) >> + >> +/* PRUSS_MII_RT register bits */ >> +#define PRUSS_MII_RT_EVENT_EN BIT(0) >> + >> +/* PRUSS_SPP register bits */ >> +#define PRUSS_SPP_XFER_SHIFT_EN BIT(1) >> +#define PRUSS_SPP_PRU1_PAD_HP_EN BIT(0) >> +#define PRUSS_SPP_RTU_XFR_SHIFT_EN BIT(3) > > ...
On Mon, Apr 03, 2023 at 02:01:44PM +0530, Md Danish Anwar wrote: > Hi Simon, > > On 01/04/23 19:37, Simon Horman wrote: > > On Fri, Mar 31, 2023 at 04:59:40PM +0530, MD Danish Anwar wrote: > >> From: Suman Anna <s-anna@ti.com> ... > All these above macros are not used anywhere in the driver code. Also in the > planned upcoming driver series, there are no APIs that will use these macros. > > I'll be dropping all these redundant macros. The below macros are used in > driver so I'll keep them as it is. Thanks Danish, Dropping unused things seems like a good idea to me.
diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index 7aa0f7171af1..0e37fe142615 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -21,6 +21,7 @@ #include <linux/regmap.h> #include <linux/remoteproc.h> #include <linux/slab.h> +#include "pruss.h" /** * struct pruss_private_data - PRUSS driver private data @@ -168,6 +169,50 @@ int pruss_release_mem_region(struct pruss *pruss, } EXPORT_SYMBOL_GPL(pruss_release_mem_region); +/** + * pruss_cfg_get_gpmux() - get the current GPMUX value for a PRU device + * @pruss: pruss instance + * @pru_id: PRU identifier (0-1) + * @mux: pointer to store the current mux value into + * + * Return: 0 on success, or an error code otherwise + */ +int pruss_cfg_get_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 *mux) +{ + int ret = 0; + u32 val; + + if (pru_id < 0 || pru_id >= PRUSS_NUM_PRUS || !mux) + return -EINVAL; + + ret = pruss_cfg_read(pruss, PRUSS_CFG_GPCFG(pru_id), &val); + if (!ret) + *mux = (u8)((val & PRUSS_GPCFG_PRU_MUX_SEL_MASK) >> + PRUSS_GPCFG_PRU_MUX_SEL_SHIFT); + return ret; +} +EXPORT_SYMBOL_GPL(pruss_cfg_get_gpmux); + +/** + * pruss_cfg_set_gpmux() - set the GPMUX value for a PRU device + * @pruss: pruss instance + * @pru_id: PRU identifier (0-1) + * @mux: new mux value for PRU + * + * Return: 0 on success, or an error code otherwise + */ +int pruss_cfg_set_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 mux) +{ + if (mux >= PRUSS_GP_MUX_SEL_MAX || + pru_id < 0 || pru_id >= PRUSS_NUM_PRUS) + return -EINVAL; + + return pruss_cfg_update(pruss, PRUSS_CFG_GPCFG(pru_id), + PRUSS_GPCFG_PRU_MUX_SEL_MASK, + (u32)mux << PRUSS_GPCFG_PRU_MUX_SEL_SHIFT); +} +EXPORT_SYMBOL_GPL(pruss_cfg_set_gpmux); + static void pruss_of_free_clk_provider(void *data) { struct device_node *clk_mux_np = data; diff --git a/drivers/soc/ti/pruss.h b/drivers/soc/ti/pruss.h new file mode 100644 index 000000000000..4626d5f6b874 --- /dev/null +++ b/drivers/soc/ti/pruss.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * PRU-ICSS Subsystem user interfaces + * + * Copyright (C) 2015-2023 Texas Instruments Incorporated - http://www.ti.com + * MD Danish Anwar <danishanwar@ti.com> + */ + +#ifndef _SOC_TI_PRUSS_H_ +#define _SOC_TI_PRUSS_H_ + +#include <linux/bits.h> +#include <linux/regmap.h> + +/* + * PRU_ICSS_CFG registers + * SYSCFG, ISRP, ISP, IESP, IECP, SCRP applicable on AMxxxx devices only + */ +#define PRUSS_CFG_REVID 0x00 +#define PRUSS_CFG_SYSCFG 0x04 +#define PRUSS_CFG_GPCFG(x) (0x08 + (x) * 4) +#define PRUSS_CFG_CGR 0x10 +#define PRUSS_CFG_ISRP 0x14 +#define PRUSS_CFG_ISP 0x18 +#define PRUSS_CFG_IESP 0x1C +#define PRUSS_CFG_IECP 0x20 +#define PRUSS_CFG_SCRP 0x24 +#define PRUSS_CFG_PMAO 0x28 +#define PRUSS_CFG_MII_RT 0x2C +#define PRUSS_CFG_IEPCLK 0x30 +#define PRUSS_CFG_SPP 0x34 +#define PRUSS_CFG_PIN_MX 0x40 + +/* PRUSS_GPCFG register bits */ +#define PRUSS_GPCFG_PRU_GPO_SH_SEL BIT(25) + +#define PRUSS_GPCFG_PRU_DIV1_SHIFT 20 +#define PRUSS_GPCFG_PRU_DIV1_MASK GENMASK(24, 20) + +#define PRUSS_GPCFG_PRU_DIV0_SHIFT 15 +#define PRUSS_GPCFG_PRU_DIV0_MASK GENMASK(15, 19) + +#define PRUSS_GPCFG_PRU_GPO_MODE BIT(14) +#define PRUSS_GPCFG_PRU_GPO_MODE_DIRECT 0 +#define PRUSS_GPCFG_PRU_GPO_MODE_SERIAL BIT(14) + +#define PRUSS_GPCFG_PRU_GPI_SB BIT(13) + +#define PRUSS_GPCFG_PRU_GPI_DIV1_SHIFT 8 +#define PRUSS_GPCFG_PRU_GPI_DIV1_MASK GENMASK(12, 8) + +#define PRUSS_GPCFG_PRU_GPI_DIV0_SHIFT 3 +#define PRUSS_GPCFG_PRU_GPI_DIV0_MASK GENMASK(7, 3) + +#define PRUSS_GPCFG_PRU_GPI_CLK_MODE_POSITIVE 0 +#define PRUSS_GPCFG_PRU_GPI_CLK_MODE_NEGATIVE BIT(2) +#define PRUSS_GPCFG_PRU_GPI_CLK_MODE BIT(2) + +#define PRUSS_GPCFG_PRU_GPI_MODE_MASK GENMASK(1, 0) +#define PRUSS_GPCFG_PRU_GPI_MODE_SHIFT 0 + +#define PRUSS_GPCFG_PRU_MUX_SEL_SHIFT 26 +#define PRUSS_GPCFG_PRU_MUX_SEL_MASK GENMASK(29, 26) + +/* PRUSS_MII_RT register bits */ +#define PRUSS_MII_RT_EVENT_EN BIT(0) + +/* PRUSS_SPP register bits */ +#define PRUSS_SPP_XFER_SHIFT_EN BIT(1) +#define PRUSS_SPP_PRU1_PAD_HP_EN BIT(0) +#define PRUSS_SPP_RTU_XFR_SHIFT_EN BIT(3) + +/** + * pruss_cfg_read() - read a PRUSS CFG sub-module register + * @pruss: the pruss instance handle + * @reg: register offset within the CFG sub-module + * @val: pointer to return the value in + * + * Reads a given register within the PRUSS CFG sub-module and + * returns it through the passed-in @val pointer + * + * Return: 0 on success, or an error code otherwise + */ +static int pruss_cfg_read(struct pruss *pruss, unsigned int reg, unsigned int *val) +{ + if (IS_ERR_OR_NULL(pruss)) + return -EINVAL; + + return regmap_read(pruss->cfg_regmap, reg, val); +} + +/** + * pruss_cfg_update() - configure a PRUSS CFG sub-module register + * @pruss: the pruss instance handle + * @reg: register offset within the CFG sub-module + * @mask: bit mask to use for programming the @val + * @val: value to write + * + * Programs a given register within the PRUSS CFG sub-module + * + * Return: 0 on success, or an error code otherwise + */ +static int pruss_cfg_update(struct pruss *pruss, unsigned int reg, + unsigned int mask, unsigned int val) +{ + if (IS_ERR_OR_NULL(pruss)) + return -EINVAL; + + return regmap_update_bits(pruss->cfg_regmap, reg, mask, val); +} + +#endif /* _SOC_TI_PRUSS_H_ */ diff --git a/include/linux/remoteproc/pruss.h b/include/linux/remoteproc/pruss.h index 33f930e0a0ce..5641153459a7 100644 --- a/include/linux/remoteproc/pruss.h +++ b/include/linux/remoteproc/pruss.h @@ -16,6 +16,24 @@ #define PRU_RPROC_DRVNAME "pru-rproc" +/* + * enum pruss_gp_mux_sel - PRUSS GPI/O Mux modes for the + * PRUSS_GPCFG0/1 registers + * + * NOTE: The below defines are the most common values, but there + * are some exceptions like on 66AK2G, where the RESERVED and MII2 + * values are interchanged. Also, this bit-field does not exist on + * AM335x SoCs + */ +enum pruss_gp_mux_sel { + PRUSS_GP_MUX_SEL_GP = 0, + PRUSS_GP_MUX_SEL_ENDAT, + PRUSS_GP_MUX_SEL_RESERVED, + PRUSS_GP_MUX_SEL_SD, + PRUSS_GP_MUX_SEL_MII2, + PRUSS_GP_MUX_SEL_MAX, +}; + /** * enum pruss_pru_id - PRU core identifiers * @PRUSS_PRU0: PRU Core 0. @@ -78,6 +96,8 @@ int pruss_request_mem_region(struct pruss *pruss, enum pruss_mem mem_id, struct pruss_mem_region *region); int pruss_release_mem_region(struct pruss *pruss, struct pruss_mem_region *region); +int pruss_cfg_get_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 *mux); +int pruss_cfg_set_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 mux); #else @@ -101,6 +121,18 @@ static inline int pruss_release_mem_region(struct pruss *pruss, return -EOPNOTSUPP; } +static inline int pruss_cfg_get_gpmux(struct pruss *pruss, + enum pruss_pru_id pru_id, u8 *mux) +{ + return ERR_PTR(-EOPNOTSUPP); +} + +static inline int pruss_cfg_set_gpmux(struct pruss *pruss, + enum pruss_pru_id pru_id, u8 mux) +{ + return ERR_PTR(-EOPNOTSUPP); +} + #endif /* CONFIG_TI_PRUSS */ #if IS_ENABLED(CONFIG_PRU_REMOTEPROC)