Skip to content

Commit 0feedca

Browse files
committed
Merge tag 'ti-driver-soc-for-v6.5' of https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux into soc/drivers
TI SoC driver updates for v6.5 * pruss: Add helper functions for ethernet client driver usage, add compile-testing, fixup function pointer casts * smartreflex: Cosmetic optimization for using devm_ioremap_resource * wkup_m3_ipc: Fix error checking around debugfs_create_dir * tag 'ti-driver-soc-for-v6.5' of https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux: wkup_m3_ipc.c: Fix error checking for debugfs_create_dir soc: ti: pruss: Add helper functions to set GPI mode, MII_RT_event and XFR soc: ti: pruss: Add pruss_cfg_read()/update(), pruss_cfg_get_gpmux()/set_gpmux() APIs soc: ti: pruss: Add pruss_{request,release}_mem_region() API soc: ti: pruss: Add pruss_get()/put() API soc: ti: pruss: Allow compile-testing soc: ti: pruss: Avoid cast to incompatible function type soc: ti: smartreflex: Use devm_platform_ioremap_resource() Link: https://lore.kernel.org/r/20230615164134.6sd5hudyadq3fvk4@garage Signed-off-by: Arnd Bergmann <arnd@arndb.de>
2 parents 37d1fc5 + b11403c commit 0feedca

7 files changed

Lines changed: 475 additions & 22 deletions

File tree

drivers/remoteproc/pru_rproc.c

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -81,21 +81,6 @@ enum pru_iomem {
8181
PRU_IOMEM_MAX,
8282
};
8383

84-
/**
85-
* enum pru_type - PRU core type identifier
86-
*
87-
* @PRU_TYPE_PRU: Programmable Real-time Unit
88-
* @PRU_TYPE_RTU: Auxiliary Programmable Real-Time Unit
89-
* @PRU_TYPE_TX_PRU: Transmit Programmable Real-Time Unit
90-
* @PRU_TYPE_MAX: just keep this one at the end
91-
*/
92-
enum pru_type {
93-
PRU_TYPE_PRU = 0,
94-
PRU_TYPE_RTU,
95-
PRU_TYPE_TX_PRU,
96-
PRU_TYPE_MAX,
97-
};
98-
9984
/**
10085
* struct pru_private_data - device data for a PRU core
10186
* @type: type of the PRU core (PRU, RTU, Tx_PRU)

drivers/soc/ti/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ config TI_K3_SOCINFO
8585

8686
config TI_PRUSS
8787
tristate "TI PRU-ICSS Subsystem Platform drivers"
88-
depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX || ARCH_KEYSTONE || ARCH_K3
88+
depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX || ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST
8989
select MFD_SYSCON
9090
help
9191
TI PRU-ICSS Subsystem platform specific support.

drivers/soc/ti/pruss.c

Lines changed: 261 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Author(s):
77
* Suman Anna <s-anna@ti.com>
88
* Andrew F. Davis <afd@ti.com>
9+
* Tero Kristo <t-kristo@ti.com>
910
*/
1011

1112
#include <linux/clk-provider.h>
@@ -18,7 +19,9 @@
1819
#include <linux/pm_runtime.h>
1920
#include <linux/pruss_driver.h>
2021
#include <linux/regmap.h>
22+
#include <linux/remoteproc.h>
2123
#include <linux/slab.h>
24+
#include "pruss.h"
2225

