0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/err.h>
0009 #include <linux/module.h>
0010 #include <linux/moduleparam.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/gpio.h>
0013 #include <linux/timer.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/workqueue.h>
0016 #include <linux/hte.h>
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 static struct tegra_hte_test {
0052 int gpio_in_irq;
0053 struct device *pdev;
0054 struct gpio_desc *gpio_in;
0055 struct gpio_desc *gpio_out;
0056 struct hte_ts_desc *desc;
0057 struct timer_list timer;
0058 struct kobject *kobj;
0059 } hte;
0060
0061 static enum hte_return process_hw_ts(struct hte_ts_data *ts, void *p)
0062 {
0063 char *edge;
0064 struct hte_ts_desc *desc = p;
0065
0066 if (!ts || !p)
0067 return HTE_CB_HANDLED;
0068
0069 if (ts->raw_level < 0)
0070 edge = "Unknown";
0071
0072 pr_info("HW timestamp(%u: %llu): %llu, edge: %s\n",
0073 desc->attr.line_id, ts->seq, ts->tsc,
0074 (ts->raw_level >= 0) ? ((ts->raw_level == 0) ?
0075 "falling" : "rising") : edge);
0076
0077 return HTE_CB_HANDLED;
0078 }
0079
0080 static void gpio_timer_cb(struct timer_list *t)
0081 {
0082 (void)t;
0083
0084 gpiod_set_value(hte.gpio_out, !gpiod_get_value(hte.gpio_out));
0085 mod_timer(&hte.timer, jiffies + msecs_to_jiffies(8000));
0086 }
0087
0088 static irqreturn_t tegra_hte_test_gpio_isr(int irq, void *data)
0089 {
0090 (void)irq;
0091 (void)data;
0092
0093 return IRQ_HANDLED;
0094 }
0095
0096 static const struct of_device_id tegra_hte_test_of_match[] = {
0097 { .compatible = "nvidia,tegra194-hte-test"},
0098 { }
0099 };
0100 MODULE_DEVICE_TABLE(of, tegra_hte_test_of_match);
0101
0102 static int tegra_hte_test_probe(struct platform_device *pdev)
0103 {
0104 int ret = 0;
0105 int i, cnt;
0106
0107 dev_set_drvdata(&pdev->dev, &hte);
0108 hte.pdev = &pdev->dev;
0109
0110 hte.gpio_out = gpiod_get(&pdev->dev, "out", 0);
0111 if (IS_ERR(hte.gpio_out)) {
0112 dev_err(&pdev->dev, "failed to get gpio out\n");
0113 ret = -EINVAL;
0114 goto out;
0115 }
0116
0117 hte.gpio_in = gpiod_get(&pdev->dev, "in", 0);
0118 if (IS_ERR(hte.gpio_in)) {
0119 dev_err(&pdev->dev, "failed to get gpio in\n");
0120 ret = -EINVAL;
0121 goto free_gpio_out;
0122 }
0123
0124 ret = gpiod_direction_output(hte.gpio_out, 0);
0125 if (ret) {
0126 dev_err(&pdev->dev, "failed to set output\n");
0127 ret = -EINVAL;
0128 goto free_gpio_in;
0129 }
0130
0131 ret = gpiod_direction_input(hte.gpio_in);
0132 if (ret) {
0133 dev_err(&pdev->dev, "failed to set input\n");
0134 ret = -EINVAL;
0135 goto free_gpio_in;
0136 }
0137
0138 ret = gpiod_to_irq(hte.gpio_in);
0139 if (ret < 0) {
0140 dev_err(&pdev->dev, "failed to map GPIO to IRQ: %d\n", ret);
0141 ret = -ENXIO;
0142 goto free_gpio_in;
0143 }
0144
0145 hte.gpio_in_irq = ret;
0146 ret = request_irq(ret, tegra_hte_test_gpio_isr,
0147 IRQF_TRIGGER_RISING,
0148 "tegra_hte_gpio_test_isr", &hte);
0149 if (ret) {
0150 dev_err(&pdev->dev, "failed to acquire IRQ\n");
0151 ret = -ENXIO;
0152 goto free_irq;
0153 }
0154
0155 cnt = of_hte_req_count(hte.pdev);
0156 if (cnt < 0)
0157 goto free_irq;
0158
0159 dev_info(&pdev->dev, "Total requested lines:%d\n", cnt);
0160
0161 hte.desc = devm_kzalloc(hte.pdev, sizeof(*hte.desc) * cnt, GFP_KERNEL);
0162 if (!hte.desc) {
0163 ret = -ENOMEM;
0164 goto free_irq;
0165 }
0166
0167 for (i = 0; i < cnt; i++) {
0168 if (i == 0)
0169
0170
0171
0172
0173
0174
0175 hte_init_line_attr(&hte.desc[i], 0, 0, NULL,
0176 hte.gpio_in);
0177 else
0178
0179
0180
0181
0182 hte_init_line_attr(&hte.desc[i], 0, 0, NULL, NULL);
0183
0184 ret = hte_ts_get(hte.pdev, &hte.desc[i], i);
0185 if (ret)
0186 goto ts_put;
0187
0188 ret = devm_hte_request_ts_ns(hte.pdev, &hte.desc[i],
0189 process_hw_ts, NULL,
0190 &hte.desc[i]);
0191 if (ret)
0192 goto free_irq;
0193 }
0194
0195 timer_setup(&hte.timer, gpio_timer_cb, 0);
0196 mod_timer(&hte.timer, jiffies + msecs_to_jiffies(5000));
0197
0198 return 0;
0199
0200 ts_put:
0201 cnt = i;
0202 for (i = 0; i < cnt; i++)
0203 hte_ts_put(&hte.desc[i]);
0204 free_irq:
0205 free_irq(hte.gpio_in_irq, &hte);
0206 free_gpio_in:
0207 gpiod_put(hte.gpio_in);
0208 free_gpio_out:
0209 gpiod_put(hte.gpio_out);
0210 out:
0211
0212 return ret;
0213 }
0214
0215 static int tegra_hte_test_remove(struct platform_device *pdev)
0216 {
0217 (void)pdev;
0218
0219 free_irq(hte.gpio_in_irq, &hte);
0220 gpiod_put(hte.gpio_in);
0221 gpiod_put(hte.gpio_out);
0222 del_timer_sync(&hte.timer);
0223
0224 return 0;
0225 }
0226
0227 static struct platform_driver tegra_hte_test_driver = {
0228 .probe = tegra_hte_test_probe,
0229 .remove = tegra_hte_test_remove,
0230 .driver = {
0231 .name = "tegra_hte_test",
0232 .of_match_table = tegra_hte_test_of_match,
0233 },
0234 };
0235 module_platform_driver(tegra_hte_test_driver);
0236
0237 MODULE_AUTHOR("Dipen Patel <dipenp@nvidia.com>");
0238 MODULE_LICENSE("GPL");