.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * ARM-specific support for Broadcom STB S2/S3/S5 power management |
---|
3 | 4 | * |
---|
.. | .. |
---|
8 | 9 | * treat this mode like a soft power-off, with wakeup allowed from AON |
---|
9 | 10 | * |
---|
10 | 11 | * Copyright © 2014-2017 Broadcom |
---|
11 | | - * |
---|
12 | | - * This program is free software; you can redistribute it and/or modify |
---|
13 | | - * it under the terms of the GNU General Public License version 2 as |
---|
14 | | - * published by the Free Software Foundation. |
---|
15 | | - * |
---|
16 | | - * This program is distributed in the hope that it will be useful, |
---|
17 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
18 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
19 | | - * GNU General Public License for more details. |
---|
20 | 12 | */ |
---|
21 | 13 | |
---|
22 | 14 | #define pr_fmt(fmt) "brcmstb-pm: " fmt |
---|
.. | .. |
---|
689 | 681 | const struct of_device_id *of_id = NULL; |
---|
690 | 682 | struct device_node *dn; |
---|
691 | 683 | void __iomem *base; |
---|
692 | | - int ret, i; |
---|
| 684 | + int ret, i, s; |
---|
693 | 685 | |
---|
694 | 686 | /* AON ctrl registers */ |
---|
695 | 687 | base = brcmstb_ioremap_match(aon_ctrl_dt_ids, 0, NULL); |
---|
696 | 688 | if (IS_ERR(base)) { |
---|
697 | 689 | pr_err("error mapping AON_CTRL\n"); |
---|
698 | | - return PTR_ERR(base); |
---|
| 690 | + ret = PTR_ERR(base); |
---|
| 691 | + goto aon_err; |
---|
699 | 692 | } |
---|
700 | 693 | ctrl.aon_ctrl_base = base; |
---|
701 | 694 | |
---|
.. | .. |
---|
705 | 698 | /* Assume standard offset */ |
---|
706 | 699 | ctrl.aon_sram = ctrl.aon_ctrl_base + |
---|
707 | 700 | AON_CTRL_SYSTEM_DATA_RAM_OFS; |
---|
| 701 | + s = 0; |
---|
708 | 702 | } else { |
---|
709 | 703 | ctrl.aon_sram = base; |
---|
| 704 | + s = 1; |
---|
710 | 705 | } |
---|
711 | 706 | |
---|
712 | 707 | writel_relaxed(0, ctrl.aon_sram + AON_REG_PANIC); |
---|
.. | .. |
---|
716 | 711 | (const void **)&ddr_phy_data); |
---|
717 | 712 | if (IS_ERR(base)) { |
---|
718 | 713 | pr_err("error mapping DDR PHY\n"); |
---|
719 | | - return PTR_ERR(base); |
---|
| 714 | + ret = PTR_ERR(base); |
---|
| 715 | + goto ddr_phy_err; |
---|
720 | 716 | } |
---|
721 | 717 | ctrl.support_warm_boot = ddr_phy_data->supports_warm_boot; |
---|
722 | 718 | ctrl.pll_status_offset = ddr_phy_data->pll_status_offset; |
---|
.. | .. |
---|
736 | 732 | for_each_matching_node(dn, ddr_shimphy_dt_ids) { |
---|
737 | 733 | i = ctrl.num_memc; |
---|
738 | 734 | if (i >= MAX_NUM_MEMC) { |
---|
| 735 | + of_node_put(dn); |
---|
739 | 736 | pr_warn("too many MEMCs (max %d)\n", MAX_NUM_MEMC); |
---|
740 | 737 | break; |
---|
741 | 738 | } |
---|
742 | 739 | |
---|
743 | 740 | base = of_io_request_and_map(dn, 0, dn->full_name); |
---|
744 | 741 | if (IS_ERR(base)) { |
---|
| 742 | + of_node_put(dn); |
---|
745 | 743 | if (!ctrl.support_warm_boot) |
---|
746 | 744 | break; |
---|
747 | 745 | |
---|
748 | 746 | pr_err("error mapping DDR SHIMPHY %d\n", i); |
---|
749 | | - return PTR_ERR(base); |
---|
| 747 | + ret = PTR_ERR(base); |
---|
| 748 | + goto ddr_shimphy_err; |
---|
750 | 749 | } |
---|
751 | 750 | ctrl.memcs[i].ddr_shimphy_base = base; |
---|
752 | 751 | ctrl.num_memc++; |
---|
.. | .. |
---|
757 | 756 | for_each_matching_node(dn, brcmstb_memc_of_match) { |
---|
758 | 757 | base = of_iomap(dn, 0); |
---|
759 | 758 | if (!base) { |
---|
| 759 | + of_node_put(dn); |
---|
760 | 760 | pr_err("error mapping DDR Sequencer %d\n", i); |
---|
761 | | - return -ENOMEM; |
---|
| 761 | + ret = -ENOMEM; |
---|
| 762 | + goto brcmstb_memc_err; |
---|
762 | 763 | } |
---|
763 | 764 | |
---|
764 | 765 | of_id = of_match_node(brcmstb_memc_of_match, dn); |
---|
765 | 766 | if (!of_id) { |
---|
766 | 767 | iounmap(base); |
---|
767 | | - return -EINVAL; |
---|
| 768 | + of_node_put(dn); |
---|
| 769 | + ret = -EINVAL; |
---|
| 770 | + goto brcmstb_memc_err; |
---|
768 | 771 | } |
---|
769 | 772 | |
---|
770 | 773 | ddr_seq_data = of_id->data; |
---|
.. | .. |
---|
784 | 787 | dn = of_find_matching_node(NULL, sram_dt_ids); |
---|
785 | 788 | if (!dn) { |
---|
786 | 789 | pr_err("SRAM not found\n"); |
---|
787 | | - return -EINVAL; |
---|
| 790 | + ret = -EINVAL; |
---|
| 791 | + goto brcmstb_memc_err; |
---|
788 | 792 | } |
---|
789 | 793 | |
---|
790 | 794 | ret = brcmstb_init_sram(dn); |
---|
| 795 | + of_node_put(dn); |
---|
791 | 796 | if (ret) { |
---|
792 | 797 | pr_err("error setting up SRAM for PM\n"); |
---|
793 | | - return ret; |
---|
| 798 | + goto brcmstb_memc_err; |
---|
794 | 799 | } |
---|
795 | 800 | |
---|
796 | 801 | ctrl.pdev = pdev; |
---|
797 | 802 | |
---|
798 | 803 | ctrl.s3_params = kmalloc(sizeof(*ctrl.s3_params), GFP_KERNEL); |
---|
799 | | - if (!ctrl.s3_params) |
---|
800 | | - return -ENOMEM; |
---|
| 804 | + if (!ctrl.s3_params) { |
---|
| 805 | + ret = -ENOMEM; |
---|
| 806 | + goto s3_params_err; |
---|
| 807 | + } |
---|
801 | 808 | ctrl.s3_params_pa = dma_map_single(&pdev->dev, ctrl.s3_params, |
---|
802 | 809 | sizeof(*ctrl.s3_params), |
---|
803 | 810 | DMA_TO_DEVICE); |
---|
.. | .. |
---|
817 | 824 | |
---|
818 | 825 | out: |
---|
819 | 826 | kfree(ctrl.s3_params); |
---|
| 827 | +s3_params_err: |
---|
| 828 | + iounmap(ctrl.boot_sram); |
---|
| 829 | +brcmstb_memc_err: |
---|
| 830 | + for (i--; i >= 0; i--) |
---|
| 831 | + iounmap(ctrl.memcs[i].ddr_ctrl); |
---|
| 832 | +ddr_shimphy_err: |
---|
| 833 | + for (i = 0; i < ctrl.num_memc; i++) |
---|
| 834 | + iounmap(ctrl.memcs[i].ddr_shimphy_base); |
---|
820 | 835 | |
---|
| 836 | + iounmap(ctrl.memcs[0].ddr_phy_base); |
---|
| 837 | +ddr_phy_err: |
---|
| 838 | + iounmap(ctrl.aon_ctrl_base); |
---|
| 839 | + if (s) |
---|
| 840 | + iounmap(ctrl.aon_sram); |
---|
| 841 | +aon_err: |
---|
821 | 842 | pr_warn("PM: initialization failed with code %d\n", ret); |
---|
822 | 843 | |
---|
823 | 844 | return ret; |
---|