| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/device.h>
- #include <linux/cpumask.h>
- #include <linux/list.h>
- #include <linux/printk.h>
- #include <linux/platform_device.h>
- #include <linux/kallsyms.h>
- #include <linux/of_address.h>
- #include <linux/slab.h>
- #include <linux/io.h>
- #include <mt-plat/mt_chip.h>
- #include <mt-plat/mt_debug_latch.h>
- #include "lastbus.h"
- static const struct of_device_id lastbus_of_ids[] = {
- {}
- };
- static int lastbus_probe(struct platform_device *pdev);
- static int lastbus_remove(struct platform_device *pdev);
- static int lastbus_suspend(struct platform_device *pdev, pm_message_t state);
- static int lastbus_resume(struct platform_device *pdev);
- static char *lastbus_dump_buf;
- static struct lastbus lastbus_drv = {
- .plt_drv = {
- .driver = {
- .name = "lastbus",
- .bus = &platform_bus_type,
- .owner = THIS_MODULE,
- .of_match_table = lastbus_of_ids,
- },
- .probe = lastbus_probe,
- .remove = lastbus_remove,
- .suspend = lastbus_suspend,
- .resume = lastbus_resume,
- },
- };
- static int lastbus_probe(struct platform_device *pdev)
- {
- struct lastbus_plt *plt = NULL;
- pr_debug("%s:%d: enter\n", __func__, __LINE__);
- plt = lastbus_drv.cur_plt;
- if (plt && plt->ops && plt->ops->probe)
- return plt->ops->probe(plt, pdev);
- lastbus_drv.mcu_base = of_iomap(pdev->dev.of_node, 0);
- lastbus_drv.peri_base = of_iomap(pdev->dev.of_node, 1);
- if (!lastbus_drv.mcu_base || !lastbus_drv.peri_base)
- return -ENODEV;
- return 0;
- }
- static int lastbus_remove(struct platform_device *pdev)
- {
- struct lastbus_plt *plt = lastbus_drv.cur_plt;
- pr_debug("%s:%d: enter\n", __func__, __LINE__);
- if (plt && plt->ops && plt->ops->remove)
- return plt->ops->remove(plt, pdev);
- return 0;
- }
- static int lastbus_suspend(struct platform_device *pdev, pm_message_t state)
- {
- struct lastbus_plt *plt = lastbus_drv.cur_plt;
- pr_debug("%s:%d: enter\n", __func__, __LINE__);
- if (plt && plt->ops && plt->ops->suspend)
- return plt->ops->suspend(plt, pdev, state);
- return 0;
- }
- static int lastbus_resume(struct platform_device *pdev)
- {
- struct lastbus_plt *plt = lastbus_drv.cur_plt;
- pr_debug("%s:%d: enter\n", __func__, __LINE__);
- if (plt && plt->ops && plt->ops->resume)
- return plt->ops->resume(plt, pdev);
- return 0;
- }
- int lastbus_register(struct lastbus_plt *plt)
- {
- if (!plt) {
- pr_warn("%s%d: plt is NULL\n", __func__, __LINE__);
- return -EINVAL;
- }
- plt->common = &lastbus_drv;
- lastbus_drv.cur_plt = plt;
- return 0;
- }
- int lastbus_dump(char *buf, int len)
- {
- struct lastbus_plt *plt = lastbus_drv.cur_plt;
- if (!buf) {
- pr_warn("%s:%d: buf is NULL\n", __func__, __LINE__);
- return -EINVAL;
- }
- if (!plt) {
- pr_warn("%s:%d: plt is NULL\n", __func__, __LINE__);
- return -ENODEV;
- }
- if (!plt->common) {
- pr_warn("%s:%d: plt->common is NULL\n", __func__, __LINE__);
- return -ENODEV;
- }
- if (!plt->common->mcu_base)
- pr_warn("%s:%d: plt->common->mcu_base is NULL\n", __func__, __LINE__);
- if (!plt->common->peri_base)
- pr_warn("%s:%d: plt->common->peri_base is NULL\n", __func__, __LINE__);
- if (!plt->common->mcu_base && !plt->common->peri_base)
- return -ENODEV;
- if (plt->ops && plt->ops->dump)
- return plt->ops->dump(plt, buf, len);
- pr_warn("no dump function implemented\n");
- return 0;
- }
- int lastbus_enable(void)
- {
- struct lastbus_plt *plt = lastbus_drv.cur_plt;
- if (!plt) {
- pr_warn("%s:%d: plt is NULL\n", __func__, __LINE__);
- return -ENODEV;
- }
- if (!plt->common) {
- pr_warn("%s:%d: plt->common is NULL\n", __func__, __LINE__);
- return -ENODEV;
- }
- if (!plt->common->mcu_base)
- pr_warn("%s:%d: plt->common->mcu_base is NULL\n", __func__, __LINE__);
- if (!plt->common->peri_base)
- pr_warn("%s:%d: plt->common->peri_base is NULL\n", __func__, __LINE__);
- if (!plt->common->mcu_base && !plt->common->peri_base)
- return -ENODEV;
- if (plt->ops && plt->ops->enable)
- return plt->ops->enable(plt);
- pr_warn("no enable function implemented\n");
- return 0;
- }
- int lastbus_dump_min_len(void)
- {
- struct lastbus_plt *plt = lastbus_drv.cur_plt;
- if (!plt) {
- pr_warn("%s:%d: plt is NULL\n", __func__, __LINE__);
- return -ENODEV;
- }
- if (!plt->min_buf_len)
- pr_warn("%s:%d: min_buf_len is 0\n", __func__, __LINE__);
- return plt->min_buf_len;
- }
- int mt_lastbus_dump(char *buf)
- {
- strncpy(buf, lastbus_dump_buf, strlen(lastbus_dump_buf)+1);
- return 0;
- }
- static ssize_t lastbus_dump_show(struct device_driver *driver, char *buf)
- {
- struct lastbus_plt *plt = lastbus_drv.cur_plt;
- int ret = 0;
- ret = plt->ops->dump(plt, buf, -1);
- if (ret)
- pr_err("%s:%d: dump failed\n", __func__, __LINE__);
- return strlen(buf);
- }
- static ssize_t lastbus_dump_store(struct device_driver *driver, const char *buf, size_t count)
- {
- return count;
- }
- DRIVER_ATTR(lastbus_dump, 0664, lastbus_dump_show, lastbus_dump_store);
- static ssize_t lastbus_test_show(struct device_driver *driver, char *buf)
- {
- struct lastbus_plt *plt = lastbus_drv.cur_plt;
- if (plt && plt->ops)
- return plt->ops->test_show(buf);
- return -ENODEV;
- }
- static ssize_t lastbus_test_store(struct device_driver *driver, const char *buf, size_t count)
- {
- struct lastbus_plt *plt = lastbus_drv.cur_plt;
- char *p = (char *)buf;
- unsigned long num = 0;
- if (kstrtoul(p, 10, &num) != 0) {
- pr_err("%s:%d: kstrtoul fail for %s\n", __func__, __LINE__, p);
- return 0;
- }
- if (plt && plt->ops && (plt->ops->test(plt, num) != 0))
- pr_err("%s:%d: test failed\n", __func__, __LINE__);
- return count;
- }
- DRIVER_ATTR(lastbus_test, 0664, lastbus_test_show, lastbus_test_store);
- static int lastbus_start(void)
- {
- struct lastbus_plt *plt = lastbus_drv.cur_plt;
- if (!plt)
- return -ENODEV;
- if (!plt->ops) {
- pr_err("%s:%d: ops not installed\n", __func__, __LINE__);
- return -ENODEV;
- }
- if (plt->ops->start)
- return plt->ops->start(plt);
- return 0;
- }
- static int __init lastbus_init(void)
- {
- struct device_node *node;
- int ret = 0;
- node = of_find_compatible_node(NULL, NULL, "mediatek,lastbus");
- if (node) {
- lastbus_drv.mcu_base = of_iomap(node, 0);
- lastbus_drv.peri_base = of_iomap(node, 1);
- } else {
- pr_err("can't find compatible node for lastbus\n");
- return -1;
- }
- ret = lastbus_start();
- if (ret) {
- pr_err("%s:%d: lastbus_start failed\n", __func__, __LINE__);
- return -ENODEV;
- }
- /* since kernel already populates dts, our probe would be callback after this registration */
- ret = platform_driver_register(&lastbus_drv.plt_drv);
- if (ret) {
- pr_err("%s:%d: platform_driver_register failed\n", __func__, __LINE__);
- return -ENODEV;
- }
- ret = driver_create_file(&lastbus_drv.plt_drv.driver, &driver_attr_lastbus_dump);
- if (ret)
- pr_err("%s:%d: driver_create_file failed.\n", __func__, __LINE__);
- ret = driver_create_file(&lastbus_drv.plt_drv.driver, &driver_attr_lastbus_test);
- if (ret)
- pr_err("%s:%d: driver_create_file failed.\n", __func__, __LINE__);
- lastbus_dump_buf = kzalloc(lastbus_drv.cur_plt->min_buf_len, GFP_KERNEL);
- if (!lastbus_dump_buf)
- return -ENOMEM;
- /* we dump here and then return lastbus_dump_buf
- to users to prevent lastbus values cleaned by low power mechanism
- (MCUSYS might be turned off before lastbus_dump()) */
- lastbus_dump(lastbus_dump_buf, lastbus_drv.cur_plt->min_buf_len);
- lastbus_enable();
- return 0;
- }
- postcore_initcall(lastbus_init);
|