pruss.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. /*
  2. * PRU-ICSS platform driver for various TI SoCs
  3. *
  4. * Copyright (C) 2014-2017 Texas Instruments Incorporated - http://www.ti.com/
  5. * Suman Anna <s-anna@ti.com>
  6. * Andrew F. Davis <afd@ti.com>
  7. * Roger Quadros <rogerq@ti.com>
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * version 2 as published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. */
  18. #include <linux/dma-mapping.h>
  19. #include <linux/module.h>
  20. #include <linux/of_device.h>
  21. #include <linux/remoteproc.h>
  22. #include <linux/pruss.h>
  23. #include "pruss.h"
  24. /**
  25. * struct pruss_private_data - PRUSS driver private data
  26. * @aux_data: auxiliary data used for creating the child nodes
  27. * @pruss_id: PRUSS instance number
  28. * @has_no_sharedram: flag to indicate the absence of PRUSS Shared Data RAM
  29. */
  30. struct pruss_private_data {
  31. struct of_dev_auxdata *aux_data;
  32. u32 pruss_id;
  33. bool has_no_sharedram;
  34. };
  35. /**
  36. * struct pruss_match_private_data - private data to handle multiple instances
  37. * @device_name: device name of the PRUSS instance
  38. * @priv_data: PRUSS driver private data for this PRUSS instance
  39. */
  40. struct pruss_match_private_data {
  41. const char *device_name;
  42. struct pruss_private_data *priv_data;
  43. };
  44. static DEFINE_MUTEX(pruss_list_mutex);
  45. static LIST_HEAD(pruss_list);
  46. /**
  47. * pruss_get() - get the pruss for the given device
  48. * @dev: device interested in the pruss
  49. * @pruss_id: integer pointer to fill in the pruss instance id
  50. *
  51. * Finds the pruss device referenced by the "pruss" property in the
  52. * requesting (client) device's device node. The function will also
  53. * return the PRUSS instance id to requestors if @pruss_id is provided.
  54. * This can be used by PRU client drivers to distinguish between
  55. * multiple PRUSS instances, and build some customization around a
  56. * specific PRUSS instance.
  57. *
  58. * This function increments the pruss device's refcount, so always
  59. * use pruss_put() to decrement it back once pruss isn't needed anymore.
  60. *
  61. * Returns the pruss handle on success. ERR_PTR on failure e.g.
  62. * -ENOENT if missing "pruss" property or if pruss device is not enabled in dt
  63. * -EINVAL if invalid parameter
  64. * -EPROBE_DEFER if the pruss device is not yet available
  65. */
  66. struct pruss *pruss_get(struct device *dev, int *pruss_id)
  67. {
  68. struct pruss *pruss = NULL, *p;
  69. struct device_node *np;
  70. if (!dev)
  71. return ERR_PTR(-EINVAL);
  72. np = of_parse_phandle(dev->of_node, "pruss", 0);
  73. if (!np || !of_device_is_available(np))
  74. /* pruss is never going to show up */
  75. return ERR_PTR(-ENOENT);
  76. mutex_lock(&pruss_list_mutex);
  77. list_for_each_entry(p, &pruss_list, node) {
  78. if (p->dev->of_node == np) {
  79. pruss = p;
  80. get_device(pruss->dev);
  81. if (pruss_id)
  82. *pruss_id = pruss->id;
  83. break;
  84. }
  85. }
  86. mutex_unlock(&pruss_list_mutex);
  87. of_node_put(np);
  88. return pruss ? pruss : ERR_PTR(-EPROBE_DEFER);
  89. }
  90. EXPORT_SYMBOL_GPL(pruss_get);
  91. /**
  92. * pruss_put() - decrement pruss device's usecount
  93. * @pruss: pruss handle
  94. *
  95. * Complimentary function for pruss_get(). Needs to be called
  96. * after the PRUSS is used, and only if the pruss_get() succeeds.
  97. */
  98. void pruss_put(struct pruss *pruss)
  99. {
  100. if (!pruss)
  101. return;
  102. put_device(pruss->dev);
  103. }
  104. EXPORT_SYMBOL_GPL(pruss_put);
  105. /* get the rproc phandle corresponding to a pru_id */
  106. static struct rproc *__pruss_rproc_get(struct pruss *pruss,
  107. enum pruss_pru_id pru_id)
  108. {
  109. struct device_node *rproc_np = NULL;
  110. struct device_node *child;
  111. struct platform_device *pdev;
  112. struct rproc *rproc;
  113. char pru_name[5];
  114. /* get rproc corresponding to pru_id using the label property */
  115. snprintf(pru_name, sizeof(pru_name), "pru%d", pru_id);
  116. for_each_child_of_node(pruss->dev->of_node, child) {
  117. if (of_property_match_string(child, "label", pru_name) == 0) {
  118. rproc_np = child;
  119. break;
  120. }
  121. }
  122. if (!rproc_np)
  123. return ERR_PTR(-ENODEV);
  124. pdev = of_find_device_by_node(rproc_np);
  125. of_node_put(rproc_np);
  126. if (!pdev)
  127. /* probably PRU not yet probed */
  128. return ERR_PTR(-EPROBE_DEFER);
  129. rproc = platform_get_drvdata(pdev);
  130. if (!rproc)
  131. return ERR_PTR(-EPROBE_DEFER);
  132. get_device(&rproc->dev);
  133. return rproc;
  134. }
  135. /**
  136. * pruss_rproc_get() - Get the rproc instance corresponding to pru_id
  137. * @pruss: the pruss instance
  138. * @pru_id: the PRU id of which we need the rproc instance
  139. *
  140. * Allows only one user to own the rproc resource at a time.
  141. * Caller must call pruss_rproc_put() when done with using the rproc.
  142. *
  143. * Returns rproc handle on success. ERR_PTR on failure e.g.
  144. * -EBUSY if PRU is already reserved by someone else
  145. * -ENODEV if not yet available.
  146. * -EINVAL if invalid parameters.
  147. */
  148. struct rproc *pruss_rproc_get(struct pruss *pruss,
  149. enum pruss_pru_id pru_id)
  150. {
  151. struct rproc *rproc;
  152. int ret;
  153. if (!pruss)
  154. return ERR_PTR(-EINVAL);
  155. if (pru_id != PRUSS_PRU0 && pru_id != PRUSS_PRU1)
  156. return ERR_PTR(-EINVAL);
  157. rproc = __pruss_rproc_get(pruss, pru_id);
  158. if (IS_ERR(rproc))
  159. return rproc;
  160. mutex_lock(&pruss->lock);
  161. if (pruss->pru_in_use[pru_id]) {
  162. ret = -EBUSY;
  163. goto unlock;
  164. }
  165. pruss->pru_in_use[pru_id] = rproc;
  166. mutex_unlock(&pruss->lock);
  167. return rproc;
  168. unlock:
  169. mutex_unlock(&pruss->lock);
  170. put_device(&rproc->dev);
  171. return ERR_PTR(ret);
  172. }
  173. EXPORT_SYMBOL_GPL(pruss_rproc_get);
  174. /* find out PRU ID from the rproc instance */
  175. static enum pruss_pru_id pruss_rproc_to_pru_id(struct pruss *pruss,
  176. struct rproc *rproc)
  177. {
  178. enum pruss_pru_id pru_id;
  179. for (pru_id = PRUSS_PRU0; pru_id < PRUSS_NUM_PRUS; pru_id++)
  180. if (pruss->pru_in_use[pru_id] == rproc)
  181. return pru_id;
  182. return -1;
  183. }
  184. /**
  185. * pruss_rproc_put() - release the PRU rproc resource
  186. * @pruss: the pruss instance
  187. * @rproc: the rproc resource to release
  188. *
  189. * Releases the rproc resource and makes it available to other
  190. * users.
  191. */
  192. void pruss_rproc_put(struct pruss *pruss, struct rproc *rproc)
  193. {
  194. int pru_id;
  195. if (!pruss || IS_ERR_OR_NULL(rproc))
  196. return;
  197. mutex_lock(&pruss->lock);
  198. pru_id = pruss_rproc_to_pru_id(pruss, rproc);
  199. if (pru_id < 0) {
  200. mutex_unlock(&pruss->lock);
  201. return;
  202. }
  203. if (!pruss->pru_in_use[pru_id]) {
  204. mutex_unlock(&pruss->lock);
  205. return;
  206. }
  207. pruss->pru_in_use[pru_id] = NULL;
  208. mutex_unlock(&pruss->lock);
  209. put_device(&rproc->dev);
  210. }
  211. EXPORT_SYMBOL(pruss_rproc_put);
  212. /**
  213. * pruss_request_mem_region() - request a memory resource
  214. * @pruss: the pruss instance
  215. * @mem_id: the memory resource id
  216. * @region: pointer to memory region structure to be filled in
  217. *
  218. * This function allows a client driver to request a memory resource,
  219. * and if successful, will let the client driver own the particular
  220. * memory region until released using the pruss_release_mem_region()
  221. * API.
  222. *
  223. * Returns the memory region if requested resource is available, an
  224. * error otherwise
  225. */
  226. int pruss_request_mem_region(struct pruss *pruss, enum pruss_mem mem_id,
  227. struct pruss_mem_region *region)
  228. {
  229. if (!pruss || !region)
  230. return -EINVAL;
  231. if (mem_id >= PRUSS_MEM_MAX)
  232. return -EINVAL;
  233. mutex_lock(&pruss->lock);
  234. if (pruss->mem_in_use[mem_id]) {
  235. mutex_unlock(&pruss->lock);
  236. return -EBUSY;
  237. }
  238. *region = pruss->mem_regions[mem_id];
  239. pruss->mem_in_use[mem_id] = region;
  240. mutex_unlock(&pruss->lock);
  241. return 0;
  242. }
  243. EXPORT_SYMBOL_GPL(pruss_request_mem_region);
  244. /**
  245. * pruss_release_mem_region() - release a memory resource
  246. * @pruss: the pruss instance
  247. * @region: the memory region to release
  248. *
  249. * This function is the complimentary function to
  250. * pruss_request_mem_region(), and allows the client drivers to
  251. * release back a memory resource.
  252. *
  253. * Returns 0 on success, an error code otherwise
  254. */
  255. int pruss_release_mem_region(struct pruss *pruss,
  256. struct pruss_mem_region *region)
  257. {
  258. int id;
  259. if (!pruss || !region)
  260. return -EINVAL;
  261. mutex_lock(&pruss->lock);
  262. /* find out the memory region being released */
  263. for (id = 0; id < PRUSS_MEM_MAX; id++) {
  264. if (pruss->mem_in_use[id] == region)
  265. break;
  266. }
  267. if (id == PRUSS_MEM_MAX) {
  268. mutex_unlock(&pruss->lock);
  269. return -EINVAL;
  270. }
  271. pruss->mem_in_use[id] = NULL;
  272. mutex_unlock(&pruss->lock);
  273. return 0;
  274. }
  275. EXPORT_SYMBOL_GPL(pruss_release_mem_region);
  276. static inline u32 pruss_read_reg(struct pruss *pruss, enum pruss_mem region,
  277. unsigned int reg)
  278. {
  279. return readl_relaxed(pruss->mem_regions[region].va + reg);
  280. }
  281. static inline void pruss_write_reg(struct pruss *pruss, enum pruss_mem region,
  282. unsigned int reg, u32 val)
  283. {
  284. writel_relaxed(val, pruss->mem_regions[region].va + reg);
  285. }
  286. static inline void pruss_set_reg(struct pruss *pruss, enum pruss_mem region,
  287. unsigned int reg, u32 mask, u32 set)
  288. {
  289. u32 val;
  290. val = pruss_read_reg(pruss, region, reg);
  291. val &= ~mask;
  292. val |= (set & mask);
  293. pruss_write_reg(pruss, region, reg, val);
  294. }
  295. /**
  296. * pruss_cfg_gpimode() - set the GPI mode of the PRU
  297. * @pruss: the pruss instance handle
  298. * @rproc: the rproc instance handle of the PRU
  299. * @mode: GPI mode to set
  300. *
  301. * Sets the GPI mode for a given PRU by programming the
  302. * corresponding PRUSS_CFG_GPCFGx register
  303. *
  304. * Returns 0 on success, or an error code otherwise
  305. */
  306. int pruss_cfg_gpimode(struct pruss *pruss, struct rproc *rproc,
  307. enum pruss_gpi_mode mode)
  308. {
  309. u32 reg;
  310. int pru_id;
  311. pru_id = pruss_rproc_to_pru_id(pruss, rproc);
  312. if (pru_id < 0 || pru_id >= PRUSS_NUM_PRUS) {
  313. dev_err(pruss->dev, "%s: PRU id not found, %d\n",
  314. __func__, pru_id);
  315. return -EINVAL;
  316. }
  317. reg = PRUSS_CFG_GPCFG0 + (0x4 * pru_id);
  318. mutex_lock(&pruss->cfg_lock);
  319. pruss_set_reg(pruss, PRUSS_MEM_CFG, reg,
  320. PRUSS_GPCFG_PRU_GPI_MODE_MASK,
  321. mode << PRUSS_GPCFG_PRU_GPI_MODE_SHIFT);
  322. mutex_unlock(&pruss->cfg_lock);
  323. return 0;
  324. }
  325. EXPORT_SYMBOL_GPL(pruss_cfg_gpimode);
  326. /**
  327. * pruss_cfg_set_gpmux() - set the GP_MUX mode of the PRU
  328. * @pruss: the pruss instance handle
  329. * @pru_id: the PRU id for which the GP_MUX mode is to be set
  330. * @mux_sel: GP mux sel value to set
  331. *
  332. * Sets the GP MUX mode for a given PRU by programming the
  333. * corresponding PRUSS_CFG_GPCFGx register. This API is currently
  334. * limited to be invoked only by the pru_rproc driver
  335. *
  336. * Returns 0 on success, or an error code otherwise
  337. */
  338. int pruss_cfg_set_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id,
  339. enum pruss_gp_mux_sel mux_sel)
  340. {
  341. u32 reg, val, mask;
  342. if (pru_id < 0 || pru_id >= PRUSS_NUM_PRUS) {
  343. dev_err(pruss->dev, "%s: invalid PRU id, %d\n",
  344. __func__, pru_id);
  345. return -EINVAL;
  346. }
  347. reg = PRUSS_CFG_GPCFG0 + (0x4 * pru_id);
  348. val = mux_sel << PRUSS_GPCFG_PRU_MUX_SEL_SHIFT;
  349. mask = PRUSS_GPCFG_PRU_MUX_SEL_MASK;
  350. pruss_set_reg(pruss, PRUSS_MEM_CFG, reg, mask, val);
  351. return 0;
  352. }
  353. EXPORT_SYMBOL_GPL(pruss_cfg_set_gpmux);
  354. /**
  355. * pruss_cfg_miirt_enable() - Enable/disable MII RT Events
  356. * @pruss: the pruss instance
  357. * @enable: enable/disable
  358. *
  359. * Enable/disable the MII RT Events for the PRUSS.
  360. */
  361. void pruss_cfg_miirt_enable(struct pruss *pruss, bool enable)
  362. {
  363. u32 set = enable ? PRUSS_MII_RT_EVENT_EN : 0;
  364. mutex_lock(&pruss->cfg_lock);
  365. pruss_set_reg(pruss, PRUSS_MEM_CFG, PRUSS_CFG_MII_RT,
  366. PRUSS_MII_RT_EVENT_EN, set);
  367. mutex_unlock(&pruss->cfg_lock);
  368. }
  369. EXPORT_SYMBOL_GPL(pruss_cfg_miirt_enable);
  370. /**
  371. * pruss_cfg_xfr_enable() - Enable/disable XIN XOUT shift functionality
  372. * @pruss: the pruss instance
  373. * @enable: enable/disable
  374. */
  375. void pruss_cfg_xfr_enable(struct pruss *pruss, bool enable)
  376. {
  377. u32 set = enable ? PRUSS_SPP_XFER_SHIFT_EN : 0;
  378. mutex_lock(&pruss->cfg_lock);
  379. pruss_set_reg(pruss, PRUSS_MEM_CFG, PRUSS_CFG_SPP,
  380. PRUSS_SPP_XFER_SHIFT_EN, set);
  381. mutex_unlock(&pruss->cfg_lock);
  382. }
  383. EXPORT_SYMBOL_GPL(pruss_cfg_xfr_enable);
  384. static const struct of_device_id pruss_of_match[];
  385. static const
  386. struct pruss_private_data *pruss_get_private_data(struct platform_device *pdev)
  387. {
  388. const struct pruss_match_private_data *data;
  389. const struct of_device_id *match;
  390. match = of_match_device(pruss_of_match, &pdev->dev);
  391. if (!match)
  392. return ERR_PTR(-ENODEV);
  393. data = match->data;
  394. for (; data && data->device_name; data++) {
  395. if (!strcmp(dev_name(&pdev->dev), data->device_name))
  396. return data->priv_data;
  397. }
  398. return NULL;
  399. }
  400. static int pruss_probe(struct platform_device *pdev)
  401. {
  402. struct device *dev = &pdev->dev;
  403. struct device_node *node = dev->of_node;
  404. struct pruss *pruss;
  405. struct resource *res;
  406. int ret, i;
  407. const struct pruss_private_data *data;
  408. const char *mem_names[PRUSS_MEM_MAX] = { "dram0", "dram1", "shrdram2",
  409. "cfg", "iep", "mii_rt" };
  410. if (!node) {
  411. dev_err(dev, "Non-DT platform device not supported\n");
  412. return -ENODEV;
  413. }
  414. data = pruss_get_private_data(pdev);
  415. if (IS_ERR_OR_NULL(data)) {
  416. dev_err(dev, "missing private data\n");
  417. return -ENODEV;
  418. }
  419. ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
  420. if (ret) {
  421. dev_err(dev, "dma_set_coherent_mask: %d\n", ret);
  422. return ret;
  423. }
  424. pruss = devm_kzalloc(dev, sizeof(*pruss), GFP_KERNEL);
  425. if (!pruss)
  426. return -ENOMEM;
  427. pruss->dev = dev;
  428. pruss->id = data->pruss_id;
  429. mutex_init(&pruss->lock);
  430. mutex_init(&pruss->cfg_lock);
  431. for (i = 0; i < ARRAY_SIZE(mem_names); i++) {
  432. if (data->has_no_sharedram && !strcmp(mem_names[i], "shrdram2"))
  433. continue;
  434. res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
  435. mem_names[i]);
  436. pruss->mem_regions[i].va = devm_ioremap_resource(dev, res);
  437. if (IS_ERR(pruss->mem_regions[i].va)) {
  438. dev_err(dev, "failed to parse and map memory resource %d %s\n",
  439. i, mem_names[i]);
  440. return PTR_ERR(pruss->mem_regions[i].va);
  441. }
  442. pruss->mem_regions[i].pa = res->start;
  443. pruss->mem_regions[i].size = resource_size(res);
  444. dev_dbg(dev, "memory %8s: pa %pa size 0x%x va %p\n",
  445. mem_names[i], &pruss->mem_regions[i].pa,
  446. pruss->mem_regions[i].size, pruss->mem_regions[i].va);
  447. }
  448. platform_set_drvdata(pdev, pruss);
  449. mutex_lock(&pruss_list_mutex);
  450. list_add_tail(&pruss->node, &pruss_list);
  451. mutex_unlock(&pruss_list_mutex);
  452. dev_info(&pdev->dev, "creating PRU cores and other child platform devices\n");
  453. ret = of_platform_populate(node, NULL, data->aux_data, &pdev->dev);
  454. if (ret) {
  455. dev_err(dev, "of_platform_populate failed\n");
  456. goto err_of_fail;
  457. }
  458. return 0;
  459. err_of_fail:
  460. mutex_lock(&pruss_list_mutex);
  461. list_del(&pruss->node);
  462. mutex_unlock(&pruss_list_mutex);
  463. return ret;
  464. }
  465. static int pruss_remove(struct platform_device *pdev)
  466. {
  467. struct device *dev = &pdev->dev;
  468. struct pruss *pruss = platform_get_drvdata(pdev);
  469. dev_info(dev, "remove PRU cores and other child platform devices\n");
  470. of_platform_depopulate(dev);
  471. mutex_lock(&pruss_list_mutex);
  472. list_del(&pruss->node);
  473. mutex_unlock(&pruss_list_mutex);
  474. return 0;
  475. }
  476. /*
  477. * auxdata lookup table for giving specific device names to PRU platform
  478. * devices. The device names are used in the driver to find private data
  479. * specific to a PRU-core such as an id and a firmware name etc, especially
  480. * needed when there are multiple PRUSS instances present on a SoC.
  481. * XXX: The auxdata in general is not a recommended usage, and this should
  482. * eventually be eliminated. The current usage allows us to define the
  483. * PRU device names with an identifier like xxxxxxxx.pru0 agnostic of
  484. * name defined in device tree.
  485. */
  486. static struct of_dev_auxdata am335x_pruss_rproc_auxdata_lookup[] = {
  487. OF_DEV_AUXDATA("ti,am3356-pru", 0x4a334000, "4a334000.pru0", NULL),
  488. OF_DEV_AUXDATA("ti,am3356-pru", 0x4a338000, "4a338000.pru1", NULL),
  489. { /* sentinel */ },
  490. };
  491. static struct of_dev_auxdata am437x_pruss1_rproc_auxdata_lookup[] = {
  492. OF_DEV_AUXDATA("ti,am4376-pru", 0x54434000, "54434000.pru0", NULL),
  493. OF_DEV_AUXDATA("ti,am4376-pru", 0x54438000, "54438000.pru1", NULL),
  494. { /* sentinel */ },
  495. };
  496. static struct of_dev_auxdata am437x_pruss0_rproc_auxdata_lookup[] = {
  497. OF_DEV_AUXDATA("ti,am4376-pru", 0x54474000, "54474000.pru0", NULL),
  498. OF_DEV_AUXDATA("ti,am4376-pru", 0x54478000, "54478000.pru1", NULL),
  499. { /* sentinel */ },
  500. };
  501. static struct of_dev_auxdata am57xx_pruss1_rproc_auxdata_lookup[] = {
  502. OF_DEV_AUXDATA("ti,am5728-pru", 0x4b234000, "4b234000.pru0", NULL),
  503. OF_DEV_AUXDATA("ti,am5728-pru", 0x4b238000, "4b238000.pru1", NULL),
  504. { /* sentinel */ },
  505. };
  506. static struct of_dev_auxdata am57xx_pruss2_rproc_auxdata_lookup[] = {
  507. OF_DEV_AUXDATA("ti,am5728-pru", 0x4b2b4000, "4b2b4000.pru0", NULL),
  508. OF_DEV_AUXDATA("ti,am5728-pru", 0x4b2b8000, "4b2b8000.pru1", NULL),
  509. { /* sentinel */ },
  510. };
  511. static struct of_dev_auxdata k2g_pruss0_rproc_auxdata_lookup[] = {
  512. OF_DEV_AUXDATA("ti,k2g-pru", 0x20ab4000, "20ab4000.pru0", NULL),
  513. OF_DEV_AUXDATA("ti,k2g-pru", 0x20ab8000, "20ab8000.pru1", NULL),
  514. { /* sentinel */ },
  515. };
  516. static struct of_dev_auxdata k2g_pruss1_rproc_auxdata_lookup[] = {
  517. OF_DEV_AUXDATA("ti,k2g-pru", 0x20af4000, "20af4000.pru0", NULL),
  518. OF_DEV_AUXDATA("ti,k2g-pru", 0x20af8000, "20af8000.pru1", NULL),
  519. { /* sentinel */ },
  520. };
  521. /* instance-specific driver private data */
  522. static struct pruss_private_data am335x_pruss_priv_data = {
  523. .aux_data = am335x_pruss_rproc_auxdata_lookup,
  524. .pruss_id = 0,
  525. };
  526. static struct pruss_private_data am437x_pruss1_priv_data = {
  527. .aux_data = am437x_pruss1_rproc_auxdata_lookup,
  528. .pruss_id = 1,
  529. };
  530. static struct pruss_private_data am437x_pruss0_priv_data = {
  531. .aux_data = am437x_pruss0_rproc_auxdata_lookup,
  532. .pruss_id = 0,
  533. .has_no_sharedram = true,
  534. };
  535. static struct pruss_private_data am57xx_pruss1_priv_data = {
  536. .aux_data = am57xx_pruss1_rproc_auxdata_lookup,
  537. .pruss_id = 1,
  538. };
  539. static struct pruss_private_data am57xx_pruss2_priv_data = {
  540. .aux_data = am57xx_pruss2_rproc_auxdata_lookup,
  541. .pruss_id = 2,
  542. };
  543. static struct pruss_private_data k2g_pruss0_priv_data = {
  544. .aux_data = k2g_pruss0_rproc_auxdata_lookup,
  545. .pruss_id = 0,
  546. };
  547. static struct pruss_private_data k2g_pruss1_priv_data = {
  548. .aux_data = k2g_pruss1_rproc_auxdata_lookup,
  549. .pruss_id = 1,
  550. };
  551. static struct pruss_match_private_data am335x_match_data[] = {
  552. {
  553. .device_name = "4a300000.pruss",
  554. .priv_data = &am335x_pruss_priv_data,
  555. },
  556. {
  557. /* sentinel */
  558. },
  559. };
  560. static struct pruss_match_private_data am437x_match_data[] = {
  561. {
  562. .device_name = "54400000.pruss",
  563. .priv_data = &am437x_pruss1_priv_data,
  564. },
  565. {
  566. .device_name = "54440000.pruss",
  567. .priv_data = &am437x_pruss0_priv_data,
  568. },
  569. {
  570. /* sentinel */
  571. },
  572. };
  573. static struct pruss_match_private_data am57xx_match_data[] = {
  574. {
  575. .device_name = "4b200000.pruss",
  576. .priv_data = &am57xx_pruss1_priv_data,
  577. },
  578. {
  579. .device_name = "4b280000.pruss",
  580. .priv_data = &am57xx_pruss2_priv_data,
  581. },
  582. {
  583. /* sentinel */
  584. },
  585. };
  586. static struct pruss_match_private_data k2g_match_data[] = {
  587. {
  588. .device_name = "20a80000.pruss",
  589. .priv_data = &k2g_pruss0_priv_data,
  590. },
  591. {
  592. .device_name = "20ac0000.pruss",
  593. .priv_data = &k2g_pruss1_priv_data,
  594. },
  595. {
  596. /* sentinel */
  597. },
  598. };
  599. static const struct of_device_id pruss_of_match[] = {
  600. { .compatible = "ti,am3356-pruss", .data = &am335x_match_data, },
  601. { .compatible = "ti,am4376-pruss", .data = &am437x_match_data, },
  602. { .compatible = "ti,am5728-pruss", .data = &am57xx_match_data, },
  603. { .compatible = "ti,k2g-pruss", .data = &k2g_match_data, },
  604. { /* sentinel */ },
  605. };
  606. MODULE_DEVICE_TABLE(of, pruss_of_match);
  607. static struct platform_driver pruss_driver = {
  608. .driver = {
  609. .name = "ti-pruss",
  610. .of_match_table = pruss_of_match,
  611. },
  612. .probe = pruss_probe,
  613. .remove = pruss_remove,
  614. };
  615. module_platform_driver(pruss_driver);
  616. MODULE_AUTHOR("Suman Anna <s-anna@ti.com>");
  617. MODULE_DESCRIPTION("PRU-ICSS Subsystem Driver");
  618. MODULE_LICENSE("GPL v2");