diff options
author | Olof Johansson <olof@lixom.net> | 2017-06-18 23:46:30 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2017-06-18 23:46:30 -0400 |
commit | 2b1ee3061f09bd90a5c659b9cb45fcbf49c5fd4c (patch) | |
tree | 37fc6c42bc227468e0c60869fd60e59685726135 /arch/arm/mach-omap2/omap_hwmod.c | |
parent | 6198c74939c085fbd31fab3ba6f1eb2ce2820b39 (diff) | |
parent | 1df5eaa6bced2d8a9de305d4a5f587adf57ddf35 (diff) |
Merge tag 'omap-for-v4.13/soc-v4-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/soc
SoC changes for omap variants for v4.13 merge window:
- PM clean-up in preparation of adding am335x/am437x PM support
- Fixes for issues found by Coccinelle
- Legacy code removal now that everything boots in device
tree only mode
- Interconnect changes in preparation of moving clkctrl clocks
to be managed by clkctrl clock driver
- Interconnect changes to add omap4 crypto acceclerator
support
* tag 'omap-for-v4.13/soc-v4-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: (27 commits)
ARM: OMAP4: hwmod_data: add SHAM crypto accelerator
ARM: OMAP4: hwmod data: add des
ARM: OMAP4: hwmod data: add aes2
ARM: OMAP4: hwmod data: add aes1
ARM: OMAP2+: Remove unused legacy code for n8x0
ARM: OMAP2+: Remove unused legacy code for watchdog
ARM: OMAP2+: Remove unused legacy code for interconnects
ARM: OMAP2+: Remove unused legacy code for PRM
ARM: OMAP2+: Remove unused legacy code for io.c
ARM: OMAP2+: Remove unused legacy code for McBSP
ARM: OMAP2+: SmartReflex: Delete an error message for a failed memory allocation in two functions
ARM: OMAP2+: Use kcalloc() in sr_set_nvalues()
ARM: OMAP2+: Improve a size determination in sr_dev_init()
ARM: OMAP2+: Delete an error message for a failed memory allocation in two functions
ARM: OMAP2+: Remove unused legacy code for device init
ARM: OMAP2+: Remove unused legacy code for PMU
ARM: OMAP2+: Remove unused legacy code for opp
ARM: OMAP2+: hwmod: populate clkctrl clocks for hwmods if available
ARM: OMAP4: cminst: add support for clkdm_xlate_address
ARM: omap2+: clockdomain: add clkdm_xlate_address
...
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 168 |
1 files changed, 140 insertions, 28 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 8bcea0d83fa0..3b47ded5fa0c 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c | |||
@@ -141,6 +141,7 @@ | |||
141 | #include <linux/cpu.h> | 141 | #include <linux/cpu.h> |
142 | #include <linux/of.h> | 142 | #include <linux/of.h> |
143 | #include <linux/of_address.h> | 143 | #include <linux/of_address.h> |
144 | #include <linux/bootmem.h> | ||
144 | 145 | ||
145 | #include <asm/system_misc.h> | 146 | #include <asm/system_misc.h> |
146 | 147 | ||
@@ -182,6 +183,24 @@ | |||
182 | #define MOD_CLK_MAX_NAME_LEN 32 | 183 | #define MOD_CLK_MAX_NAME_LEN 32 |
183 | 184 | ||
184 | /** | 185 | /** |
186 | * struct clkctrl_provider - clkctrl provider mapping data | ||
187 | * @addr: base address for the provider | ||
188 | * @offset: base offset for the provider | ||
189 | * @clkdm: base clockdomain for provider | ||
190 | * @node: device node associated with the provider | ||
191 | * @link: list link | ||
192 | */ | ||
193 | struct clkctrl_provider { | ||
194 | u32 addr; | ||
195 | u16 offset; | ||
196 | struct clockdomain *clkdm; | ||
197 | struct device_node *node; | ||
198 | struct list_head link; | ||
199 | }; | ||
200 | |||
201 | static LIST_HEAD(clkctrl_providers); | ||
202 | |||
203 | /** | ||
185 | * struct omap_hwmod_soc_ops - fn ptrs for some SoC-specific operations | 204 | * struct omap_hwmod_soc_ops - fn ptrs for some SoC-specific operations |
186 | * @enable_module: function to enable a module (via MODULEMODE) | 205 | * @enable_module: function to enable a module (via MODULEMODE) |
187 | * @disable_module: function to disable a module (via MODULEMODE) | 206 | * @disable_module: function to disable a module (via MODULEMODE) |
@@ -204,6 +223,8 @@ struct omap_hwmod_soc_ops { | |||
204 | void (*update_context_lost)(struct omap_hwmod *oh); | 223 | void (*update_context_lost)(struct omap_hwmod *oh); |
205 | int (*get_context_lost)(struct omap_hwmod *oh); | 224 | int (*get_context_lost)(struct omap_hwmod *oh); |
206 | int (*disable_direct_prcm)(struct omap_hwmod *oh); | 225 | int (*disable_direct_prcm)(struct omap_hwmod *oh); |
226 | u32 (*xlate_clkctrl)(struct omap_hwmod *oh, | ||
227 | struct clkctrl_provider *provider); | ||
207 | }; | 228 | }; |
208 | 229 | ||
209 | /* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */ | 230 | /* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */ |
@@ -690,6 +711,103 @@ static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh) | |||
690 | return clkdm_del_sleepdep(clkdm, init_clkdm); | 711 | return clkdm_del_sleepdep(clkdm, init_clkdm); |
691 | } | 712 | } |
692 | 713 | ||
714 | static const struct of_device_id ti_clkctrl_match_table[] __initconst = { | ||
715 | { .compatible = "ti,clkctrl" }, | ||
716 | { } | ||
717 | }; | ||
718 | |||
719 | static int _match_clkdm(struct clockdomain *clkdm, void *user) | ||
720 | { | ||
721 | struct clkctrl_provider *provider = user; | ||
722 | |||
723 | if (clkdm_xlate_address(clkdm) == provider->addr) { | ||
724 | pr_debug("%s: Matched clkdm %s for addr %x (%s)\n", __func__, | ||
725 | clkdm->name, provider->addr, | ||
726 | provider->node->parent->name); | ||
727 | provider->clkdm = clkdm; | ||
728 | |||
729 | return -1; | ||
730 | } | ||
731 | |||
732 | return 0; | ||
733 | } | ||
734 | |||
735 | static int _setup_clkctrl_provider(struct device_node *np) | ||
736 | { | ||
737 | const __be32 *addrp; | ||
738 | struct clkctrl_provider *provider; | ||
739 | |||
740 | provider = memblock_virt_alloc(sizeof(*provider), 0); | ||
741 | if (!provider) | ||
742 | return -ENOMEM; | ||
743 | |||
744 | addrp = of_get_address(np, 0, NULL, NULL); | ||
745 | provider->addr = (u32)of_translate_address(np, addrp); | ||
746 | provider->offset = provider->addr & 0xff; | ||
747 | provider->addr &= ~0xff; | ||
748 | provider->node = np; | ||
749 | |||
750 | clkdm_for_each(_match_clkdm, provider); | ||
751 | |||
752 | if (!provider->clkdm) { | ||
753 | pr_err("%s: nothing matched for node %s (%x)\n", | ||
754 | __func__, np->parent->name, provider->addr); | ||
755 | memblock_free_early(__pa(provider), sizeof(*provider)); | ||
756 | return -EINVAL; | ||
757 | } | ||
758 | |||
759 | list_add(&provider->link, &clkctrl_providers); | ||
760 | |||
761 | return 0; | ||
762 | } | ||
763 | |||
764 | static int _init_clkctrl_providers(void) | ||
765 | { | ||
766 | struct device_node *np; | ||
767 | int ret = 0; | ||
768 | |||
769 | for_each_matching_node(np, ti_clkctrl_match_table) { | ||
770 | ret = _setup_clkctrl_provider(np); | ||
771 | if (ret) | ||
772 | break; | ||
773 | } | ||
774 | |||
775 | return ret; | ||
776 | } | ||
777 | |||
778 | static u32 _omap4_xlate_clkctrl(struct omap_hwmod *oh, | ||
779 | struct clkctrl_provider *provider) | ||
780 | { | ||
781 | return oh->prcm.omap4.clkctrl_offs - | ||
782 | provider->offset - provider->clkdm->clkdm_offs; | ||
783 | } | ||
784 | |||
785 | static struct clk *_lookup_clkctrl_clk(struct omap_hwmod *oh) | ||
786 | { | ||
787 | struct clkctrl_provider *provider; | ||
788 | struct clk *clk; | ||
789 | |||
790 | if (!soc_ops.xlate_clkctrl) | ||
791 | return NULL; | ||
792 | |||
793 | list_for_each_entry(provider, &clkctrl_providers, link) { | ||
794 | if (provider->clkdm == oh->clkdm) { | ||
795 | struct of_phandle_args clkspec; | ||
796 | |||
797 | clkspec.np = provider->node; | ||
798 | clkspec.args_count = 2; | ||
799 | clkspec.args[0] = soc_ops.xlate_clkctrl(oh, provider); | ||
800 | clkspec.args[1] = 0; | ||
801 | |||
802 | clk = of_clk_get_from_provider(&clkspec); | ||
803 | |||
804 | return clk; | ||
805 | } | ||
806 | } | ||
807 | |||
808 | return NULL; | ||
809 | } | ||
810 | |||
693 | /** | 811 | /** |
694 | * _init_main_clk - get a struct clk * for the the hwmod's main functional clk | 812 | * _init_main_clk - get a struct clk * for the the hwmod's main functional clk |
695 | * @oh: struct omap_hwmod * | 813 | * @oh: struct omap_hwmod * |
@@ -701,22 +819,16 @@ static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh) | |||
701 | static int _init_main_clk(struct omap_hwmod *oh) | 819 | static int _init_main_clk(struct omap_hwmod *oh) |
702 | { | 820 | { |
703 | int ret = 0; | 821 | int ret = 0; |
704 | char name[MOD_CLK_MAX_NAME_LEN]; | 822 | struct clk *clk = NULL; |
705 | struct clk *clk; | ||
706 | static const char modck[] = "_mod_ck"; | ||
707 | 823 | ||
708 | if (strlen(oh->name) >= MOD_CLK_MAX_NAME_LEN - strlen(modck)) | 824 | clk = _lookup_clkctrl_clk(oh); |
709 | pr_warn("%s: warning: cropping name for %s\n", __func__, | ||
710 | oh->name); | ||
711 | |||
712 | strlcpy(name, oh->name, MOD_CLK_MAX_NAME_LEN - strlen(modck)); | ||
713 | strlcat(name, modck, MOD_CLK_MAX_NAME_LEN); | ||
714 | 825 | ||
715 | clk = clk_get(NULL, name); | 826 | if (!IS_ERR_OR_NULL(clk)) { |
716 | if (!IS_ERR(clk)) { | 827 | pr_debug("%s: mapped main_clk %s for %s\n", __func__, |
828 | __clk_get_name(clk), oh->name); | ||
829 | oh->main_clk = __clk_get_name(clk); | ||
717 | oh->_clk = clk; | 830 | oh->_clk = clk; |
718 | soc_ops.disable_direct_prcm(oh); | 831 | soc_ops.disable_direct_prcm(oh); |
719 | oh->main_clk = kstrdup(name, GFP_KERNEL); | ||
720 | } else { | 832 | } else { |
721 | if (!oh->main_clk) | 833 | if (!oh->main_clk) |
722 | return 0; | 834 | return 0; |
@@ -1482,13 +1594,13 @@ static int _init_clkdm(struct omap_hwmod *oh) | |||
1482 | * _init_clocks - clk_get() all clocks associated with this hwmod. Retrieve as | 1594 | * _init_clocks - clk_get() all clocks associated with this hwmod. Retrieve as |
1483 | * well the clockdomain. | 1595 | * well the clockdomain. |
1484 | * @oh: struct omap_hwmod * | 1596 | * @oh: struct omap_hwmod * |
1485 | * @data: not used; pass NULL | 1597 | * @np: device_node mapped to this hwmod |
1486 | * | 1598 | * |
1487 | * Called by omap_hwmod_setup_*() (after omap2_clk_init()). | 1599 | * Called by omap_hwmod_setup_*() (after omap2_clk_init()). |
1488 | * Resolves all clock names embedded in the hwmod. Returns 0 on | 1600 | * Resolves all clock names embedded in the hwmod. Returns 0 on |
1489 | * success, or a negative error code on failure. | 1601 | * success, or a negative error code on failure. |
1490 | */ | 1602 | */ |
1491 | static int _init_clocks(struct omap_hwmod *oh, void *data) | 1603 | static int _init_clocks(struct omap_hwmod *oh, struct device_node *np) |
1492 | { | 1604 | { |
1493 | int ret = 0; | 1605 | int ret = 0; |
1494 | 1606 | ||
@@ -2334,24 +2446,21 @@ static int __init _init(struct omap_hwmod *oh, void *data) | |||
2334 | { | 2446 | { |
2335 | int r, index; | 2447 | int r, index; |
2336 | struct device_node *np = NULL; | 2448 | struct device_node *np = NULL; |
2449 | struct device_node *bus; | ||
2337 | 2450 | ||
2338 | if (oh->_state != _HWMOD_STATE_REGISTERED) | 2451 | if (oh->_state != _HWMOD_STATE_REGISTERED) |
2339 | return 0; | 2452 | return 0; |
2340 | 2453 | ||
2341 | if (of_have_populated_dt()) { | 2454 | bus = of_find_node_by_name(NULL, "ocp"); |
2342 | struct device_node *bus; | 2455 | if (!bus) |
2456 | return -ENODEV; | ||
2343 | 2457 | ||
2344 | bus = of_find_node_by_name(NULL, "ocp"); | 2458 | r = of_dev_hwmod_lookup(bus, oh, &index, &np); |
2345 | if (!bus) | 2459 | if (r) |
2346 | return -ENODEV; | 2460 | pr_debug("omap_hwmod: %s missing dt data\n", oh->name); |
2347 | 2461 | else if (np && index) | |
2348 | r = of_dev_hwmod_lookup(bus, oh, &index, &np); | 2462 | pr_warn("omap_hwmod: %s using broken dt data from %s\n", |
2349 | if (r) | 2463 | oh->name, np->name); |
2350 | pr_debug("omap_hwmod: %s missing dt data\n", oh->name); | ||
2351 | else if (np && index) | ||
2352 | pr_warn("omap_hwmod: %s using broken dt data from %s\n", | ||
2353 | oh->name, np->name); | ||
2354 | } | ||
2355 | 2464 | ||
2356 | r = _init_mpu_rt_base(oh, NULL, index, np); | 2465 | r = _init_mpu_rt_base(oh, NULL, index, np); |
2357 | if (r < 0) { | 2466 | if (r < 0) { |
@@ -2360,7 +2469,7 @@ static int __init _init(struct omap_hwmod *oh, void *data) | |||
2360 | return 0; | 2469 | return 0; |
2361 | } | 2470 | } |
2362 | 2471 | ||
2363 | r = _init_clocks(oh, NULL); | 2472 | r = _init_clocks(oh, np); |
2364 | if (r < 0) { | 2473 | if (r < 0) { |
2365 | WARN(1, "omap_hwmod: %s: couldn't init clocks\n", oh->name); | 2474 | WARN(1, "omap_hwmod: %s: couldn't init clocks\n", oh->name); |
2366 | return -EINVAL; | 2475 | return -EINVAL; |
@@ -3722,6 +3831,7 @@ void __init omap_hwmod_init(void) | |||
3722 | soc_ops.update_context_lost = _omap4_update_context_lost; | 3831 | soc_ops.update_context_lost = _omap4_update_context_lost; |
3723 | soc_ops.get_context_lost = _omap4_get_context_lost; | 3832 | soc_ops.get_context_lost = _omap4_get_context_lost; |
3724 | soc_ops.disable_direct_prcm = _omap4_disable_direct_prcm; | 3833 | soc_ops.disable_direct_prcm = _omap4_disable_direct_prcm; |
3834 | soc_ops.xlate_clkctrl = _omap4_xlate_clkctrl; | ||
3725 | } else if (cpu_is_ti814x() || cpu_is_ti816x() || soc_is_am33xx() || | 3835 | } else if (cpu_is_ti814x() || cpu_is_ti816x() || soc_is_am33xx() || |
3726 | soc_is_am43xx()) { | 3836 | soc_is_am43xx()) { |
3727 | soc_ops.enable_module = _omap4_enable_module; | 3837 | soc_ops.enable_module = _omap4_enable_module; |
@@ -3736,6 +3846,8 @@ void __init omap_hwmod_init(void) | |||
3736 | WARN(1, "omap_hwmod: unknown SoC type\n"); | 3846 | WARN(1, "omap_hwmod: unknown SoC type\n"); |
3737 | } | 3847 | } |
3738 | 3848 | ||
3849 | _init_clkctrl_providers(); | ||
3850 | |||
3739 | inited = true; | 3851 | inited = true; |
3740 | } | 3852 | } |
3741 | 3853 | ||