.. | .. |
---|
1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
---|
2 | 2 | // Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. |
---|
3 | 3 | |
---|
| 4 | +#include <linux/acpi.h> |
---|
4 | 5 | #include <linux/clk.h> |
---|
5 | 6 | #include <linux/slab.h> |
---|
6 | 7 | #include <linux/dma-mapping.h> |
---|
.. | .. |
---|
90 | 91 | void __iomem *base; |
---|
91 | 92 | struct clk_bulk_data ahb_clks[NUM_AHB_CLKS]; |
---|
92 | 93 | }; |
---|
| 94 | + |
---|
| 95 | +static const char * const icc_path_names[] = {"qup-core", "qup-config", |
---|
| 96 | + "qup-memory"}; |
---|
93 | 97 | |
---|
94 | 98 | #define QUP_HW_VER_REG 0x4 |
---|
95 | 99 | |
---|
.. | .. |
---|
215 | 219 | writel_relaxed(FORCE_DEFAULT, base + GENI_FORCE_DEFAULT_REG); |
---|
216 | 220 | } |
---|
217 | 221 | |
---|
| 222 | +static void geni_se_irq_clear(struct geni_se *se) |
---|
| 223 | +{ |
---|
| 224 | + writel_relaxed(0, se->base + SE_GSI_EVENT_EN); |
---|
| 225 | + writel_relaxed(0xffffffff, se->base + SE_GENI_M_IRQ_CLEAR); |
---|
| 226 | + writel_relaxed(0xffffffff, se->base + SE_GENI_S_IRQ_CLEAR); |
---|
| 227 | + writel_relaxed(0xffffffff, se->base + SE_DMA_TX_IRQ_CLR); |
---|
| 228 | + writel_relaxed(0xffffffff, se->base + SE_DMA_RX_IRQ_CLR); |
---|
| 229 | + writel_relaxed(0xffffffff, se->base + SE_IRQ_EN); |
---|
| 230 | +} |
---|
| 231 | + |
---|
218 | 232 | /** |
---|
219 | 233 | * geni_se_init() - Initialize the GENI serial engine |
---|
220 | 234 | * @se: Pointer to the concerned serial engine. |
---|
.. | .. |
---|
228 | 242 | { |
---|
229 | 243 | u32 val; |
---|
230 | 244 | |
---|
| 245 | + geni_se_irq_clear(se); |
---|
231 | 246 | geni_se_io_init(se->base); |
---|
232 | 247 | geni_se_io_set_mode(se->base); |
---|
233 | 248 | |
---|
.. | .. |
---|
249 | 264 | u32 proto = geni_se_read_proto(se); |
---|
250 | 265 | u32 val; |
---|
251 | 266 | |
---|
252 | | - writel_relaxed(0, se->base + SE_GSI_EVENT_EN); |
---|
253 | | - writel_relaxed(0xffffffff, se->base + SE_GENI_M_IRQ_CLEAR); |
---|
254 | | - writel_relaxed(0xffffffff, se->base + SE_GENI_S_IRQ_CLEAR); |
---|
255 | | - writel_relaxed(0xffffffff, se->base + SE_DMA_TX_IRQ_CLR); |
---|
256 | | - writel_relaxed(0xffffffff, se->base + SE_DMA_RX_IRQ_CLR); |
---|
257 | | - writel_relaxed(0xffffffff, se->base + SE_IRQ_EN); |
---|
| 267 | + geni_se_irq_clear(se); |
---|
258 | 268 | |
---|
259 | 269 | val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN); |
---|
260 | 270 | if (proto != GENI_SE_UART) { |
---|
.. | .. |
---|
278 | 288 | u32 proto = geni_se_read_proto(se); |
---|
279 | 289 | u32 val; |
---|
280 | 290 | |
---|
281 | | - writel_relaxed(0, se->base + SE_GSI_EVENT_EN); |
---|
282 | | - writel_relaxed(0xffffffff, se->base + SE_GENI_M_IRQ_CLEAR); |
---|
283 | | - writel_relaxed(0xffffffff, se->base + SE_GENI_S_IRQ_CLEAR); |
---|
284 | | - writel_relaxed(0xffffffff, se->base + SE_DMA_TX_IRQ_CLR); |
---|
285 | | - writel_relaxed(0xffffffff, se->base + SE_DMA_RX_IRQ_CLR); |
---|
286 | | - writel_relaxed(0xffffffff, se->base + SE_IRQ_EN); |
---|
| 291 | + geni_se_irq_clear(se); |
---|
287 | 292 | |
---|
288 | 293 | val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN); |
---|
289 | 294 | if (proto != GENI_SE_UART) { |
---|
.. | .. |
---|
462 | 467 | { |
---|
463 | 468 | int ret; |
---|
464 | 469 | |
---|
| 470 | + if (has_acpi_companion(se->dev)) |
---|
| 471 | + return 0; |
---|
| 472 | + |
---|
465 | 473 | ret = pinctrl_pm_select_sleep_state(se->dev); |
---|
466 | 474 | if (ret) |
---|
467 | 475 | return ret; |
---|
.. | .. |
---|
498 | 506 | int geni_se_resources_on(struct geni_se *se) |
---|
499 | 507 | { |
---|
500 | 508 | int ret; |
---|
| 509 | + |
---|
| 510 | + if (has_acpi_companion(se->dev)) |
---|
| 511 | + return 0; |
---|
501 | 512 | |
---|
502 | 513 | ret = geni_se_clks_on(se); |
---|
503 | 514 | if (ret) |
---|
.. | .. |
---|
635 | 646 | struct geni_wrapper *wrapper = se->wrapper; |
---|
636 | 647 | u32 val; |
---|
637 | 648 | |
---|
| 649 | + if (!wrapper) |
---|
| 650 | + return -EINVAL; |
---|
| 651 | + |
---|
638 | 652 | *iova = dma_map_single(wrapper->dev, buf, len, DMA_TO_DEVICE); |
---|
639 | 653 | if (dma_mapping_error(wrapper->dev, *iova)) |
---|
640 | 654 | return -EIO; |
---|
.. | .. |
---|
667 | 681 | { |
---|
668 | 682 | struct geni_wrapper *wrapper = se->wrapper; |
---|
669 | 683 | u32 val; |
---|
| 684 | + |
---|
| 685 | + if (!wrapper) |
---|
| 686 | + return -EINVAL; |
---|
670 | 687 | |
---|
671 | 688 | *iova = dma_map_single(wrapper->dev, buf, len, DMA_FROM_DEVICE); |
---|
672 | 689 | if (dma_mapping_error(wrapper->dev, *iova)) |
---|
.. | .. |
---|
719 | 736 | } |
---|
720 | 737 | EXPORT_SYMBOL(geni_se_rx_dma_unprep); |
---|
721 | 738 | |
---|
| 739 | +int geni_icc_get(struct geni_se *se, const char *icc_ddr) |
---|
| 740 | +{ |
---|
| 741 | + int i, err; |
---|
| 742 | + const char *icc_names[] = {"qup-core", "qup-config", icc_ddr}; |
---|
| 743 | + |
---|
| 744 | + if (has_acpi_companion(se->dev)) |
---|
| 745 | + return 0; |
---|
| 746 | + |
---|
| 747 | + for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) { |
---|
| 748 | + if (!icc_names[i]) |
---|
| 749 | + continue; |
---|
| 750 | + |
---|
| 751 | + se->icc_paths[i].path = devm_of_icc_get(se->dev, icc_names[i]); |
---|
| 752 | + if (IS_ERR(se->icc_paths[i].path)) |
---|
| 753 | + goto err; |
---|
| 754 | + } |
---|
| 755 | + |
---|
| 756 | + return 0; |
---|
| 757 | + |
---|
| 758 | +err: |
---|
| 759 | + err = PTR_ERR(se->icc_paths[i].path); |
---|
| 760 | + if (err != -EPROBE_DEFER) |
---|
| 761 | + dev_err_ratelimited(se->dev, "Failed to get ICC path '%s': %d\n", |
---|
| 762 | + icc_names[i], err); |
---|
| 763 | + return err; |
---|
| 764 | + |
---|
| 765 | +} |
---|
| 766 | +EXPORT_SYMBOL(geni_icc_get); |
---|
| 767 | + |
---|
| 768 | +int geni_icc_set_bw(struct geni_se *se) |
---|
| 769 | +{ |
---|
| 770 | + int i, ret; |
---|
| 771 | + |
---|
| 772 | + for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) { |
---|
| 773 | + ret = icc_set_bw(se->icc_paths[i].path, |
---|
| 774 | + se->icc_paths[i].avg_bw, se->icc_paths[i].avg_bw); |
---|
| 775 | + if (ret) { |
---|
| 776 | + dev_err_ratelimited(se->dev, "ICC BW voting failed on path '%s': %d\n", |
---|
| 777 | + icc_path_names[i], ret); |
---|
| 778 | + return ret; |
---|
| 779 | + } |
---|
| 780 | + } |
---|
| 781 | + |
---|
| 782 | + return 0; |
---|
| 783 | +} |
---|
| 784 | +EXPORT_SYMBOL(geni_icc_set_bw); |
---|
| 785 | + |
---|
| 786 | +void geni_icc_set_tag(struct geni_se *se, u32 tag) |
---|
| 787 | +{ |
---|
| 788 | + int i; |
---|
| 789 | + |
---|
| 790 | + for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) |
---|
| 791 | + icc_set_tag(se->icc_paths[i].path, tag); |
---|
| 792 | +} |
---|
| 793 | +EXPORT_SYMBOL(geni_icc_set_tag); |
---|
| 794 | + |
---|
| 795 | +/* To do: Replace this by icc_bulk_enable once it's implemented in ICC core */ |
---|
| 796 | +int geni_icc_enable(struct geni_se *se) |
---|
| 797 | +{ |
---|
| 798 | + int i, ret; |
---|
| 799 | + |
---|
| 800 | + for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) { |
---|
| 801 | + ret = icc_enable(se->icc_paths[i].path); |
---|
| 802 | + if (ret) { |
---|
| 803 | + dev_err_ratelimited(se->dev, "ICC enable failed on path '%s': %d\n", |
---|
| 804 | + icc_path_names[i], ret); |
---|
| 805 | + return ret; |
---|
| 806 | + } |
---|
| 807 | + } |
---|
| 808 | + |
---|
| 809 | + return 0; |
---|
| 810 | +} |
---|
| 811 | +EXPORT_SYMBOL(geni_icc_enable); |
---|
| 812 | + |
---|
| 813 | +int geni_icc_disable(struct geni_se *se) |
---|
| 814 | +{ |
---|
| 815 | + int i, ret; |
---|
| 816 | + |
---|
| 817 | + for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) { |
---|
| 818 | + ret = icc_disable(se->icc_paths[i].path); |
---|
| 819 | + if (ret) { |
---|
| 820 | + dev_err_ratelimited(se->dev, "ICC disable failed on path '%s': %d\n", |
---|
| 821 | + icc_path_names[i], ret); |
---|
| 822 | + return ret; |
---|
| 823 | + } |
---|
| 824 | + } |
---|
| 825 | + |
---|
| 826 | + return 0; |
---|
| 827 | +} |
---|
| 828 | +EXPORT_SYMBOL(geni_icc_disable); |
---|
| 829 | + |
---|
722 | 830 | static int geni_se_probe(struct platform_device *pdev) |
---|
723 | 831 | { |
---|
724 | 832 | struct device *dev = &pdev->dev; |
---|
.. | .. |
---|
736 | 844 | if (IS_ERR(wrapper->base)) |
---|
737 | 845 | return PTR_ERR(wrapper->base); |
---|
738 | 846 | |
---|
739 | | - wrapper->ahb_clks[0].id = "m-ahb"; |
---|
740 | | - wrapper->ahb_clks[1].id = "s-ahb"; |
---|
741 | | - ret = devm_clk_bulk_get(dev, NUM_AHB_CLKS, wrapper->ahb_clks); |
---|
742 | | - if (ret) { |
---|
743 | | - dev_err(dev, "Err getting AHB clks %d\n", ret); |
---|
744 | | - return ret; |
---|
| 847 | + if (!has_acpi_companion(&pdev->dev)) { |
---|
| 848 | + wrapper->ahb_clks[0].id = "m-ahb"; |
---|
| 849 | + wrapper->ahb_clks[1].id = "s-ahb"; |
---|
| 850 | + ret = devm_clk_bulk_get(dev, NUM_AHB_CLKS, wrapper->ahb_clks); |
---|
| 851 | + if (ret) { |
---|
| 852 | + dev_err(dev, "Err getting AHB clks %d\n", ret); |
---|
| 853 | + return ret; |
---|
| 854 | + } |
---|
745 | 855 | } |
---|
746 | 856 | |
---|
747 | 857 | dev_set_drvdata(dev, wrapper); |
---|