.. | .. |
---|
16 | 16 | * (C) 2015-2016 Chunyan Zhang <zhang.chunyan@linaro.org> |
---|
17 | 17 | */ |
---|
18 | 18 | #include <asm/local.h> |
---|
| 19 | +#include <linux/acpi.h> |
---|
19 | 20 | #include <linux/amba/bus.h> |
---|
20 | 21 | #include <linux/bitmap.h> |
---|
21 | 22 | #include <linux/clk.h> |
---|
.. | .. |
---|
107 | 108 | unsigned long *guaranteed; |
---|
108 | 109 | }; |
---|
109 | 110 | |
---|
| 111 | +DEFINE_CORESIGHT_DEVLIST(stm_devs, "stm"); |
---|
| 112 | + |
---|
110 | 113 | /** |
---|
111 | 114 | * struct stm_drvdata - specifics associated to an STM component |
---|
112 | 115 | * @base: memory mapped base address for this component. |
---|
113 | | - * @dev: the device entity associated to this component. |
---|
114 | 116 | * @atclk: optional clock for the core parts of the STM. |
---|
115 | 117 | * @csdev: component vitals needed by the framework. |
---|
116 | 118 | * @spinlock: only one at a time pls. |
---|
.. | .. |
---|
128 | 130 | */ |
---|
129 | 131 | struct stm_drvdata { |
---|
130 | 132 | void __iomem *base; |
---|
131 | | - struct device *dev; |
---|
132 | 133 | struct clk *atclk; |
---|
133 | 134 | struct coresight_device *csdev; |
---|
134 | 135 | spinlock_t spinlock; |
---|
.. | .. |
---|
205 | 206 | if (val) |
---|
206 | 207 | return -EBUSY; |
---|
207 | 208 | |
---|
208 | | - pm_runtime_get_sync(drvdata->dev); |
---|
| 209 | + pm_runtime_get_sync(csdev->dev.parent); |
---|
209 | 210 | |
---|
210 | 211 | spin_lock(&drvdata->spinlock); |
---|
211 | 212 | stm_enable_hw(drvdata); |
---|
212 | 213 | spin_unlock(&drvdata->spinlock); |
---|
213 | 214 | |
---|
214 | | - dev_dbg(drvdata->dev, "STM tracing enabled\n"); |
---|
| 215 | + dev_dbg(&csdev->dev, "STM tracing enabled\n"); |
---|
215 | 216 | return 0; |
---|
216 | 217 | } |
---|
217 | 218 | |
---|
.. | .. |
---|
257 | 258 | struct perf_event *event) |
---|
258 | 259 | { |
---|
259 | 260 | struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); |
---|
| 261 | + struct csdev_access *csa = &csdev->access; |
---|
260 | 262 | |
---|
261 | 263 | /* |
---|
262 | 264 | * For as long as the tracer isn't disabled another entity can't |
---|
.. | .. |
---|
269 | 271 | spin_unlock(&drvdata->spinlock); |
---|
270 | 272 | |
---|
271 | 273 | /* Wait until the engine has completely stopped */ |
---|
272 | | - coresight_timeout(drvdata->base, STMTCSR, STMTCSR_BUSY_BIT, 0); |
---|
| 274 | + coresight_timeout(csa, STMTCSR, STMTCSR_BUSY_BIT, 0); |
---|
273 | 275 | |
---|
274 | | - pm_runtime_put(drvdata->dev); |
---|
| 276 | + pm_runtime_put(csdev->dev.parent); |
---|
275 | 277 | |
---|
276 | 278 | local_set(&drvdata->mode, CS_MODE_DISABLED); |
---|
277 | | - dev_dbg(drvdata->dev, "STM tracing disabled\n"); |
---|
| 279 | + dev_dbg(&csdev->dev, "STM tracing disabled\n"); |
---|
278 | 280 | } |
---|
279 | 281 | } |
---|
280 | 282 | |
---|
.. | .. |
---|
411 | 413 | void __iomem *ch_addr; |
---|
412 | 414 | struct stm_drvdata *drvdata = container_of(stm_data, |
---|
413 | 415 | struct stm_drvdata, stm); |
---|
| 416 | + unsigned int stm_flags; |
---|
414 | 417 | |
---|
415 | 418 | if (!(drvdata && local_read(&drvdata->mode))) |
---|
416 | 419 | return -EACCES; |
---|
.. | .. |
---|
420 | 423 | |
---|
421 | 424 | ch_addr = stm_channel_addr(drvdata, channel); |
---|
422 | 425 | |
---|
423 | | - flags = (flags == STP_PACKET_TIMESTAMPED) ? STM_FLAG_TIMESTAMPED : 0; |
---|
424 | | - flags |= test_bit(channel, drvdata->chs.guaranteed) ? |
---|
| 426 | + stm_flags = (flags & STP_PACKET_TIMESTAMPED) ? |
---|
| 427 | + STM_FLAG_TIMESTAMPED : 0; |
---|
| 428 | + stm_flags |= test_bit(channel, drvdata->chs.guaranteed) ? |
---|
425 | 429 | STM_FLAG_GUARANTEED : 0; |
---|
426 | 430 | |
---|
427 | 431 | if (size > drvdata->write_bytes) |
---|
.. | .. |
---|
431 | 435 | |
---|
432 | 436 | switch (packet) { |
---|
433 | 437 | case STP_PACKET_FLAG: |
---|
434 | | - ch_addr += stm_channel_off(STM_PKT_TYPE_FLAG, flags); |
---|
| 438 | + ch_addr += stm_channel_off(STM_PKT_TYPE_FLAG, stm_flags); |
---|
435 | 439 | |
---|
436 | 440 | /* |
---|
437 | 441 | * The generic STM core sets a size of '0' on flag packets. |
---|
.. | .. |
---|
443 | 447 | break; |
---|
444 | 448 | |
---|
445 | 449 | case STP_PACKET_DATA: |
---|
446 | | - ch_addr += stm_channel_off(STM_PKT_TYPE_DATA, flags); |
---|
| 450 | + stm_flags |= (flags & STP_PACKET_MARKED) ? STM_FLAG_MARKED : 0; |
---|
| 451 | + ch_addr += stm_channel_off(STM_PKT_TYPE_DATA, stm_flags); |
---|
447 | 452 | stm_send(ch_addr, payload, size, |
---|
448 | 453 | drvdata->write_bytes); |
---|
449 | 454 | break; |
---|
.. | .. |
---|
685 | 690 | NULL, |
---|
686 | 691 | }; |
---|
687 | 692 | |
---|
688 | | -static int stm_get_resource_byname(struct device_node *np, |
---|
689 | | - char *ch_base, struct resource *res) |
---|
| 693 | +#ifdef CONFIG_OF |
---|
| 694 | +static int of_stm_get_stimulus_area(struct device *dev, struct resource *res) |
---|
690 | 695 | { |
---|
691 | 696 | const char *name = NULL; |
---|
692 | 697 | int index = 0, found = 0; |
---|
| 698 | + struct device_node *np = dev->of_node; |
---|
693 | 699 | |
---|
694 | 700 | while (!of_property_read_string_index(np, "reg-names", index, &name)) { |
---|
695 | | - if (strcmp(ch_base, name)) { |
---|
| 701 | + if (strcmp("stm-stimulus-base", name)) { |
---|
696 | 702 | index++; |
---|
697 | 703 | continue; |
---|
698 | 704 | } |
---|
.. | .. |
---|
706 | 712 | return -EINVAL; |
---|
707 | 713 | |
---|
708 | 714 | return of_address_to_resource(np, index, res); |
---|
| 715 | +} |
---|
| 716 | +#else |
---|
| 717 | +static inline int of_stm_get_stimulus_area(struct device *dev, |
---|
| 718 | + struct resource *res) |
---|
| 719 | +{ |
---|
| 720 | + return -ENOENT; |
---|
| 721 | +} |
---|
| 722 | +#endif |
---|
| 723 | + |
---|
| 724 | +#ifdef CONFIG_ACPI |
---|
| 725 | +static int acpi_stm_get_stimulus_area(struct device *dev, struct resource *res) |
---|
| 726 | +{ |
---|
| 727 | + int rc; |
---|
| 728 | + bool found_base = false; |
---|
| 729 | + struct resource_entry *rent; |
---|
| 730 | + LIST_HEAD(res_list); |
---|
| 731 | + |
---|
| 732 | + struct acpi_device *adev = ACPI_COMPANION(dev); |
---|
| 733 | + |
---|
| 734 | + rc = acpi_dev_get_resources(adev, &res_list, NULL, NULL); |
---|
| 735 | + if (rc < 0) |
---|
| 736 | + return rc; |
---|
| 737 | + |
---|
| 738 | + /* |
---|
| 739 | + * The stimulus base for STM device must be listed as the second memory |
---|
| 740 | + * resource, followed by the programming base address as described in |
---|
| 741 | + * "Section 2.3 Resources" in ACPI for CoreSightTM 1.0 Platform Design |
---|
| 742 | + * document (DEN0067). |
---|
| 743 | + */ |
---|
| 744 | + rc = -ENOENT; |
---|
| 745 | + list_for_each_entry(rent, &res_list, node) { |
---|
| 746 | + if (resource_type(rent->res) != IORESOURCE_MEM) |
---|
| 747 | + continue; |
---|
| 748 | + if (found_base) { |
---|
| 749 | + *res = *rent->res; |
---|
| 750 | + rc = 0; |
---|
| 751 | + break; |
---|
| 752 | + } |
---|
| 753 | + |
---|
| 754 | + found_base = true; |
---|
| 755 | + } |
---|
| 756 | + |
---|
| 757 | + acpi_dev_free_resource_list(&res_list); |
---|
| 758 | + return rc; |
---|
| 759 | +} |
---|
| 760 | +#else |
---|
| 761 | +static inline int acpi_stm_get_stimulus_area(struct device *dev, |
---|
| 762 | + struct resource *res) |
---|
| 763 | +{ |
---|
| 764 | + return -ENOENT; |
---|
| 765 | +} |
---|
| 766 | +#endif |
---|
| 767 | + |
---|
| 768 | +static int stm_get_stimulus_area(struct device *dev, struct resource *res) |
---|
| 769 | +{ |
---|
| 770 | + struct fwnode_handle *fwnode = dev_fwnode(dev); |
---|
| 771 | + |
---|
| 772 | + if (is_of_node(fwnode)) |
---|
| 773 | + return of_stm_get_stimulus_area(dev, res); |
---|
| 774 | + else if (is_acpi_node(fwnode)) |
---|
| 775 | + return acpi_stm_get_stimulus_area(dev, res); |
---|
| 776 | + return -ENOENT; |
---|
709 | 777 | } |
---|
710 | 778 | |
---|
711 | 779 | static u32 stm_fundamental_data_size(struct stm_drvdata *drvdata) |
---|
.. | .. |
---|
763 | 831 | bitmap_clear(drvdata->chs.guaranteed, 0, drvdata->numsp); |
---|
764 | 832 | } |
---|
765 | 833 | |
---|
766 | | -static void stm_init_generic_data(struct stm_drvdata *drvdata) |
---|
| 834 | +static void stm_init_generic_data(struct stm_drvdata *drvdata, |
---|
| 835 | + const char *name) |
---|
767 | 836 | { |
---|
768 | | - drvdata->stm.name = dev_name(drvdata->dev); |
---|
| 837 | + drvdata->stm.name = name; |
---|
769 | 838 | |
---|
770 | 839 | /* |
---|
771 | 840 | * MasterIDs are assigned at HW design phase. As such the core is |
---|
.. | .. |
---|
793 | 862 | struct stm_drvdata *drvdata; |
---|
794 | 863 | struct resource *res = &adev->res; |
---|
795 | 864 | struct resource ch_res; |
---|
796 | | - size_t res_size, bitmap_size; |
---|
| 865 | + size_t bitmap_size; |
---|
797 | 866 | struct coresight_desc desc = { 0 }; |
---|
798 | | - struct device_node *np = adev->dev.of_node; |
---|
799 | 867 | |
---|
800 | | - if (np) { |
---|
801 | | - pdata = of_get_coresight_platform_data(dev, np); |
---|
802 | | - if (IS_ERR(pdata)) |
---|
803 | | - return PTR_ERR(pdata); |
---|
804 | | - adev->dev.platform_data = pdata; |
---|
805 | | - } |
---|
| 868 | + desc.name = coresight_alloc_device_name(&stm_devs, dev); |
---|
| 869 | + if (!desc.name) |
---|
| 870 | + return -ENOMEM; |
---|
| 871 | + |
---|
806 | 872 | drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); |
---|
807 | 873 | if (!drvdata) |
---|
808 | 874 | return -ENOMEM; |
---|
809 | 875 | |
---|
810 | | - drvdata->dev = &adev->dev; |
---|
811 | 876 | drvdata->atclk = devm_clk_get(&adev->dev, "atclk"); /* optional */ |
---|
812 | 877 | if (!IS_ERR(drvdata->atclk)) { |
---|
813 | 878 | ret = clk_prepare_enable(drvdata->atclk); |
---|
.. | .. |
---|
820 | 885 | if (IS_ERR(base)) |
---|
821 | 886 | return PTR_ERR(base); |
---|
822 | 887 | drvdata->base = base; |
---|
| 888 | + desc.access = CSDEV_ACCESS_IOMEM(base); |
---|
823 | 889 | |
---|
824 | | - ret = stm_get_resource_byname(np, "stm-stimulus-base", &ch_res); |
---|
| 890 | + ret = stm_get_stimulus_area(dev, &ch_res); |
---|
825 | 891 | if (ret) |
---|
826 | 892 | return ret; |
---|
827 | 893 | drvdata->chs.phys = ch_res.start; |
---|
.. | .. |
---|
833 | 899 | |
---|
834 | 900 | drvdata->write_bytes = stm_fundamental_data_size(drvdata); |
---|
835 | 901 | |
---|
836 | | - if (boot_nr_channel) { |
---|
| 902 | + if (boot_nr_channel) |
---|
837 | 903 | drvdata->numsp = boot_nr_channel; |
---|
838 | | - res_size = min((resource_size_t)(boot_nr_channel * |
---|
839 | | - BYTES_PER_CHANNEL), resource_size(res)); |
---|
840 | | - } else { |
---|
| 904 | + else |
---|
841 | 905 | drvdata->numsp = stm_num_stimulus_port(drvdata); |
---|
842 | | - res_size = min((resource_size_t)(drvdata->numsp * |
---|
843 | | - BYTES_PER_CHANNEL), resource_size(res)); |
---|
844 | | - } |
---|
| 906 | + |
---|
845 | 907 | bitmap_size = BITS_TO_LONGS(drvdata->numsp) * sizeof(long); |
---|
846 | 908 | |
---|
847 | 909 | guaranteed = devm_kzalloc(dev, bitmap_size, GFP_KERNEL); |
---|
.. | .. |
---|
852 | 914 | spin_lock_init(&drvdata->spinlock); |
---|
853 | 915 | |
---|
854 | 916 | stm_init_default_data(drvdata); |
---|
855 | | - stm_init_generic_data(drvdata); |
---|
| 917 | + stm_init_generic_data(drvdata, desc.name); |
---|
856 | 918 | |
---|
857 | 919 | if (stm_register_device(dev, &drvdata->stm, THIS_MODULE)) { |
---|
858 | 920 | dev_info(dev, |
---|
859 | | - "stm_register_device failed, probing deffered\n"); |
---|
| 921 | + "%s : stm_register_device failed, probing deferred\n", |
---|
| 922 | + desc.name); |
---|
860 | 923 | return -EPROBE_DEFER; |
---|
861 | 924 | } |
---|
| 925 | + |
---|
| 926 | + pdata = coresight_get_platform_data(dev); |
---|
| 927 | + if (IS_ERR(pdata)) { |
---|
| 928 | + ret = PTR_ERR(pdata); |
---|
| 929 | + goto stm_unregister; |
---|
| 930 | + } |
---|
| 931 | + adev->dev.platform_data = pdata; |
---|
862 | 932 | |
---|
863 | 933 | desc.type = CORESIGHT_DEV_TYPE_SOURCE; |
---|
864 | 934 | desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE; |
---|
.. | .. |
---|
874 | 944 | |
---|
875 | 945 | pm_runtime_put(&adev->dev); |
---|
876 | 946 | |
---|
877 | | - dev_info(dev, "%s initialized\n", (char *)id->data); |
---|
| 947 | + dev_info(&drvdata->csdev->dev, "%s initialized\n", |
---|
| 948 | + (char *)coresight_get_uci_data(id)); |
---|
878 | 949 | return 0; |
---|
879 | 950 | |
---|
880 | 951 | stm_unregister: |
---|
881 | 952 | stm_unregister_device(&drvdata->stm); |
---|
882 | 953 | return ret; |
---|
| 954 | +} |
---|
| 955 | + |
---|
| 956 | +static void stm_remove(struct amba_device *adev) |
---|
| 957 | +{ |
---|
| 958 | + struct stm_drvdata *drvdata = dev_get_drvdata(&adev->dev); |
---|
| 959 | + |
---|
| 960 | + coresight_unregister(drvdata->csdev); |
---|
| 961 | + |
---|
| 962 | + stm_unregister_device(&drvdata->stm); |
---|
883 | 963 | } |
---|
884 | 964 | |
---|
885 | 965 | #ifdef CONFIG_PM |
---|
.. | .. |
---|
909 | 989 | }; |
---|
910 | 990 | |
---|
911 | 991 | static const struct amba_id stm_ids[] = { |
---|
912 | | - { |
---|
913 | | - .id = 0x000bb962, |
---|
914 | | - .mask = 0x000fffff, |
---|
915 | | - .data = "STM32", |
---|
916 | | - }, |
---|
917 | | - { |
---|
918 | | - .id = 0x000bb963, |
---|
919 | | - .mask = 0x000fffff, |
---|
920 | | - .data = "STM500", |
---|
921 | | - }, |
---|
| 992 | + CS_AMBA_ID_DATA(0x000bb962, "STM32"), |
---|
| 993 | + CS_AMBA_ID_DATA(0x000bb963, "STM500"), |
---|
922 | 994 | { 0, 0}, |
---|
923 | 995 | }; |
---|
| 996 | + |
---|
| 997 | +MODULE_DEVICE_TABLE(amba, stm_ids); |
---|
924 | 998 | |
---|
925 | 999 | static struct amba_driver stm_driver = { |
---|
926 | 1000 | .drv = { |
---|
.. | .. |
---|
930 | 1004 | .suppress_bind_attrs = true, |
---|
931 | 1005 | }, |
---|
932 | 1006 | .probe = stm_probe, |
---|
| 1007 | + .remove = stm_remove, |
---|
933 | 1008 | .id_table = stm_ids, |
---|
934 | 1009 | }; |
---|
935 | 1010 | |
---|
936 | | -builtin_amba_driver(stm_driver); |
---|
| 1011 | +module_amba_driver(stm_driver); |
---|
| 1012 | + |
---|
| 1013 | +MODULE_AUTHOR("Pratik Patel <pratikp@codeaurora.org>"); |
---|
| 1014 | +MODULE_DESCRIPTION("Arm CoreSight System Trace Macrocell driver"); |
---|
| 1015 | +MODULE_LICENSE("GPL v2"); |
---|