2326
/**
2427
* struct pruss_private_data - PRUSS driver private data
@@ -30,6 +33,257 @@ struct pruss_private_data {
3033
bool has_core_mux_clock;
3134
};
3235

36+
/**
37+
* pruss_get() - get the pruss for a given PRU remoteproc
38+
* @rproc: remoteproc handle of a PRU instance
39+
*
40+
* Finds the parent pruss device for a PRU given the @rproc handle of the
41+
* PRU remote processor. This function increments the pruss device's refcount,
42+
* so always use pruss_put() to decrement it back once pruss isn't needed
43+
* anymore.
44+
*
45+
* This API doesn't check if @rproc is valid or not. It is expected the caller
46+
* will have done a pru_rproc_get() on @rproc, before calling this API to make
47+
* sure that @rproc is valid.
48+
*
49+
* Return: pruss handle on success, and an ERR_PTR on failure using one
50+
* of the following error values
51+
* -EINVAL if invalid parameter
52+
* -ENODEV if PRU device or PRUSS device is not found
53+
*/
54+
struct pruss *pruss_get(struct rproc *rproc)
55+
{
56+
struct pruss *pruss;
57+
struct device *dev;
58+
struct platform_device *ppdev;
59+
60+
if (IS_ERR_OR_NULL(rproc))
61+
return ERR_PTR(-EINVAL);
62+
63+
dev = &rproc->dev;
64+
65+
/* make sure it is PRU rproc */
66+
if (!dev->parent || !is_pru_rproc(dev->parent))
67+
return ERR_PTR(-ENODEV);
68+
69+
ppdev = to_platform_device(dev->parent->parent);
70+
pruss = platform_get_drvdata(ppdev);
71+
if (!pruss)
72+
return ERR_PTR(-ENODEV);
73+
74+
get_device(pruss->dev);
75+
76+
return pruss;
77+
}
78+
EXPORT_SYMBOL_GPL(pruss_get);
79+
80+
/**
81+
* pruss_put() - decrement pruss device's usecount
82+
* @pruss: pruss handle
83+
*
84+
* Complimentary function for pruss_get(). Needs to be called
85+
* after the PRUSS is used, and only if the pruss_get() succeeds.
86+
*/
87+
void pruss_put(struct pruss *pruss)
88+
{
89+
if (IS_ERR_OR_NULL(pruss))
90+
return;
91+
92+
put_device(pruss->dev);
93+
}
94+
EXPORT_SYMBOL_GPL(pruss_put);
95+
96+
/**
97+
* pruss_request_mem_region() - request a memory resource
98+
* @pruss: the pruss instance
99+
* @mem_id: the memory resource id
100+
* @region: pointer to memory region structure to be filled in
101+
*
102+
* This function allows a client driver to request a memory resource,
103+
* and if successful, will let the client driver own the particular
104+
* memory region until released using the pruss_release_mem_region()
105+
* API.
106+
*
107+
* Return: 0 if requested memory region is available (in such case pointer to
108+
* memory region is returned via @region), an error otherwise
109+
*/
110+
int pruss_request_mem_region(struct pruss *pruss, enum pruss_mem mem_id,
111+
struct pruss_mem_region *region)
112+
{
113+
if (!pruss || !region || mem_id >= PRUSS_MEM_MAX)
114+
return -EINVAL;
115+
116+
mutex_lock(&pruss->lock);
117+
118+
if (pruss->mem_in_use[mem_id]) {
119+
mutex_unlock(&pruss->lock);
120+
return -EBUSY;
121+
}
122+
123+
*region = pruss->mem_regions[mem_id];
124+
pruss->mem_in_use[mem_id] = region;
125+
126+
mutex_unlock(&pruss->lock);
127+
128+
return 0;
129+
}
130+
EXPORT_SYMBOL_GPL(pruss_request_mem_region);
131+
132+
/**
133+
* pruss_release_mem_region() - release a memory resource
134+
* @pruss: the pruss instance
135+
* @region: the memory region to release
136+
*
137+
* This function is the complimentary function to
138+
* pruss_request_mem_region(), and allows the client drivers to
139+
* release back a memory resource.
140+
*
141+
* Return: 0 on success, an error code otherwise
142+
*/
143+
int pruss_release_mem_region(struct pruss *pruss,
144+
struct pruss_mem_region *region)
145+
{
146+
int id;
147+
148+
if (!pruss || !region)
149+
return -EINVAL;
150+
151+
mutex_lock(&pruss->lock);
152+
153+
/* find out the memory region being released */
154+
for (id = 0; id < PRUSS_MEM_MAX; id++) {
155+
if (pruss->mem_in_use[id] == region)
156+
break;
157+
}
158+
159+
if (id == PRUSS_MEM_MAX) {
160+
mutex_unlock(&pruss->lock);
161+
return -EINVAL;
162+
}
163+
164+
pruss->mem_in_use[id] = NULL;
165+
166+
mutex_unlock(&pruss->lock);
167+
168+
return 0;
169+
}
170+
EXPORT_SYMBOL_GPL(pruss_release_mem_region);
171+
172+
/**
173+
* pruss_cfg_get_gpmux() - get the current GPMUX value for a PRU device
174+
* @pruss: pruss instance
175+
* @pru_id: PRU identifier (0-1)
176+
* @mux: pointer to store the current mux value into
177+
*
178+
* Return: 0 on success, or an error code otherwise
179+
*/
180+
int pruss_cfg_get_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 *mux)
181+
{
182+
int ret;
183+
u32 val;
184+
185+
if (pru_id >= PRUSS_NUM_PRUS || !mux)
186+
return -EINVAL;
187+
188+
ret = pruss_cfg_read(pruss, PRUSS_CFG_GPCFG(pru_id), &val);
189+
if (!ret)
190+
*mux = (u8)((val & PRUSS_GPCFG_PRU_MUX_SEL_MASK) >>
191+
PRUSS_GPCFG_PRU_MUX_SEL_SHIFT);
192+
return ret;
193+
}
194+
EXPORT_SYMBOL_GPL(pruss_cfg_get_gpmux);
195+
196+
/**
197+
* pruss_cfg_set_gpmux() - set the GPMUX value for a PRU device
198+
* @pruss: pruss instance
199+
* @pru_id: PRU identifier (0-1)
200+
* @mux: new mux value for PRU
201+
*
202+
* Return: 0 on success, or an error code otherwise
203+
*/
204+
int pruss_cfg_set_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 mux)
205+
{
206+
if (mux >= PRUSS_GP_MUX_SEL_MAX ||
207+
pru_id >= PRUSS_NUM_PRUS)
208+
return -EINVAL;
209+
210+
return pruss_cfg_update(pruss, PRUSS_CFG_GPCFG(pru_id),
211+
PRUSS_GPCFG_PRU_MUX_SEL_MASK,
212+
(u32)mux << PRUSS_GPCFG_PRU_MUX_SEL_SHIFT);
213+
}
214+
EXPORT_SYMBOL_GPL(pruss_cfg_set_gpmux);
215+
216+
/**
217+
* pruss_cfg_gpimode() - set the GPI mode of the PRU
218+
* @pruss: the pruss instance handle
219+
* @pru_id: id of the PRU core within the PRUSS
220+
* @mode: GPI mode to set
221+
*
222+
* Sets the GPI mode for a given PRU by programming the
223+
* corresponding PRUSS_CFG_GPCFGx register
224+
*
225+
* Return: 0 on success, or an error code otherwise
226+
*/
227+
int pruss_cfg_gpimode(struct pruss *pruss, enum pruss_pru_id pru_id,
228+
enum pruss_gpi_mode mode)
229+
{
230+
if (pru_id >= PRUSS_NUM_PRUS || mode >= PRUSS_GPI_MODE_MAX)
231+
return -EINVAL;
232+
233+
return pruss_cfg_update(pruss, PRUSS_CFG_GPCFG(pru_id),
234+
PRUSS_GPCFG_PRU_GPI_MODE_MASK,
235+
mode << PRUSS_GPCFG_PRU_GPI_MODE_SHIFT);
236+
}
237+
EXPORT_SYMBOL_GPL(pruss_cfg_gpimode);
238+
239+
/**
240+
* pruss_cfg_miirt_enable() - Enable/disable MII RT Events
241+
* @pruss: the pruss instance
242+
* @enable: enable/disable
243+
*
244+
* Enable/disable the MII RT Events for the PRUSS.
245+
*
246+
* Return: 0 on success, or an error code otherwise
247+
*/
248+
int pruss_cfg_miirt_enable(struct pruss *pruss, bool enable)
249+
{
250+
u32 set = enable ? PRUSS_MII_RT_EVENT_EN : 0;
251+
252+
return pruss_cfg_update(pruss, PRUSS_CFG_MII_RT,
253+
PRUSS_MII_RT_EVENT_EN, set);
254+
}
255+
EXPORT_SYMBOL_GPL(pruss_cfg_miirt_enable);
256+
257+
/**
258+
* pruss_cfg_xfr_enable() - Enable/disable XIN XOUT shift functionality
259+
* @pruss: the pruss instance
260+
* @pru_type: PRU core type identifier
261+
* @enable: enable/disable
262+
*
263+
* Return: 0 on success, or an error code otherwise
264+
*/
265+
int pruss_cfg_xfr_enable(struct pruss *pruss, enum pru_type pru_type,
266+
bool enable)
267+
{
268+
u32 mask, set;
269+
270+
switch (pru_type) {
271+
case PRU_TYPE_PRU:
272+
mask = PRUSS_SPP_XFER_SHIFT_EN;
273+
break;
274+
case PRU_TYPE_RTU:
275+
mask = PRUSS_SPP_RTU_XFR_SHIFT_EN;
276+
break;
277+
default:
278+
return -EINVAL;
279+
}
280+
281+
set = enable ? mask : 0;
282+
283+
return pruss_cfg_update(pruss, PRUSS_CFG_SPP, mask, set);
284+
}
285+
EXPORT_SYMBOL_GPL(pruss_cfg_xfr_enable);
286+
33287
static void pruss_of_free_clk_provider(void *data)
34288
{
35289
struct device_node *clk_mux_np = data;
@@ -38,6 +292,11 @@ static void pruss_of_free_clk_provider(void *data)
38292
of_node_put(clk_mux_np);
39293
}
40294

295+
static void pruss_clk_unregister_mux(void *data)
296+
{
297+
clk_unregister_mux(data);
298+
}
299+
41300
static int pruss_clk_mux_setup(struct pruss *pruss, struct clk *clk_mux,
42301
char *mux_name, struct device_node *clks_np)
43302
{
@@ -93,8 +352,7 @@ static int pruss_clk_mux_setup(struct pruss *pruss, struct clk *clk_mux,
93352
goto put_clk_mux_np;
94353
}
95354

96-
ret = devm_add_action_or_reset(dev, (void(*)(void *))clk_unregister_mux,
97-
clk_mux);
355+
ret = devm_add_action_or_reset(dev, pruss_clk_unregister_mux, clk_mux);
98356
if (ret) {
99357
dev_err(dev, "failed to add clkmux unregister action %d", ret);
100358
goto put_clk_mux_np;
@@ -232,6 +490,7 @@ static int pruss_probe(struct platform_device *pdev)
232490
return -ENOMEM;
233491

234492
pruss->dev = dev;
493+
mutex_init(&pruss->lock);
235494

236495
child = of_get_child_by_name(np, "memories");
237496
if (!child) {

0 commit comments

Comments
 (0)