| .. | .. |
|---|
| 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; |
|---|