blob: 9d02431d3194bfa7ca4bbf1afa05c085c2a041cd [file] [log] [blame]
Kristofer Jonsson116a6352020-08-20 17:25:23 +02001/*
2 * (C) COPYRIGHT 2020 ARM Limited. All rights reserved.
3 *
4 * This program is free software and is provided to you under the terms of the
5 * GNU General Public License version 2 as published by the Free Software
6 * Foundation, and any use by you of this program is subject to the terms
7 * of such GNU licence.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, you can access it online at
16 * http://www.gnu.org/licenses/gpl-2.0.html.
17 *
18 * SPDX-License-Identifier: GPL-2.0-only
19 */
20
Kristofer Jonsson4aec3762021-10-13 17:09:27 +020021#include <linux/bitmap.h>
22#include <linux/fs.h>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020023#include <linux/module.h>
24#include <linux/io.h>
25#include <linux/of.h>
26#include <linux/of_address.h>
27#include <linux/platform_device.h>
28
29#include "ethosu_device.h"
30
31/****************************************************************************
32 * Defines
33 ****************************************************************************/
34
35#define ETHOSU_DRIVER_VERSION "1.0"
36#define ETHOSU_DRIVER_NAME "ethosu"
37
Kristofer Jonsson4aec3762021-10-13 17:09:27 +020038#define MINOR_BASE 0 /* Minor version starts at 0 */
39#define MINOR_COUNT 64 /* Allocate minor versions */
40
Kristofer Jonsson116a6352020-08-20 17:25:23 +020041/****************************************************************************
42 * Variables
43 ****************************************************************************/
44
Kristofer Jonsson4aec3762021-10-13 17:09:27 +020045static struct class *ethosu_class;
46
47static dev_t devt;
48
49static DECLARE_BITMAP(minors, MINOR_COUNT);
Kristofer Jonsson116a6352020-08-20 17:25:23 +020050
51/****************************************************************************
52 * Arm Ethos-U
53 ****************************************************************************/
54
55static int ethosu_pdev_probe(struct platform_device *pdev)
56{
57 struct ethosu_device *edev;
58 struct resource *in_queue_res;
59 struct resource *out_queue_res;
Kristofer Jonsson4aec3762021-10-13 17:09:27 +020060 int minor;
Kristofer Jonsson116a6352020-08-20 17:25:23 +020061 int ret;
62
63 dev_info(&pdev->dev, "Probe\n");
64
Kristofer Jonsson4aec3762021-10-13 17:09:27 +020065 minor = find_first_zero_bit(minors, MINOR_COUNT);
66 if (minor >= MINOR_COUNT) {
67 dev_err(&pdev->dev, "No more minor numbers.\n");
68
69 return -ENOMEM;
70 }
71
Kristofer Jonsson116a6352020-08-20 17:25:23 +020072 /* Get path to TCM memory */
73 in_queue_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
74 "in_queue");
75 if (IS_ERR(in_queue_res)) {
76 dev_err(&pdev->dev, "Failed to get in_queue resource.\n");
77
78 return PTR_ERR(in_queue_res);
79 }
80
81 out_queue_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
82 "out_queue");
83 if (IS_ERR(out_queue_res)) {
84 dev_err(&pdev->dev, "Failed to get out_queue resource.\n");
85
86 return PTR_ERR(out_queue_res);
87 }
88
89 /* Allocate memory for Arm Ethos-U device */
90 edev = devm_kzalloc(&pdev->dev, sizeof(*edev), GFP_KERNEL);
91 if (!edev)
92 return -ENOMEM;
93
94 platform_set_drvdata(pdev, edev);
95
96 /* Initialize device */
Kristofer Jonsson4aec3762021-10-13 17:09:27 +020097 ret = ethosu_dev_init(edev, &pdev->dev, ethosu_class,
98 MKDEV(MAJOR(devt), minor), in_queue_res,
Kristofer Jonsson116a6352020-08-20 17:25:23 +020099 out_queue_res);
100 if (ret)
101 goto free_dev;
102
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200103 set_bit(minor, minors);
104
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200105 return 0;
106
107free_dev:
108 devm_kfree(&pdev->dev, edev);
109
110 return ret;
111}
112
113static int ethosu_pdev_remove(struct platform_device *pdev)
114{
115 struct ethosu_device *edev = platform_get_drvdata(pdev);
116
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200117 clear_bit(MINOR(edev->devt), minors);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200118 ethosu_dev_deinit(edev);
119
120 return 0;
121}
122
123static const struct of_device_id ethosu_pdev_match[] = {
124 { .compatible = "arm,ethosu" },
125 { /* Sentinel */ },
126};
127
128MODULE_DEVICE_TABLE(of, ethosu_pdev_match);
129
130static struct platform_driver ethosu_pdev_driver = {
131 .probe = &ethosu_pdev_probe,
132 .remove = &ethosu_pdev_remove,
133 .driver = {
134 .name = ETHOSU_DRIVER_NAME,
135 .owner = THIS_MODULE,
136 .of_match_table = of_match_ptr(ethosu_pdev_match),
137 },
138};
139
140/****************************************************************************
141 * Module init and exit
142 ****************************************************************************/
143
144static int __init ethosu_init(void)
145{
146 int ret;
147
148 ethosu_class = class_create(THIS_MODULE, ETHOSU_DRIVER_NAME);
149 if (IS_ERR(ethosu_class)) {
150 printk("Failed to create class '%s'.\n", ETHOSU_DRIVER_NAME);
151
152 return PTR_ERR(ethosu_class);
153 }
154
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200155 ret = alloc_chrdev_region(&devt, MINOR_BASE, MINOR_COUNT,
156 ETHOSU_DRIVER_NAME);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200157 if (ret) {
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200158 printk("Failed to allocate chrdev region.\n");
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200159 goto destroy_class;
160 }
161
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200162 ret = platform_driver_register(&ethosu_pdev_driver);
163 if (ret) {
164 printk("Failed to register Arm Ethos-U platform driver.\n");
165 goto region_unregister;
166 }
167
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200168 return 0;
169
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200170region_unregister:
171 unregister_chrdev_region(devt, MINOR_COUNT);
172
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200173destroy_class:
174 class_destroy(ethosu_class);
175
176 return ret;
177}
178
179static void __exit ethosu_exit(void)
180{
181 platform_driver_unregister(&ethosu_pdev_driver);
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200182 unregister_chrdev_region(devt, MINOR_COUNT);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200183 class_destroy(ethosu_class);
184}
185
186module_init(ethosu_init)
187module_exit(ethosu_exit)
188MODULE_LICENSE("GPL v2");
189MODULE_AUTHOR("Arm Ltd");
190MODULE_DESCRIPTION("Arm Ethos-U NPU Driver");
191MODULE_VERSION(ETHOSU_DRIVER_VERSION);