hc
2024-05-10 23fa18eaa71266feff7ba8d83022d9e1cc83c65a
kernel/arch/arm/mach-omap2/omap_hwmod.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * omap_hwmod implementation for OMAP2/3/4
34 *
....@@ -9,10 +10,6 @@
910 * Created in collaboration with (alphabetical order): Thara Gopinath,
1011 * Tony Lindgren, Rajendra Nayak, Vikram Pandita, Sakari Poussa, Anand
1112 * Sawant, Santosh Shilimkar, Richard Woodruff
12
- *
13
- * This program is free software; you can redistribute it and/or modify
14
- * it under the terms of the GNU General Public License version 2 as
15
- * published by the Free Software Foundation.
1613 *
1714 * Introduction
1815 * ------------
....@@ -141,7 +138,7 @@
141138 #include <linux/cpu.h>
142139 #include <linux/of.h>
143140 #include <linux/of_address.h>
144
-#include <linux/bootmem.h>
141
+#include <linux/memblock.h>
145142
146143 #include <linux/platform_data/ti-sysc.h>
147144
....@@ -155,6 +152,8 @@
155152 #include "soc.h"
156153 #include "common.h"
157154 #include "clockdomain.h"
155
+#include "hdq1w.h"
156
+#include "mmc.h"
158157 #include "powerdomain.h"
159158 #include "cm2xxx.h"
160159 #include "cm3xxx.h"
....@@ -165,6 +164,7 @@
165164 #include "prm33xx.h"
166165 #include "prminst44xx.h"
167166 #include "pm.h"
167
+#include "wd_timer.h"
168168
169169 /* Name of the OMAP hwmod for the MPU */
170170 #define MPU_INITIATOR_NAME "mpu"
....@@ -188,21 +188,35 @@
188188
189189 /**
190190 * struct clkctrl_provider - clkctrl provider mapping data
191
- * @addr: base address for the provider
192
- * @size: size of the provider address space
193
- * @offset: offset of the provider from PRCM instance base
191
+ * @num_addrs: number of base address ranges for the provider
192
+ * @addr: base address(es) for the provider
193
+ * @size: size(s) of the provider address space(s)
194194 * @node: device node associated with the provider
195195 * @link: list link
196196 */
197197 struct clkctrl_provider {
198
- u32 addr;
199
- u32 size;
200
- u16 offset;
198
+ int num_addrs;
199
+ u32 *addr;
200
+ u32 *size;
201201 struct device_node *node;
202202 struct list_head link;
203203 };
204204
205205 static LIST_HEAD(clkctrl_providers);
206
+
207
+/**
208
+ * struct omap_hwmod_reset - IP specific reset functions
209
+ * @match: string to match against the module name
210
+ * @len: number of characters to match
211
+ * @reset: IP specific reset function
212
+ *
213
+ * Used only in cases where struct omap_hwmod is dynamically allocated.
214
+ */
215
+struct omap_hwmod_reset {
216
+ const char *match;
217
+ int len;
218
+ int (*reset)(struct omap_hwmod *oh);
219
+};
206220
207221 /**
208222 * struct omap_hwmod_soc_ops - fn ptrs for some SoC-specific operations
....@@ -235,6 +249,7 @@
235249
236250 /* omap_hwmod_list contains all registered struct omap_hwmods */
237251 static LIST_HEAD(omap_hwmod_list);
252
+static DEFINE_MUTEX(list_lock);
238253
239254 /* mpu_oh: used to add/remove MPU initiator from sleepdep list */
240255 static struct omap_hwmod *mpu_oh;
....@@ -608,39 +623,6 @@
608623 return 0;
609624 }
610625
611
-/**
612
- * _disable_wakeup: clear OCP_SYSCONFIG.ENAWAKEUP bit in the hardware
613
- * @oh: struct omap_hwmod *
614
- *
615
- * Prevent the hardware module @oh to send wakeups. Returns -EINVAL
616
- * upon error or 0 upon success.
617
- */
618
-static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
619
-{
620
- if (!oh->class->sysc ||
621
- !((oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP) ||
622
- (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP) ||
623
- (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)))
624
- return -EINVAL;
625
-
626
- if (!oh->class->sysc->sysc_fields) {
627
- WARN(1, "omap_hwmod: %s: offset struct for sysconfig not provided in class\n", oh->name);
628
- return -EINVAL;
629
- }
630
-
631
- if (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)
632
- *v &= ~(0x1 << oh->class->sysc->sysc_fields->enwkup_shift);
633
-
634
- if (oh->class->sysc->idlemodes & SIDLE_SMART_WKUP)
635
- _set_slave_idlemode(oh, HWMOD_IDLEMODE_SMART, v);
636
- if (oh->class->sysc->idlemodes & MSTANDBY_SMART_WKUP)
637
- _set_master_standbymode(oh, HWMOD_IDLEMODE_SMART, v);
638
-
639
- /* XXX test pwrdm_get_wken for this hwmod's subsystem */
640
-
641
- return 0;
642
-}
643
-
644626 static struct clockdomain *_get_clkdm(struct omap_hwmod *oh)
645627 {
646628 struct clk_hw_omap *clk;
....@@ -648,10 +630,10 @@
648630 if (oh->clkdm) {
649631 return oh->clkdm;
650632 } else if (oh->_clk) {
651
- if (__clk_get_flags(oh->_clk) & CLK_IS_BASIC)
633
+ if (!omap2_clk_is_hw_omap(__clk_get_hw(oh->_clk)))
652634 return NULL;
653635 clk = to_clk_hw_omap(__clk_get_hw(oh->_clk));
654
- return clk->clkdm;
636
+ return clk->clkdm;
655637 }
656638 return NULL;
657639 }
....@@ -724,23 +706,36 @@
724706 const __be32 *addrp;
725707 struct clkctrl_provider *provider;
726708 u64 size;
709
+ int i;
727710
728
- provider = memblock_virt_alloc(sizeof(*provider), 0);
711
+ provider = memblock_alloc(sizeof(*provider), SMP_CACHE_BYTES);
729712 if (!provider)
730713 return -ENOMEM;
731714
732
- addrp = of_get_address(np, 0, &size, NULL);
733
- provider->addr = (u32)of_translate_address(np, addrp);
734
- addrp = of_get_address(np->parent, 0, NULL, NULL);
735
- provider->offset = provider->addr -
736
- (u32)of_translate_address(np->parent, addrp);
737
- provider->addr &= ~0xff;
738
- provider->size = size | 0xff;
739715 provider->node = np;
740716
741
- pr_debug("%s: %s: %x...%x [+%x]\n", __func__, np->parent->name,
742
- provider->addr, provider->addr + provider->size,
743
- provider->offset);
717
+ provider->num_addrs =
718
+ of_property_count_elems_of_size(np, "reg", sizeof(u32)) / 2;
719
+
720
+ provider->addr =
721
+ memblock_alloc(sizeof(void *) * provider->num_addrs,
722
+ SMP_CACHE_BYTES);
723
+ if (!provider->addr)
724
+ return -ENOMEM;
725
+
726
+ provider->size =
727
+ memblock_alloc(sizeof(u32) * provider->num_addrs,
728
+ SMP_CACHE_BYTES);
729
+ if (!provider->size)
730
+ return -ENOMEM;
731
+
732
+ for (i = 0; i < provider->num_addrs; i++) {
733
+ addrp = of_get_address(np, i, &size, NULL);
734
+ provider->addr[i] = (u32)of_translate_address(np, addrp);
735
+ provider->size[i] = size;
736
+ pr_debug("%s: %pOF: %x...%x\n", __func__, np, provider->addr[i],
737
+ provider->addr[i] + provider->size[i]);
738
+ }
744739
745740 list_add(&provider->link, &clkctrl_providers);
746741
....@@ -789,23 +784,26 @@
789784 pr_debug("%s: %s: addr=%x\n", __func__, oh->name, addr);
790785
791786 list_for_each_entry(provider, &clkctrl_providers, link) {
792
- if (provider->addr <= addr &&
793
- provider->addr + provider->size >= addr) {
794
- struct of_phandle_args clkspec;
787
+ int i;
795788
796
- clkspec.np = provider->node;
797
- clkspec.args_count = 2;
798
- clkspec.args[0] = addr - provider->addr -
799
- provider->offset;
800
- clkspec.args[1] = 0;
789
+ for (i = 0; i < provider->num_addrs; i++) {
790
+ if (provider->addr[i] <= addr &&
791
+ provider->addr[i] + provider->size[i] > addr) {
792
+ struct of_phandle_args clkspec;
801793
802
- clk = of_clk_get_from_provider(&clkspec);
794
+ clkspec.np = provider->node;
795
+ clkspec.args_count = 2;
796
+ clkspec.args[0] = addr - provider->addr[0];
797
+ clkspec.args[1] = 0;
803798
804
- pr_debug("%s: %s got %p (offset=%x, provider=%s)\n",
805
- __func__, oh->name, clk, clkspec.args[0],
806
- provider->node->parent->name);
799
+ clk = of_clk_get_from_provider(&clkspec);
807800
808
- return clk;
801
+ pr_debug("%s: %s got %p (offset=%x, provider=%pOF)\n",
802
+ __func__, oh->name, clk,
803
+ clkspec.args[0], provider->node);
804
+
805
+ return clk;
806
+ }
809807 }
810808 }
811809
....@@ -988,8 +986,10 @@
988986 clk_enable(oh->_clk);
989987
990988 list_for_each_entry(os, &oh->slave_ports, node) {
991
- if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE))
989
+ if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE)) {
990
+ omap2_clk_deny_idle(os->_clk);
992991 clk_enable(os->_clk);
992
+ }
993993 }
994994
995995 /* The opt clocks are controlled by the device driver. */
....@@ -1041,8 +1041,10 @@
10411041 clk_disable(oh->_clk);
10421042
10431043 list_for_each_entry(os, &oh->slave_ports, node) {
1044
- if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE))
1044
+ if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE)) {
10451045 clk_disable(os->_clk);
1046
+ omap2_clk_allow_idle(os->_clk);
1047
+ }
10461048 }
10471049
10481050 if (oh->flags & HWMOD_OPT_CLKS_NEEDED)
....@@ -1853,23 +1855,6 @@
18531855 }
18541856
18551857 /**
1856
- * _enable_preprogram - Pre-program an IP block during the _enable() process
1857
- * @oh: struct omap_hwmod *
1858
- *
1859
- * Some IP blocks (such as AESS) require some additional programming
1860
- * after enable before they can enter idle. If a function pointer to
1861
- * do so is present in the hwmod data, then call it and pass along the
1862
- * return value; otherwise, return 0.
1863
- */
1864
-static int _enable_preprogram(struct omap_hwmod *oh)
1865
-{
1866
- if (!oh->class->enable_preprogram)
1867
- return 0;
1868
-
1869
- return oh->class->enable_preprogram(oh);
1870
-}
1871
-
1872
-/**
18731858 * _enable - enable an omap_hwmod
18741859 * @oh: struct omap_hwmod *
18751860 *
....@@ -1952,7 +1937,6 @@
19521937 _update_sysc_cache(oh);
19531938 _enable_sysc(oh);
19541939 }
1955
- r = _enable_preprogram(oh);
19561940 } else {
19571941 if (soc_ops.disable_module)
19581942 soc_ops.disable_module(oh);
....@@ -2109,8 +2093,8 @@
21092093 if (res)
21102094 continue;
21112095 if (!strcmp(p, oh->name)) {
2112
- pr_debug("omap_hwmod: dt %s[%i] uses hwmod %s\n",
2113
- np->name, i, oh->name);
2096
+ pr_debug("omap_hwmod: dt %pOFn[%i] uses hwmod %s\n",
2097
+ np, i, oh->name);
21142098 return i;
21152099 }
21162100 }
....@@ -2243,8 +2227,8 @@
22432227 return -ENOENT;
22442228
22452229 if (nr_addr != 1 || nr_size != 1) {
2246
- pr_err("%s: invalid range for %s->%s\n", __func__,
2247
- oh->name, np->name);
2230
+ pr_err("%s: invalid range for %s->%pOFn\n", __func__,
2231
+ oh->name, np);
22482232 return -EINVAL;
22492233 }
22502234
....@@ -2252,8 +2236,8 @@
22522236 base = of_translate_address(np, ranges++);
22532237 size = be32_to_cpup(ranges);
22542238
2255
- pr_debug("omap_hwmod: %s %s at 0x%llx size 0x%llx\n",
2256
- oh ? oh->name : "", np->name, base, size);
2239
+ pr_debug("omap_hwmod: %s %pOFn at 0x%llx size 0x%llx\n",
2240
+ oh->name, np, base, size);
22572241
22582242 if (oh && oh->mpu_rt_idx) {
22592243 omap_hwmod_fix_mpu_rt_idx(oh, np, res);
....@@ -2331,6 +2315,17 @@
23312315 return 0;
23322316 }
23332317
2318
+static void __init parse_module_flags(struct omap_hwmod *oh,
2319
+ struct device_node *np)
2320
+{
2321
+ if (of_find_property(np, "ti,no-reset-on-init", NULL))
2322
+ oh->flags |= HWMOD_INIT_NO_RESET;
2323
+ if (of_find_property(np, "ti,no-idle-on-init", NULL))
2324
+ oh->flags |= HWMOD_INIT_NO_IDLE;
2325
+ if (of_find_property(np, "ti,no-idle", NULL))
2326
+ oh->flags |= HWMOD_NO_IDLE;
2327
+}
2328
+
23342329 /**
23352330 * _init - initialize internal data for the hwmod @oh
23362331 * @oh: struct omap_hwmod *
....@@ -2361,8 +2356,8 @@
23612356 if (r)
23622357 pr_debug("omap_hwmod: %s missing dt data\n", oh->name);
23632358 else if (np && index)
2364
- pr_warn("omap_hwmod: %s using broken dt data from %s\n",
2365
- oh->name, np->name);
2359
+ pr_warn("omap_hwmod: %s using broken dt data from %pOFn\n",
2360
+ oh->name, np);
23662361
23672362 r = _init_mpu_rt_base(oh, NULL, index, np);
23682363 if (r < 0) {
....@@ -2378,12 +2373,12 @@
23782373 }
23792374
23802375 if (np) {
2381
- if (of_find_property(np, "ti,no-reset-on-init", NULL))
2382
- oh->flags |= HWMOD_INIT_NO_RESET;
2383
- if (of_find_property(np, "ti,no-idle-on-init", NULL))
2384
- oh->flags |= HWMOD_INIT_NO_IDLE;
2385
- if (of_find_property(np, "ti,no-idle", NULL))
2386
- oh->flags |= HWMOD_NO_IDLE;
2376
+ struct device_node *child;
2377
+
2378
+ parse_module_flags(oh, np);
2379
+ child = of_get_next_child(np, NULL);
2380
+ if (child)
2381
+ parse_module_flags(oh, child);
23872382 }
23882383
23892384 oh->_state = _HWMOD_STATE_INITIALIZED;
....@@ -2411,9 +2406,13 @@
24112406 continue;
24122407
24132408 if (os->flags & OCPIF_SWSUP_IDLE) {
2414
- /* XXX omap_iclk_deny_idle(c); */
2409
+ /*
2410
+ * we might have multiple users of one iclk with
2411
+ * different requirements, disable autoidle when
2412
+ * the module is enabled, e.g. dss iclk
2413
+ */
24152414 } else {
2416
- /* XXX omap_iclk_allow_idle(c); */
2415
+ /* we are enabling autoidle afterwards anyways */
24172416 clk_enable(os->_clk);
24182417 }
24192418 }
....@@ -2591,7 +2590,7 @@
25912590 * that the copy process would be relatively complex due to the large number
25922591 * of substructures.
25932592 */
2594
-static int __init _register(struct omap_hwmod *oh)
2593
+static int _register(struct omap_hwmod *oh)
25952594 {
25962595 if (!oh || !oh->name || !oh->class || !oh->class->name ||
25972596 (oh->_state != _HWMOD_STATE_UNKNOWN))
....@@ -2630,7 +2629,7 @@
26302629 * locking in this code. Changes to this assumption will require
26312630 * additional locking. Returns 0.
26322631 */
2633
-static int __init _add_link(struct omap_hwmod_ocp_if *oi)
2632
+static int _add_link(struct omap_hwmod_ocp_if *oi)
26342633 {
26352634 pr_debug("omap_hwmod: %s -> %s: adding link\n", oi->master->name,
26362635 oi->slave->name);
....@@ -3151,15 +3150,14 @@
31513150 /**
31523151 * omap_hwmod_init_regbits - init sysconfig specific register bits
31533152 * @dev: struct device
3153
+ * @oh: module
31543154 * @data: module data
31553155 * @sysc_fields: new sysc configuration
31563156 */
3157
-static int omap_hwmod_init_regbits(struct device *dev,
3157
+static int omap_hwmod_init_regbits(struct device *dev, struct omap_hwmod *oh,
31583158 const struct ti_sysc_module_data *data,
31593159 struct sysc_regbits **sysc_fields)
31603160 {
3161
- *sysc_fields = NULL;
3162
-
31633161 switch (data->cap->type) {
31643162 case TI_SYSC_OMAP2:
31653163 case TI_SYSC_OMAP2_TIMER:
....@@ -3194,6 +3192,12 @@
31943192 *sysc_fields = &omap_hwmod_sysc_type_usb_host_fs;
31953193 break;
31963194 default:
3195
+ *sysc_fields = NULL;
3196
+ if (!oh->class->sysc->sysc_fields)
3197
+ return 0;
3198
+
3199
+ dev_err(dev, "sysc_fields not found\n");
3200
+
31973201 return -EINVAL;
31983202 }
31993203
....@@ -3208,9 +3212,10 @@
32083212 * @sysc_offs: sysc register offset
32093213 * @syss_offs: syss register offset
32103214 */
3211
-int omap_hwmod_init_reg_offs(struct device *dev,
3212
- const struct ti_sysc_module_data *data,
3213
- s32 *rev_offs, s32 *sysc_offs, s32 *syss_offs)
3215
+static int omap_hwmod_init_reg_offs(struct device *dev,
3216
+ const struct ti_sysc_module_data *data,
3217
+ s32 *rev_offs, s32 *sysc_offs,
3218
+ s32 *syss_offs)
32143219 {
32153220 *rev_offs = -ENODEV;
32163221 *sysc_offs = 0;
....@@ -3234,9 +3239,9 @@
32343239 * @data: module data
32353240 * @sysc_flags: module configuration
32363241 */
3237
-int omap_hwmod_init_sysc_flags(struct device *dev,
3238
- const struct ti_sysc_module_data *data,
3239
- u32 *sysc_flags)
3242
+static int omap_hwmod_init_sysc_flags(struct device *dev,
3243
+ const struct ti_sysc_module_data *data,
3244
+ u32 *sysc_flags)
32403245 {
32413246 *sysc_flags = 0;
32423247
....@@ -3308,9 +3313,9 @@
33083313 * @data: module data
33093314 * @idlemodes: module supported idle modes
33103315 */
3311
-int omap_hwmod_init_idlemodes(struct device *dev,
3312
- const struct ti_sysc_module_data *data,
3313
- u32 *idlemodes)
3316
+static int omap_hwmod_init_idlemodes(struct device *dev,
3317
+ const struct ti_sysc_module_data *data,
3318
+ u32 *idlemodes)
33143319 {
33153320 *idlemodes = 0;
33163321
....@@ -3358,9 +3363,9 @@
33583363 if (!oh->class->sysc)
33593364 return -ENODEV;
33603365
3361
- if (sysc_fields != oh->class->sysc->sysc_fields)
3362
- dev_warn(dev, "sysc_fields %p != %p\n", sysc_fields,
3363
- oh->class->sysc->sysc_fields);
3366
+ if (oh->class->sysc->sysc_fields &&
3367
+ sysc_fields != oh->class->sysc->sysc_fields)
3368
+ dev_warn(dev, "sysc_fields mismatch\n");
33643369
33653370 if (rev_offs != oh->class->sysc->rev_offs)
33663371 dev_warn(dev, "rev_offs %08x != %08x\n", rev_offs,
....@@ -3393,6 +3398,7 @@
33933398 * @dev: struct device
33943399 * @oh: module
33953400 * @sysc_fields: sysc register bits
3401
+ * @clockdomain: clockdomain
33963402 * @rev_offs: revision register offset
33973403 * @sysc_offs: sysconfig register offset
33983404 * @syss_offs: sysstatus register offset
....@@ -3401,14 +3407,17 @@
34013407 *
34023408 * Note that the allocations here cannot use devm as ti-sysc can rebind.
34033409 */
3404
-int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
3405
- const struct ti_sysc_module_data *data,
3406
- struct sysc_regbits *sysc_fields,
3407
- s32 rev_offs, s32 sysc_offs, s32 syss_offs,
3408
- u32 sysc_flags, u32 idlemodes)
3410
+static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
3411
+ const struct ti_sysc_module_data *data,
3412
+ struct sysc_regbits *sysc_fields,
3413
+ struct clockdomain *clkdm,
3414
+ s32 rev_offs, s32 sysc_offs,
3415
+ s32 syss_offs, u32 sysc_flags,
3416
+ u32 idlemodes)
34093417 {
34103418 struct omap_hwmod_class_sysconfig *sysc;
3411
- struct omap_hwmod_class *class;
3419
+ struct omap_hwmod_class *class = NULL;
3420
+ struct omap_hwmod_ocp_if *oi = NULL;
34123421 void __iomem *regs = NULL;
34133422 unsigned long flags;
34143423
....@@ -3428,28 +3437,108 @@
34283437 regs = ioremap(data->module_pa,
34293438 data->module_size);
34303439 if (!regs)
3431
- return -ENOMEM;
3440
+ goto out_free_sysc;
34323441 }
34333442
34343443 /*
3435
- * We need new oh->class as the other devices in the same class
3444
+ * We may need a new oh->class as the other devices in the same class
34363445 * may not yet have ioremapped their registers.
34373446 */
3438
- class = kmemdup(oh->class, sizeof(*oh->class), GFP_KERNEL);
3439
- if (!class)
3440
- return -ENOMEM;
3447
+ if (oh->class->name && strcmp(oh->class->name, data->name)) {
3448
+ class = kmemdup(oh->class, sizeof(*oh->class), GFP_KERNEL);
3449
+ if (!class)
3450
+ goto out_unmap;
3451
+ }
34413452
3442
- class->sysc = sysc;
3453
+ if (list_empty(&oh->slave_ports)) {
3454
+ oi = kcalloc(1, sizeof(*oi), GFP_KERNEL);
3455
+ if (!oi)
3456
+ goto out_free_class;
3457
+
3458
+ /*
3459
+ * Note that we assume interconnect interface clocks will be
3460
+ * managed by the interconnect driver for OCPIF_SWSUP_IDLE case
3461
+ * on omap24xx and omap3.
3462
+ */
3463
+ oi->slave = oh;
3464
+ oi->user = OCP_USER_MPU | OCP_USER_SDMA;
3465
+ }
34433466
34443467 spin_lock_irqsave(&oh->_lock, flags);
34453468 if (regs)
34463469 oh->_mpu_rt_va = regs;
3447
- oh->class = class;
3470
+ if (class)
3471
+ oh->class = class;
3472
+ oh->class->sysc = sysc;
3473
+ if (oi)
3474
+ _add_link(oi);
3475
+ if (clkdm)
3476
+ oh->clkdm = clkdm;
34483477 oh->_state = _HWMOD_STATE_INITIALIZED;
3478
+ oh->_postsetup_state = _HWMOD_STATE_DEFAULT;
34493479 _setup(oh, NULL);
34503480 spin_unlock_irqrestore(&oh->_lock, flags);
34513481
34523482 return 0;
3483
+
3484
+out_free_class:
3485
+ kfree(class);
3486
+out_unmap:
3487
+ iounmap(regs);
3488
+out_free_sysc:
3489
+ kfree(sysc);
3490
+ return -ENOMEM;
3491
+}
3492
+
3493
+static const struct omap_hwmod_reset omap24xx_reset_quirks[] = {
3494
+ { .match = "msdi", .len = 4, .reset = omap_msdi_reset, },
3495
+};
3496
+
3497
+static const struct omap_hwmod_reset dra7_reset_quirks[] = {
3498
+ { .match = "pcie", .len = 4, .reset = dra7xx_pciess_reset, },
3499
+};
3500
+
3501
+static const struct omap_hwmod_reset omap_reset_quirks[] = {
3502
+ { .match = "dss_core", .len = 8, .reset = omap_dss_reset, },
3503
+ { .match = "hdq1w", .len = 5, .reset = omap_hdq1w_reset, },
3504
+ { .match = "i2c", .len = 3, .reset = omap_i2c_reset, },
3505
+ { .match = "wd_timer", .len = 8, .reset = omap2_wd_timer_reset, },
3506
+};
3507
+
3508
+static void
3509
+omap_hwmod_init_reset_quirk(struct device *dev, struct omap_hwmod *oh,
3510
+ const struct ti_sysc_module_data *data,
3511
+ const struct omap_hwmod_reset *quirks,
3512
+ int quirks_sz)
3513
+{
3514
+ const struct omap_hwmod_reset *quirk;
3515
+ int i;
3516
+
3517
+ for (i = 0; i < quirks_sz; i++) {
3518
+ quirk = &quirks[i];
3519
+ if (!strncmp(data->name, quirk->match, quirk->len)) {
3520
+ oh->class->reset = quirk->reset;
3521
+
3522
+ return;
3523
+ }
3524
+ }
3525
+}
3526
+
3527
+static void
3528
+omap_hwmod_init_reset_quirks(struct device *dev, struct omap_hwmod *oh,
3529
+ const struct ti_sysc_module_data *data)
3530
+{
3531
+ if (soc_is_omap24xx())
3532
+ omap_hwmod_init_reset_quirk(dev, oh, data,
3533
+ omap24xx_reset_quirks,
3534
+ ARRAY_SIZE(omap24xx_reset_quirks));
3535
+
3536
+ if (soc_is_dra7xx())
3537
+ omap_hwmod_init_reset_quirk(dev, oh, data, dra7_reset_quirks,
3538
+ ARRAY_SIZE(dra7_reset_quirks));
3539
+
3540
+ omap_hwmod_init_reset_quirk(dev, oh, data, omap_reset_quirks,
3541
+ ARRAY_SIZE(omap_reset_quirks));
34533542 }
34543543
34553544 /**
....@@ -3468,16 +3557,39 @@
34683557 u32 sysc_flags, idlemodes;
34693558 int error;
34703559
3471
- if (!dev || !data)
3560
+ if (!dev || !data || !data->name || !cookie)
34723561 return -EINVAL;
34733562
34743563 oh = _lookup(data->name);
3475
- if (!oh)
3476
- return -ENODEV;
3564
+ if (!oh) {
3565
+ oh = kzalloc(sizeof(*oh), GFP_KERNEL);
3566
+ if (!oh)
3567
+ return -ENOMEM;
3568
+
3569
+ oh->name = data->name;
3570
+ oh->_state = _HWMOD_STATE_UNKNOWN;
3571
+ lockdep_register_key(&oh->hwmod_key);
3572
+
3573
+ /* Unused, can be handled by PRM driver handling resets */
3574
+ oh->prcm.omap4.flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT;
3575
+
3576
+ oh->class = kzalloc(sizeof(*oh->class), GFP_KERNEL);
3577
+ if (!oh->class) {
3578
+ kfree(oh);
3579
+ return -ENOMEM;
3580
+ }
3581
+
3582
+ omap_hwmod_init_reset_quirks(dev, oh, data);
3583
+
3584
+ oh->class->name = data->name;
3585
+ mutex_lock(&list_lock);
3586
+ error = _register(oh);
3587
+ mutex_unlock(&list_lock);
3588
+ }
34773589
34783590 cookie->data = oh;
34793591
3480
- error = omap_hwmod_init_regbits(dev, data, &sysc_fields);
3592
+ error = omap_hwmod_init_regbits(dev, oh, data, &sysc_fields);
34813593 if (error)
34823594 return error;
34833595
....@@ -3494,10 +3606,22 @@
34943606 if (error)
34953607 return error;
34963608
3609
+ if (data->cfg->quirks & SYSC_QUIRK_NO_IDLE)
3610
+ oh->flags |= HWMOD_NO_IDLE;
34973611 if (data->cfg->quirks & SYSC_QUIRK_NO_IDLE_ON_INIT)
34983612 oh->flags |= HWMOD_INIT_NO_IDLE;
34993613 if (data->cfg->quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
35003614 oh->flags |= HWMOD_INIT_NO_RESET;
3615
+ if (data->cfg->quirks & SYSC_QUIRK_USE_CLOCKACT)
3616
+ oh->flags |= HWMOD_SET_DEFAULT_CLOCKACT;
3617
+ if (data->cfg->quirks & SYSC_QUIRK_SWSUP_SIDLE)
3618
+ oh->flags |= HWMOD_SWSUP_SIDLE;
3619
+ if (data->cfg->quirks & SYSC_QUIRK_SWSUP_SIDLE_ACT)
3620
+ oh->flags |= HWMOD_SWSUP_SIDLE_ACT;
3621
+ if (data->cfg->quirks & SYSC_QUIRK_SWSUP_MSTANDBY)
3622
+ oh->flags |= HWMOD_SWSUP_MSTANDBY;
3623
+ if (data->cfg->quirks & SYSC_QUIRK_CLKDM_NOAUTO)
3624
+ oh->flags |= HWMOD_CLKDM_NOAUTO;
35013625
35023626 error = omap_hwmod_check_module(dev, oh, data, sysc_fields,
35033627 rev_offs, sysc_offs, syss_offs,
....@@ -3506,7 +3630,8 @@
35063630 return error;
35073631
35083632 return omap_hwmod_allocate_module(dev, oh, data, sysc_fields,
3509
- rev_offs, sysc_offs, syss_offs,
3633
+ cookie->clkdm, rev_offs,
3634
+ sysc_offs, syss_offs,
35103635 sysc_flags, idlemodes);
35113636 }
35123637
....@@ -3656,6 +3781,7 @@
36563781 struct omap_hwmod_ocp_if *oi;
36573782 struct clockdomain *clkdm;
36583783 struct clk_hw_omap *clk;
3784
+ struct clk_hw *hw;
36593785
36603786 if (!oh)
36613787 return NULL;
....@@ -3672,7 +3798,14 @@
36723798 c = oi->_clk;
36733799 }
36743800
3675
- clk = to_clk_hw_omap(__clk_get_hw(c));
3801
+ hw = __clk_get_hw(c);
3802
+ if (!hw)
3803
+ return NULL;
3804
+
3805
+ clk = to_clk_hw_omap(hw);
3806
+ if (!clk)
3807
+ return NULL;
3808
+
36763809 clkdm = clk->clkdm;
36773810 if (!clkdm)
36783811 return NULL;
....@@ -3707,70 +3840,6 @@
37073840 * XXX what about functions for drivers to save/restore ocp_sysconfig
37083841 * for context save/restore operations?
37093842 */
3710
-
3711
-/**
3712
- * omap_hwmod_enable_wakeup - allow device to wake up the system
3713
- * @oh: struct omap_hwmod *
3714
- *
3715
- * Sets the module OCP socket ENAWAKEUP bit to allow the module to
3716
- * send wakeups to the PRCM, and enable I/O ring wakeup events for
3717
- * this IP block if it has dynamic mux entries. Eventually this
3718
- * should set PRCM wakeup registers to cause the PRCM to receive
3719
- * wakeup events from the module. Does not set any wakeup routing
3720
- * registers beyond this point - if the module is to wake up any other
3721
- * module or subsystem, that must be set separately. Called by
3722
- * omap_device code. Returns -EINVAL on error or 0 upon success.
3723
- */
3724
-int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
3725
-{
3726
- unsigned long flags;
3727
- u32 v;
3728
-
3729
- spin_lock_irqsave(&oh->_lock, flags);
3730
-
3731
- if (oh->class->sysc &&
3732
- (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) {
3733
- v = oh->_sysc_cache;
3734
- _enable_wakeup(oh, &v);
3735
- _write_sysconfig(v, oh);
3736
- }
3737
-
3738
- spin_unlock_irqrestore(&oh->_lock, flags);
3739
-
3740
- return 0;
3741
-}
3742
-
3743
-/**
3744
- * omap_hwmod_disable_wakeup - prevent device from waking the system
3745
- * @oh: struct omap_hwmod *
3746
- *
3747
- * Clears the module OCP socket ENAWAKEUP bit to prevent the module
3748
- * from sending wakeups to the PRCM, and disable I/O ring wakeup
3749
- * events for this IP block if it has dynamic mux entries. Eventually
3750
- * this should clear PRCM wakeup registers to cause the PRCM to ignore
3751
- * wakeup events from the module. Does not set any wakeup routing
3752
- * registers beyond this point - if the module is to wake up any other
3753
- * module or subsystem, that must be set separately. Called by
3754
- * omap_device code. Returns -EINVAL on error or 0 upon success.
3755
- */
3756
-int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
3757
-{
3758
- unsigned long flags;
3759
- u32 v;
3760
-
3761
- spin_lock_irqsave(&oh->_lock, flags);
3762
-
3763
- if (oh->class->sysc &&
3764
- (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) {
3765
- v = oh->_sysc_cache;
3766
- _disable_wakeup(oh, &v);
3767
- _write_sysconfig(v, oh);
3768
- }
3769
-
3770
- spin_unlock_irqrestore(&oh->_lock, flags);
3771
-
3772
- return 0;
3773
-}
37743843
37753844 /**
37763845 * omap_hwmod_assert_hardreset - assert the HW reset line of submodules