Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'tegra-for-4.8-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into next/drivers

soc/tegra: Changes for v4.8-rc1

Contains fixes and cleanups to the PMC driver, as well as some fixes for
the generic PM domain support and some prep work to support PCIe on 64-
bit ARM.

* tag 'tegra-for-4.8-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
soc/tegra: Stub out PCIe IRQ workaround on 64-bit ARM
soc/tegra: pmc: Enable XUSB partitions on boot
soc/tegra: pmc: Initialise power partitions early
soc/tegra: pmc: Add specific error messages
soc/tegra: pmc: Use whitespace more consistently
soc/tegra: pmc: Don't probe PMC if early initialisation fails
soc/tegra: pmc: Add missing of_node_put()
soc/tegra: pmc: Ensure mutex is always initialised
soc/tegra: pmc: Don't populate SoC data until register space is mapped
soc/tegra: pmc: Fix early initialisation of PMC
soc/tegra: pmc: Ensure powergate is available when powering on
soc/tegra: pmc: Initialise resets associated with a power partition
soc/tegra: pmc: Use register definitions instead of magic values

Signed-off-by: Olof Johansson <olof@lixom.net>

+116 -41
+115 -40
drivers/soc/tegra/pmc.c
··· 51 51 #define PMC_CNTRL_CPU_PWRREQ_POLARITY (1 << 15) /* CPU pwr req polarity */ 52 52 #define PMC_CNTRL_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */ 53 53 #define PMC_CNTRL_INTR_POLARITY (1 << 17) /* inverts INTR polarity */ 54 + #define PMC_CNTRL_MAIN_RST (1 << 4) 54 55 55 56 #define DPD_SAMPLE 0x020 56 57 #define DPD_SAMPLE_ENABLE (1 << 0) ··· 80 79 #define PMC_SENSOR_CTRL 0x1b0 81 80 #define PMC_SENSOR_CTRL_SCRATCH_WRITE (1 << 2) 82 81 #define PMC_SENSOR_CTRL_ENABLE_RST (1 << 1) 82 + 83 + #define PMC_RST_STATUS 0x1b4 84 + #define PMC_RST_STATUS_POR 0 85 + #define PMC_RST_STATUS_WATCHDOG 1 86 + #define PMC_RST_STATUS_SENSOR 2 87 + #define PMC_RST_STATUS_SW_MAIN 3 88 + #define PMC_RST_STATUS_LP0 4 89 + #define PMC_RST_STATUS_AOTAG 5 83 90 84 91 #define IO_DPD_REQ 0x1b8 85 92 #define IO_DPD_REQ_CODE_IDLE (0 << 30) ··· 408 399 disable_clks: 409 400 tegra_powergate_disable_clocks(pg); 410 401 usleep_range(10, 20); 402 + 411 403 powergate_off: 412 404 tegra_powergate_set(pg->id, false); 413 405 ··· 446 436 usleep_range(10, 20); 447 437 tegra_powergate_reset_deassert(pg); 448 438 usleep_range(10, 20); 439 + 449 440 disable_clks: 450 441 tegra_powergate_disable_clocks(pg); 451 442 ··· 551 540 struct tegra_powergate pg; 552 541 int err; 553 542 543 + if (!tegra_powergate_is_available(id)) 544 + return -EINVAL; 545 + 554 546 pg.id = id; 555 547 pg.clks = &clk; 556 548 pg.num_clks = 1; ··· 652 638 653 639 tegra_pmc_writel(value, PMC_SCRATCH0); 654 640 655 - value = tegra_pmc_readl(0); 656 - value |= 0x10; 657 - tegra_pmc_writel(value, 0); 641 + /* reset everything but PMC_SCRATCH0 and PMC_RST_STATUS */ 642 + value = tegra_pmc_readl(PMC_CNTRL); 643 + value |= PMC_CNTRL_MAIN_RST; 644 + tegra_pmc_writel(value, PMC_CNTRL); 658 645 659 646 return NOTIFY_DONE; 660 647 } ··· 737 722 err: 738 723 while (i--) 739 724 clk_put(pg->clks[i]); 725 + 740 726 kfree(pg->clks); 741 727 742 728 return err; 743 729 } 744 730 745 731 static int tegra_powergate_of_get_resets(struct tegra_powergate *pg, 746 - struct device_node *np) 732 + struct device_node *np, bool off) 747 733 { 748 734 struct reset_control *rst; 749 735 unsigned int i, count; ··· 764 748 err = PTR_ERR(pg->resets[i]); 765 749 goto error; 766 750 } 751 + 752 + if (off) 753 + err = reset_control_assert(pg->resets[i]); 754 + else 755 + err = reset_control_deassert(pg->resets[i]); 756 + 757 + if (err) { 758 + reset_control_put(pg->resets[i]); 759 + goto error; 760 + } 767 761 } 768 762 769 763 pg->num_resets = count; ··· 783 757 error: 784 758 while (i--) 785 759 reset_control_put(pg->resets[i]); 760 + 786 761 kfree(pg->resets); 787 762 788 763 return err; ··· 792 765 static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np) 793 766 { 794 767 struct tegra_powergate *pg; 768 + int id, err; 795 769 bool off; 796 - int id; 797 770 798 771 pg = kzalloc(sizeof(*pg), GFP_KERNEL); 799 772 if (!pg) 800 - goto error; 773 + return; 801 774 802 775 id = tegra_powergate_lookup(pmc, np->name); 803 - if (id < 0) 776 + if (id < 0) { 777 + dev_err(pmc->dev, "powergate lookup failed for %s: %d\n", 778 + np->name, id); 804 779 goto free_mem; 780 + } 805 781 806 782 /* 807 783 * Clear the bit for this powergate so it cannot be managed ··· 818 788 pg->genpd.power_on = tegra_genpd_power_on; 819 789 pg->pmc = pmc; 820 790 821 - if (tegra_powergate_of_get_clks(pg, np)) 822 - goto set_available; 823 - 824 - if (tegra_powergate_of_get_resets(pg, np)) 825 - goto remove_clks; 826 - 827 791 off = !tegra_powergate_is_powered(pg->id); 792 + 793 + err = tegra_powergate_of_get_clks(pg, np); 794 + if (err < 0) { 795 + dev_err(pmc->dev, "failed to get clocks for %s: %d\n", 796 + np->name, err); 797 + goto set_available; 798 + } 799 + 800 + err = tegra_powergate_of_get_resets(pg, np, off); 801 + if (err < 0) { 802 + dev_err(pmc->dev, "failed to get resets for %s: %d\n", 803 + np->name, err); 804 + goto remove_clks; 805 + } 806 + 807 + if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) 808 + goto power_on_cleanup; 809 + 810 + /* 811 + * FIXME: If XHCI is enabled for Tegra, then power-up the XUSB 812 + * host and super-speed partitions. Once the XHCI driver 813 + * manages the partitions itself this code can be removed. Note 814 + * that we don't register these partitions with the genpd core 815 + * to avoid it from powering down the partitions as they appear 816 + * to be unused. 817 + */ 818 + if (IS_ENABLED(CONFIG_USB_XHCI_TEGRA) && 819 + (id == TEGRA_POWERGATE_XUSBA || id == TEGRA_POWERGATE_XUSBC)) 820 + goto power_on_cleanup; 828 821 829 822 pm_genpd_init(&pg->genpd, NULL, off); 830 823 831 - if (of_genpd_add_provider_simple(np, &pg->genpd)) 824 + err = of_genpd_add_provider_simple(np, &pg->genpd); 825 + if (err < 0) { 826 + dev_err(pmc->dev, "failed to add genpd provider for %s: %d\n", 827 + np->name, err); 832 828 goto remove_resets; 829 + } 833 830 834 831 dev_dbg(pmc->dev, "added power domain %s\n", pg->genpd.name); 835 832 836 833 return; 837 834 835 + power_on_cleanup: 836 + if (off) 837 + WARN_ON(tegra_powergate_power_up(pg, true)); 838 + 838 839 remove_resets: 839 840 while (pg->num_resets--) 840 841 reset_control_put(pg->resets[pg->num_resets]); 842 + 841 843 kfree(pg->resets); 842 844 843 845 remove_clks: 844 846 while (pg->num_clks--) 845 847 clk_put(pg->clks[pg->num_clks]); 848 + 846 849 kfree(pg->clks); 847 850 848 851 set_available: ··· 883 820 884 821 free_mem: 885 822 kfree(pg); 886 - 887 - error: 888 - dev_err(pmc->dev, "failed to create power domain for %s\n", np->name); 889 823 } 890 824 891 - static void tegra_powergate_init(struct tegra_pmc *pmc) 825 + static void tegra_powergate_init(struct tegra_pmc *pmc, 826 + struct device_node *parent) 892 827 { 893 828 struct device_node *np, *child; 829 + unsigned int i; 894 830 895 - np = of_get_child_by_name(pmc->dev->of_node, "powergates"); 831 + /* Create a bitmap of the available and valid partitions */ 832 + for (i = 0; i < pmc->soc->num_powergates; i++) 833 + if (pmc->soc->powergates[i]) 834 + set_bit(i, pmc->powergates_available); 835 + 836 + np = of_get_child_by_name(parent, "powergates"); 896 837 if (!np) 897 838 return; 898 839 ··· 1272 1205 struct resource *res; 1273 1206 int err; 1274 1207 1208 + /* 1209 + * Early initialisation should have configured an initial 1210 + * register mapping and setup the soc data pointer. If these 1211 + * are not valid then something went badly wrong! 1212 + */ 1213 + if (WARN_ON(!pmc->base || !pmc->soc)) 1214 + return -ENODEV; 1215 + 1275 1216 err = tegra_pmc_parse_dt(pmc, pdev->dev.of_node); 1276 1217 if (err < 0) 1277 1218 return err; ··· 1316 1241 err); 1317 1242 return err; 1318 1243 } 1319 - 1320 - tegra_powergate_init(pmc); 1321 1244 1322 1245 mutex_lock(&pmc->powergates_lock); 1323 1246 iounmap(pmc->base); ··· 1550 1477 const struct of_device_id *match; 1551 1478 struct device_node *np; 1552 1479 struct resource regs; 1553 - unsigned int i; 1554 1480 bool invert; 1555 1481 u32 value; 1482 + 1483 + mutex_init(&pmc->powergates_lock); 1556 1484 1557 1485 np = of_find_matching_node_and_match(NULL, tegra_pmc_match, &match); 1558 1486 if (!np) { ··· 1589 1515 */ 1590 1516 if (of_address_to_resource(np, 0, &regs) < 0) { 1591 1517 pr_err("failed to get PMC registers\n"); 1518 + of_node_put(np); 1592 1519 return -ENXIO; 1593 1520 } 1594 - 1595 - pmc->soc = match->data; 1596 1521 } 1597 1522 1598 1523 pmc->base = ioremap_nocache(regs.start, resource_size(&regs)); 1599 1524 if (!pmc->base) { 1600 1525 pr_err("failed to map PMC registers\n"); 1526 + of_node_put(np); 1601 1527 return -ENXIO; 1602 1528 } 1603 1529 1604 - /* Create a bit-map of the available and valid partitions */ 1605 - for (i = 0; i < pmc->soc->num_powergates; i++) 1606 - if (pmc->soc->powergates[i]) 1607 - set_bit(i, pmc->powergates_available); 1530 + if (np) { 1531 + pmc->soc = match->data; 1608 1532 1609 - mutex_init(&pmc->powergates_lock); 1533 + tegra_powergate_init(pmc, np); 1610 1534 1611 - /* 1612 - * Invert the interrupt polarity if a PMC device tree node exists and 1613 - * contains the nvidia,invert-interrupt property. 1614 - */ 1615 - invert = of_property_read_bool(np, "nvidia,invert-interrupt"); 1535 + /* 1536 + * Invert the interrupt polarity if a PMC device tree node 1537 + * exists and contains the nvidia,invert-interrupt property. 1538 + */ 1539 + invert = of_property_read_bool(np, "nvidia,invert-interrupt"); 1616 1540 1617 - value = tegra_pmc_readl(PMC_CNTRL); 1541 + value = tegra_pmc_readl(PMC_CNTRL); 1618 1542 1619 - if (invert) 1620 - value |= PMC_CNTRL_INTR_POLARITY; 1621 - else 1622 - value &= ~PMC_CNTRL_INTR_POLARITY; 1543 + if (invert) 1544 + value |= PMC_CNTRL_INTR_POLARITY; 1545 + else 1546 + value &= ~PMC_CNTRL_INTR_POLARITY; 1623 1547 1624 - tegra_pmc_writel(value, PMC_CNTRL); 1548 + tegra_pmc_writel(value, PMC_CNTRL); 1549 + 1550 + of_node_put(np); 1551 + } 1625 1552 1626 1553 return 0; 1627 1554 }
+1 -1
include/soc/tegra/cpuidle.h
··· 14 14 #ifndef __SOC_TEGRA_CPUIDLE_H__ 15 15 #define __SOC_TEGRA_CPUIDLE_H__ 16 16 17 - #ifdef CONFIG_CPU_IDLE 17 + #if defined(CONFIG_ARM) && defined(CONFIG_CPU_IDLE) 18 18 void tegra_cpuidle_pcie_irqs_in_use(void); 19 19 #else 20 20 static inline void tegra_cpuidle_pcie_irqs_in_use(void)