blob: fc9aac3d4d02ee34ef68fec5e1699e9c0e847e98 [file] [log] [blame]
Tony Lindgren0eecc632017-10-10 14:23:43 -07001/*
2 * ti-sysc.c - Texas Instruments sysc interconnect target driver
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
9 * kind, whether express or implied; without even the implied warranty
10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/io.h>
15#include <linux/clk.h>
Tony Lindgren2c355ff2018-02-22 13:58:03 -080016#include <linux/clkdev.h>
Tony Lindgren0eecc632017-10-10 14:23:43 -070017#include <linux/module.h>
18#include <linux/platform_device.h>
19#include <linux/pm_runtime.h>
20#include <linux/of_address.h>
21#include <linux/of_platform.h>
Tony Lindgren2c355ff2018-02-22 13:58:03 -080022#include <linux/slab.h>
23
Tony Lindgren70a65242017-12-15 09:41:09 -080024#include <linux/platform_data/ti-sysc.h>
25
26#include <dt-bindings/bus/ti-sysc.h>
Tony Lindgren0eecc632017-10-10 14:23:43 -070027
28enum sysc_registers {
29 SYSC_REVISION,
30 SYSC_SYSCONFIG,
31 SYSC_SYSSTATUS,
32 SYSC_MAX_REGS,
33};
34
35static const char * const reg_names[] = { "rev", "sysc", "syss", };
36
37enum sysc_clocks {
38 SYSC_FCK,
39 SYSC_ICK,
40 SYSC_MAX_CLOCKS,
41};
42
43static const char * const clock_names[] = { "fck", "ick", };
44
Tony Lindgrenc5a2de92017-12-15 09:41:23 -080045#define SYSC_IDLEMODE_MASK 3
46#define SYSC_CLOCKACTIVITY_MASK 3
47
Tony Lindgren0eecc632017-10-10 14:23:43 -070048/**
49 * struct sysc - TI sysc interconnect target module registers and capabilities
50 * @dev: struct device pointer
51 * @module_pa: physical address of the interconnect target module
52 * @module_size: size of the interconnect target module
53 * @module_va: virtual address of the interconnect target module
54 * @offsets: register offsets from module base
55 * @clocks: clocks used by the interconnect target module
56 * @legacy_mode: configured for legacy mode if set
Tony Lindgren70a65242017-12-15 09:41:09 -080057 * @cap: interconnect target module capabilities
58 * @cfg: interconnect target module configuration
Tony Lindgren566a9b052017-12-15 09:41:19 -080059 * @name: name if available
60 * @revision: interconnect target module revision
Tony Lindgren62020f22018-02-22 13:59:44 -080061 * @needs_resume: runtime resume needed on resume from suspend
Tony Lindgren0eecc632017-10-10 14:23:43 -070062 */
63struct sysc {
64 struct device *dev;
65 u64 module_pa;
66 u32 module_size;
67 void __iomem *module_va;
68 int offsets[SYSC_MAX_REGS];
69 struct clk *clocks[SYSC_MAX_CLOCKS];
70 const char *legacy_mode;
Tony Lindgren70a65242017-12-15 09:41:09 -080071 const struct sysc_capabilities *cap;
72 struct sysc_config cfg;
Tony Lindgren566a9b052017-12-15 09:41:19 -080073 const char *name;
74 u32 revision;
Tony Lindgren62020f22018-02-22 13:59:44 -080075 bool enabled;
76 bool needs_resume;
Tony Lindgren76f0f772018-02-23 08:28:45 -080077 struct delayed_work idle_work;
Tony Lindgren0eecc632017-10-10 14:23:43 -070078};
79
Tony Lindgren566a9b052017-12-15 09:41:19 -080080static u32 sysc_read(struct sysc *ddata, int offset)
81{
82 if (ddata->cfg.quirks & SYSC_QUIRK_16BIT) {
83 u32 val;
84
85 val = readw_relaxed(ddata->module_va + offset);
86 val |= (readw_relaxed(ddata->module_va + offset + 4) << 16);
87
88 return val;
89 }
90
91 return readl_relaxed(ddata->module_va + offset);
92}
93
Tony Lindgren0eecc632017-10-10 14:23:43 -070094static u32 sysc_read_revision(struct sysc *ddata)
95{
Tony Lindgren566a9b052017-12-15 09:41:19 -080096 int offset = ddata->offsets[SYSC_REVISION];
97
98 if (offset < 0)
99 return 0;
100
101 return sysc_read(ddata, offset);
Tony Lindgren0eecc632017-10-10 14:23:43 -0700102}
103
104static int sysc_get_one_clock(struct sysc *ddata,
105 enum sysc_clocks index)
106{
107 const char *name;
108 int error;
109
110 switch (index) {
111 case SYSC_FCK:
112 break;
113 case SYSC_ICK:
114 break;
115 default:
116 return -EINVAL;
117 }
118 name = clock_names[index];
119
120 ddata->clocks[index] = devm_clk_get(ddata->dev, name);
121 if (IS_ERR(ddata->clocks[index])) {
122 if (PTR_ERR(ddata->clocks[index]) == -ENOENT)
123 return 0;
124
125 dev_err(ddata->dev, "clock get error for %s: %li\n",
126 name, PTR_ERR(ddata->clocks[index]));
127
128 return PTR_ERR(ddata->clocks[index]);
129 }
130
131 error = clk_prepare(ddata->clocks[index]);
132 if (error) {
133 dev_err(ddata->dev, "clock prepare error for %s: %i\n",
134 name, error);
135
136 return error;
137 }
138
139 return 0;
140}
141
142static int sysc_get_clocks(struct sysc *ddata)
143{
144 int i, error;
145
Tony Lindgren0eecc632017-10-10 14:23:43 -0700146 for (i = 0; i < SYSC_MAX_CLOCKS; i++) {
147 error = sysc_get_one_clock(ddata, i);
148 if (error && error != -ENOENT)
149 return error;
150 }
151
152 return 0;
153}
154
155/**
156 * sysc_parse_and_check_child_range - parses module IO region from ranges
157 * @ddata: device driver data
158 *
159 * In general we only need rev, syss, and sysc registers and not the whole
160 * module range. But we do want the offsets for these registers from the
161 * module base. This allows us to check them against the legacy hwmod
162 * platform data. Let's also check the ranges are configured properly.
163 */
164static int sysc_parse_and_check_child_range(struct sysc *ddata)
165{
166 struct device_node *np = ddata->dev->of_node;
167 const __be32 *ranges;
168 u32 nr_addr, nr_size;
169 int len, error;
170
171 ranges = of_get_property(np, "ranges", &len);
172 if (!ranges) {
173 dev_err(ddata->dev, "missing ranges for %pOF\n", np);
174
175 return -ENOENT;
176 }
177
178 len /= sizeof(*ranges);
179
180 if (len < 3) {
181 dev_err(ddata->dev, "incomplete ranges for %pOF\n", np);
182
183 return -EINVAL;
184 }
185
186 error = of_property_read_u32(np, "#address-cells", &nr_addr);
187 if (error)
188 return -ENOENT;
189
190 error = of_property_read_u32(np, "#size-cells", &nr_size);
191 if (error)
192 return -ENOENT;
193
194 if (nr_addr != 1 || nr_size != 1) {
195 dev_err(ddata->dev, "invalid ranges for %pOF\n", np);
196
197 return -EINVAL;
198 }
199
200 ranges++;
201 ddata->module_pa = of_translate_address(np, ranges++);
202 ddata->module_size = be32_to_cpup(ranges);
203
Tony Lindgren0eecc632017-10-10 14:23:43 -0700204 return 0;
205}
206
Tony Lindgren3bb37c82018-02-22 14:05:14 -0800207static struct device_node *stdout_path;
208
209static void sysc_init_stdout_path(struct sysc *ddata)
210{
211 struct device_node *np = NULL;
212 const char *uart;
213
214 if (IS_ERR(stdout_path))
215 return;
216
217 if (stdout_path)
218 return;
219
220 np = of_find_node_by_path("/chosen");
221 if (!np)
222 goto err;
223
224 uart = of_get_property(np, "stdout-path", NULL);
225 if (!uart)
226 goto err;
227
228 np = of_find_node_by_path(uart);
229 if (!np)
230 goto err;
231
232 stdout_path = np;
233
234 return;
235
236err:
237 stdout_path = ERR_PTR(-ENODEV);
238}
239
240static void sysc_check_quirk_stdout(struct sysc *ddata,
241 struct device_node *np)
242{
243 sysc_init_stdout_path(ddata);
244 if (np != stdout_path)
245 return;
246
247 ddata->cfg.quirks |= SYSC_QUIRK_NO_IDLE_ON_INIT |
248 SYSC_QUIRK_NO_RESET_ON_INIT;
249}
250
Tony Lindgren0eecc632017-10-10 14:23:43 -0700251/**
252 * sysc_check_one_child - check child configuration
253 * @ddata: device driver data
254 * @np: child device node
255 *
256 * Let's avoid messy situations where we have new interconnect target
257 * node but children have "ti,hwmods". These belong to the interconnect
258 * target node and are managed by this driver.
259 */
260static int sysc_check_one_child(struct sysc *ddata,
261 struct device_node *np)
262{
263 const char *name;
264
265 name = of_get_property(np, "ti,hwmods", NULL);
266 if (name)
267 dev_warn(ddata->dev, "really a child ti,hwmods property?");
268
Tony Lindgren3bb37c82018-02-22 14:05:14 -0800269 sysc_check_quirk_stdout(ddata, np);
270
Tony Lindgren0eecc632017-10-10 14:23:43 -0700271 return 0;
272}
273
274static int sysc_check_children(struct sysc *ddata)
275{
276 struct device_node *child;
277 int error;
278
279 for_each_child_of_node(ddata->dev->of_node, child) {
280 error = sysc_check_one_child(ddata, child);
281 if (error)
282 return error;
283 }
284
285 return 0;
286}
287
Tony Lindgrena7199e22017-12-15 09:41:14 -0800288/*
289 * So far only I2C uses 16-bit read access with clockactivity with revision
290 * in two registers with stride of 4. We can detect this based on the rev
291 * register size to configure things far enough to be able to properly read
292 * the revision register.
293 */
294static void sysc_check_quirk_16bit(struct sysc *ddata, struct resource *res)
295{
Tony Lindgrendd57ac12018-02-22 14:09:57 -0800296 if (resource_size(res) == 8)
Tony Lindgrena7199e22017-12-15 09:41:14 -0800297 ddata->cfg.quirks |= SYSC_QUIRK_16BIT | SYSC_QUIRK_USE_CLOCKACT;
Tony Lindgrena7199e22017-12-15 09:41:14 -0800298}
299
Tony Lindgren0eecc632017-10-10 14:23:43 -0700300/**
301 * sysc_parse_one - parses the interconnect target module registers
302 * @ddata: device driver data
303 * @reg: register to parse
304 */
305static int sysc_parse_one(struct sysc *ddata, enum sysc_registers reg)
306{
307 struct resource *res;
308 const char *name;
309
310 switch (reg) {
311 case SYSC_REVISION:
312 case SYSC_SYSCONFIG:
313 case SYSC_SYSSTATUS:
314 name = reg_names[reg];
315 break;
316 default:
317 return -EINVAL;
318 }
319
320 res = platform_get_resource_byname(to_platform_device(ddata->dev),
321 IORESOURCE_MEM, name);
322 if (!res) {
Tony Lindgren0eecc632017-10-10 14:23:43 -0700323 ddata->offsets[reg] = -ENODEV;
324
325 return 0;
326 }
327
328 ddata->offsets[reg] = res->start - ddata->module_pa;
Tony Lindgrena7199e22017-12-15 09:41:14 -0800329 if (reg == SYSC_REVISION)
330 sysc_check_quirk_16bit(ddata, res);
Tony Lindgren0eecc632017-10-10 14:23:43 -0700331
332 return 0;
333}
334
335static int sysc_parse_registers(struct sysc *ddata)
336{
337 int i, error;
338
339 for (i = 0; i < SYSC_MAX_REGS; i++) {
340 error = sysc_parse_one(ddata, i);
341 if (error)
342 return error;
343 }
344
345 return 0;
346}
347
348/**
349 * sysc_check_registers - check for misconfigured register overlaps
350 * @ddata: device driver data
351 */
352static int sysc_check_registers(struct sysc *ddata)
353{
354 int i, j, nr_regs = 0, nr_matches = 0;
355
356 for (i = 0; i < SYSC_MAX_REGS; i++) {
357 if (ddata->offsets[i] < 0)
358 continue;
359
360 if (ddata->offsets[i] > (ddata->module_size - 4)) {
361 dev_err(ddata->dev, "register outside module range");
362
363 return -EINVAL;
364 }
365
366 for (j = 0; j < SYSC_MAX_REGS; j++) {
367 if (ddata->offsets[j] < 0)
368 continue;
369
370 if (ddata->offsets[i] == ddata->offsets[j])
371 nr_matches++;
372 }
373 nr_regs++;
374 }
375
376 if (nr_regs < 1) {
377 dev_err(ddata->dev, "missing registers\n");
378
379 return -EINVAL;
380 }
381
382 if (nr_matches > nr_regs) {
383 dev_err(ddata->dev, "overlapping registers: (%i/%i)",
384 nr_regs, nr_matches);
385
386 return -EINVAL;
387 }
388
389 return 0;
390}
391
392/**
393 * syc_ioremap - ioremap register space for the interconnect target module
394 * @ddata: deviec driver data
395 *
396 * Note that the interconnect target module registers can be anywhere
397 * within the first child device address space. For example, SGX has
398 * them at offset 0x1fc00 in the 32MB module address space. We just
399 * what we need around the interconnect target module registers.
400 */
401static int sysc_ioremap(struct sysc *ddata)
402{
403 u32 size = 0;
404
405 if (ddata->offsets[SYSC_SYSSTATUS] >= 0)
406 size = ddata->offsets[SYSC_SYSSTATUS];
407 else if (ddata->offsets[SYSC_SYSCONFIG] >= 0)
408 size = ddata->offsets[SYSC_SYSCONFIG];
409 else if (ddata->offsets[SYSC_REVISION] >= 0)
410 size = ddata->offsets[SYSC_REVISION];
411 else
412 return -EINVAL;
413
414 size &= 0xfff00;
415 size += SZ_256;
416
417 ddata->module_va = devm_ioremap(ddata->dev,
418 ddata->module_pa,
419 size);
420 if (!ddata->module_va)
421 return -EIO;
422
423 return 0;
424}
425
426/**
427 * sysc_map_and_check_registers - ioremap and check device registers
428 * @ddata: device driver data
429 */
430static int sysc_map_and_check_registers(struct sysc *ddata)
431{
432 int error;
433
434 error = sysc_parse_and_check_child_range(ddata);
435 if (error)
436 return error;
437
438 error = sysc_check_children(ddata);
439 if (error)
440 return error;
441
442 error = sysc_parse_registers(ddata);
443 if (error)
444 return error;
445
446 error = sysc_ioremap(ddata);
447 if (error)
448 return error;
449
450 error = sysc_check_registers(ddata);
451 if (error)
452 return error;
453
454 return 0;
455}
456
457/**
458 * sysc_show_rev - read and show interconnect target module revision
459 * @bufp: buffer to print the information to
460 * @ddata: device driver data
461 */
462static int sysc_show_rev(char *bufp, struct sysc *ddata)
463{
Tony Lindgren566a9b052017-12-15 09:41:19 -0800464 int len;
Tony Lindgren0eecc632017-10-10 14:23:43 -0700465
466 if (ddata->offsets[SYSC_REVISION] < 0)
467 return sprintf(bufp, ":NA");
468
Tony Lindgren566a9b052017-12-15 09:41:19 -0800469 len = sprintf(bufp, ":%08x", ddata->revision);
Tony Lindgren0eecc632017-10-10 14:23:43 -0700470
471 return len;
472}
473
474static int sysc_show_reg(struct sysc *ddata,
475 char *bufp, enum sysc_registers reg)
476{
477 if (ddata->offsets[reg] < 0)
478 return sprintf(bufp, ":NA");
479
480 return sprintf(bufp, ":%x", ddata->offsets[reg]);
481}
482
483/**
484 * sysc_show_registers - show information about interconnect target module
485 * @ddata: device driver data
486 */
487static void sysc_show_registers(struct sysc *ddata)
488{
489 char buf[128];
490 char *bufp = buf;
491 int i;
492
493 for (i = 0; i < SYSC_MAX_REGS; i++)
494 bufp += sysc_show_reg(ddata, bufp, i);
495
496 bufp += sysc_show_rev(bufp, ddata);
497
498 dev_dbg(ddata->dev, "%llx:%x%s\n",
499 ddata->module_pa, ddata->module_size,
500 buf);
501}
502
Arnd Bergmanna4a5d492017-10-13 11:25:32 +0200503static int __maybe_unused sysc_runtime_suspend(struct device *dev)
Tony Lindgren0eecc632017-10-10 14:23:43 -0700504{
505 struct sysc *ddata;
506 int i;
507
508 ddata = dev_get_drvdata(dev);
509
510 if (ddata->legacy_mode)
511 return 0;
512
513 for (i = 0; i < SYSC_MAX_CLOCKS; i++) {
514 if (IS_ERR_OR_NULL(ddata->clocks[i]))
515 continue;
516 clk_disable(ddata->clocks[i]);
517 }
518
519 return 0;
520}
521
Arnd Bergmanna4a5d492017-10-13 11:25:32 +0200522static int __maybe_unused sysc_runtime_resume(struct device *dev)
Tony Lindgren0eecc632017-10-10 14:23:43 -0700523{
524 struct sysc *ddata;
525 int i, error;
526
527 ddata = dev_get_drvdata(dev);
528
529 if (ddata->legacy_mode)
530 return 0;
531
532 for (i = 0; i < SYSC_MAX_CLOCKS; i++) {
533 if (IS_ERR_OR_NULL(ddata->clocks[i]))
534 continue;
535 error = clk_enable(ddata->clocks[i]);
536 if (error)
537 return error;
538 }
539
540 return 0;
541}
542
Tony Lindgren62020f22018-02-22 13:59:44 -0800543#ifdef CONFIG_PM_SLEEP
544static int sysc_suspend(struct device *dev)
545{
546 struct sysc *ddata;
547
548 ddata = dev_get_drvdata(dev);
549
550 if (!ddata->enabled)
551 return 0;
552
553 ddata->needs_resume = true;
554
555 return sysc_runtime_suspend(dev);
556}
557
558static int sysc_resume(struct device *dev)
559{
560 struct sysc *ddata;
561
562 ddata = dev_get_drvdata(dev);
563 if (ddata->needs_resume) {
564 ddata->needs_resume = false;
565
566 return sysc_runtime_resume(dev);
567 }
568
569 return 0;
570}
571#endif
572
Tony Lindgren0eecc632017-10-10 14:23:43 -0700573static const struct dev_pm_ops sysc_pm_ops = {
Tony Lindgren62020f22018-02-22 13:59:44 -0800574 SET_SYSTEM_SLEEP_PM_OPS(sysc_suspend, sysc_resume)
Tony Lindgren0eecc632017-10-10 14:23:43 -0700575 SET_RUNTIME_PM_OPS(sysc_runtime_suspend,
576 sysc_runtime_resume,
577 NULL)
578};
579
Tony Lindgren566a9b052017-12-15 09:41:19 -0800580/* At this point the module is configured enough to read the revision */
581static int sysc_init_module(struct sysc *ddata)
582{
583 int error;
584
585 error = pm_runtime_get_sync(ddata->dev);
586 if (error < 0) {
587 pm_runtime_put_noidle(ddata->dev);
588
589 return 0;
590 }
591 ddata->revision = sysc_read_revision(ddata);
592 pm_runtime_put_sync(ddata->dev);
593
594 return 0;
595}
596
Tony Lindgrenc5a2de92017-12-15 09:41:23 -0800597static int sysc_init_sysc_mask(struct sysc *ddata)
598{
599 struct device_node *np = ddata->dev->of_node;
600 int error;
601 u32 val;
602
603 error = of_property_read_u32(np, "ti,sysc-mask", &val);
604 if (error)
605 return 0;
606
607 if (val)
608 ddata->cfg.sysc_val = val & ddata->cap->sysc_mask;
609 else
610 ddata->cfg.sysc_val = ddata->cap->sysc_mask;
611
612 return 0;
613}
614
615static int sysc_init_idlemode(struct sysc *ddata, u8 *idlemodes,
616 const char *name)
617{
618 struct device_node *np = ddata->dev->of_node;
619 struct property *prop;
620 const __be32 *p;
621 u32 val;
622
623 of_property_for_each_u32(np, name, prop, p, val) {
624 if (val >= SYSC_NR_IDLEMODES) {
625 dev_err(ddata->dev, "invalid idlemode: %i\n", val);
626 return -EINVAL;
627 }
628 *idlemodes |= (1 << val);
629 }
630
631 return 0;
632}
633
634static int sysc_init_idlemodes(struct sysc *ddata)
635{
636 int error;
637
638 error = sysc_init_idlemode(ddata, &ddata->cfg.midlemodes,
639 "ti,sysc-midle");
640 if (error)
641 return error;
642
643 error = sysc_init_idlemode(ddata, &ddata->cfg.sidlemodes,
644 "ti,sysc-sidle");
645 if (error)
646 return error;
647
648 return 0;
649}
650
651/*
652 * Only some devices on omap4 and later have SYSCONFIG reset done
653 * bit. We can detect this if there is no SYSSTATUS at all, or the
654 * SYSTATUS bit 0 is not used. Note that some SYSSTATUS registers
655 * have multiple bits for the child devices like OHCI and EHCI.
656 * Depends on SYSC being parsed first.
657 */
658static int sysc_init_syss_mask(struct sysc *ddata)
659{
660 struct device_node *np = ddata->dev->of_node;
661 int error;
662 u32 val;
663
664 error = of_property_read_u32(np, "ti,syss-mask", &val);
665 if (error) {
666 if ((ddata->cap->type == TI_SYSC_OMAP4 ||
667 ddata->cap->type == TI_SYSC_OMAP4_TIMER) &&
668 (ddata->cfg.sysc_val & SYSC_OMAP4_SOFTRESET))
669 ddata->cfg.quirks |= SYSC_QUIRK_RESET_STATUS;
670
671 return 0;
672 }
673
674 if (!(val & 1) && (ddata->cfg.sysc_val & SYSC_OMAP4_SOFTRESET))
675 ddata->cfg.quirks |= SYSC_QUIRK_RESET_STATUS;
676
677 ddata->cfg.syss_mask = val;
678
679 return 0;
680}
681
Tony Lindgren2c355ff2018-02-22 13:58:03 -0800682/*
683 * Many child device drivers need to have fck available to get the clock
684 * rate for device internal configuration.
685 */
686static int sysc_child_add_fck(struct sysc *ddata,
687 struct device *child)
688{
689 struct clk *fck;
690 struct clk_lookup *l;
691 const char *name = clock_names[SYSC_FCK];
692
693 if (IS_ERR_OR_NULL(ddata->clocks[SYSC_FCK]))
694 return 0;
695
696 fck = clk_get(child, name);
697 if (!IS_ERR(fck)) {
698 clk_put(fck);
699
700 return -EEXIST;
701 }
702
703 l = clkdev_create(ddata->clocks[SYSC_FCK], name, dev_name(child));
704
705 return l ? 0 : -ENODEV;
706}
707
708static struct device_type sysc_device_type = {
709};
710
711static struct sysc *sysc_child_to_parent(struct device *dev)
712{
713 struct device *parent = dev->parent;
714
715 if (!parent || parent->type != &sysc_device_type)
716 return NULL;
717
718 return dev_get_drvdata(parent);
719}
720
721static int sysc_notifier_call(struct notifier_block *nb,
722 unsigned long event, void *device)
723{
724 struct device *dev = device;
725 struct sysc *ddata;
726 int error;
727
728 ddata = sysc_child_to_parent(dev);
729 if (!ddata)
730 return NOTIFY_DONE;
731
732 switch (event) {
733 case BUS_NOTIFY_ADD_DEVICE:
734 error = sysc_child_add_fck(ddata, dev);
735 if (error && error != -EEXIST)
736 dev_warn(ddata->dev, "could not add %s fck: %i\n",
737 dev_name(dev), error);
738 break;
739 default:
740 break;
741 }
742
743 return NOTIFY_DONE;
744}
745
746static struct notifier_block sysc_nb = {
747 .notifier_call = sysc_notifier_call,
748};
749
Tony Lindgren566a9b052017-12-15 09:41:19 -0800750/* Device tree configured quirks */
751struct sysc_dts_quirk {
752 const char *name;
753 u32 mask;
754};
755
756static const struct sysc_dts_quirk sysc_dts_quirks[] = {
757 { .name = "ti,no-idle-on-init",
758 .mask = SYSC_QUIRK_NO_IDLE_ON_INIT, },
759 { .name = "ti,no-reset-on-init",
760 .mask = SYSC_QUIRK_NO_RESET_ON_INIT, },
761};
762
763static int sysc_init_dts_quirks(struct sysc *ddata)
764{
765 struct device_node *np = ddata->dev->of_node;
766 const struct property *prop;
767 int i, len, error;
768 u32 val;
769
770 ddata->legacy_mode = of_get_property(np, "ti,hwmods", NULL);
771
772 for (i = 0; i < ARRAY_SIZE(sysc_dts_quirks); i++) {
773 prop = of_get_property(np, sysc_dts_quirks[i].name, &len);
774 if (!prop)
775 break;
776
777 ddata->cfg.quirks |= sysc_dts_quirks[i].mask;
778 }
779
780 error = of_property_read_u32(np, "ti,sysc-delay-us", &val);
781 if (!error) {
782 if (val > 255) {
783 dev_warn(ddata->dev, "bad ti,sysc-delay-us: %i\n",
784 val);
785 }
786
787 ddata->cfg.srst_udelay = (u8)val;
788 }
789
790 return 0;
791}
792
Tony Lindgren0eecc632017-10-10 14:23:43 -0700793static void sysc_unprepare(struct sysc *ddata)
794{
795 int i;
796
797 for (i = 0; i < SYSC_MAX_CLOCKS; i++) {
798 if (!IS_ERR_OR_NULL(ddata->clocks[i]))
799 clk_unprepare(ddata->clocks[i]);
800 }
801}
802
Tony Lindgren70a65242017-12-15 09:41:09 -0800803/*
804 * Common sysc register bits found on omap2, also known as type1
805 */
806static const struct sysc_regbits sysc_regbits_omap2 = {
807 .dmadisable_shift = -ENODEV,
808 .midle_shift = 12,
809 .sidle_shift = 3,
810 .clkact_shift = 8,
811 .emufree_shift = 5,
812 .enwkup_shift = 2,
813 .srst_shift = 1,
814 .autoidle_shift = 0,
815};
816
817static const struct sysc_capabilities sysc_omap2 = {
818 .type = TI_SYSC_OMAP2,
819 .sysc_mask = SYSC_OMAP2_CLOCKACTIVITY | SYSC_OMAP2_EMUFREE |
820 SYSC_OMAP2_ENAWAKEUP | SYSC_OMAP2_SOFTRESET |
821 SYSC_OMAP2_AUTOIDLE,
822 .regbits = &sysc_regbits_omap2,
823};
824
825/* All omap2 and 3 timers, and timers 1, 2 & 10 on omap 4 and 5 */
826static const struct sysc_capabilities sysc_omap2_timer = {
827 .type = TI_SYSC_OMAP2_TIMER,
828 .sysc_mask = SYSC_OMAP2_CLOCKACTIVITY | SYSC_OMAP2_EMUFREE |
829 SYSC_OMAP2_ENAWAKEUP | SYSC_OMAP2_SOFTRESET |
830 SYSC_OMAP2_AUTOIDLE,
831 .regbits = &sysc_regbits_omap2,
832 .mod_quirks = SYSC_QUIRK_USE_CLOCKACT,
833};
834
835/*
836 * SHAM2 (SHA1/MD5) sysc found on omap3, a variant of sysc_regbits_omap2
837 * with different sidle position
838 */
839static const struct sysc_regbits sysc_regbits_omap3_sham = {
840 .dmadisable_shift = -ENODEV,
841 .midle_shift = -ENODEV,
842 .sidle_shift = 4,
843 .clkact_shift = -ENODEV,
844 .enwkup_shift = -ENODEV,
845 .srst_shift = 1,
846 .autoidle_shift = 0,
847 .emufree_shift = -ENODEV,
848};
849
850static const struct sysc_capabilities sysc_omap3_sham = {
851 .type = TI_SYSC_OMAP3_SHAM,
852 .sysc_mask = SYSC_OMAP2_SOFTRESET | SYSC_OMAP2_AUTOIDLE,
853 .regbits = &sysc_regbits_omap3_sham,
854};
855
856/*
857 * AES register bits found on omap3 and later, a variant of
858 * sysc_regbits_omap2 with different sidle position
859 */
860static const struct sysc_regbits sysc_regbits_omap3_aes = {
861 .dmadisable_shift = -ENODEV,
862 .midle_shift = -ENODEV,
863 .sidle_shift = 6,
864 .clkact_shift = -ENODEV,
865 .enwkup_shift = -ENODEV,
866 .srst_shift = 1,
867 .autoidle_shift = 0,
868 .emufree_shift = -ENODEV,
869};
870
871static const struct sysc_capabilities sysc_omap3_aes = {
872 .type = TI_SYSC_OMAP3_AES,
873 .sysc_mask = SYSC_OMAP2_SOFTRESET | SYSC_OMAP2_AUTOIDLE,
874 .regbits = &sysc_regbits_omap3_aes,
875};
876
877/*
878 * Common sysc register bits found on omap4, also known as type2
879 */
880static const struct sysc_regbits sysc_regbits_omap4 = {
881 .dmadisable_shift = 16,
882 .midle_shift = 4,
883 .sidle_shift = 2,
884 .clkact_shift = -ENODEV,
885 .enwkup_shift = -ENODEV,
886 .emufree_shift = 1,
887 .srst_shift = 0,
888 .autoidle_shift = -ENODEV,
889};
890
891static const struct sysc_capabilities sysc_omap4 = {
892 .type = TI_SYSC_OMAP4,
893 .sysc_mask = SYSC_OMAP4_DMADISABLE | SYSC_OMAP4_FREEEMU |
894 SYSC_OMAP4_SOFTRESET,
895 .regbits = &sysc_regbits_omap4,
896};
897
898static const struct sysc_capabilities sysc_omap4_timer = {
899 .type = TI_SYSC_OMAP4_TIMER,
900 .sysc_mask = SYSC_OMAP4_DMADISABLE | SYSC_OMAP4_FREEEMU |
901 SYSC_OMAP4_SOFTRESET,
902 .regbits = &sysc_regbits_omap4,
903};
904
905/*
906 * Common sysc register bits found on omap4, also known as type3
907 */
908static const struct sysc_regbits sysc_regbits_omap4_simple = {
909 .dmadisable_shift = -ENODEV,
910 .midle_shift = 2,
911 .sidle_shift = 0,
912 .clkact_shift = -ENODEV,
913 .enwkup_shift = -ENODEV,
914 .srst_shift = -ENODEV,
915 .emufree_shift = -ENODEV,
916 .autoidle_shift = -ENODEV,
917};
918
919static const struct sysc_capabilities sysc_omap4_simple = {
920 .type = TI_SYSC_OMAP4_SIMPLE,
921 .regbits = &sysc_regbits_omap4_simple,
922};
923
924/*
925 * SmartReflex sysc found on omap34xx
926 */
927static const struct sysc_regbits sysc_regbits_omap34xx_sr = {
928 .dmadisable_shift = -ENODEV,
929 .midle_shift = -ENODEV,
930 .sidle_shift = -ENODEV,
931 .clkact_shift = 20,
932 .enwkup_shift = -ENODEV,
933 .srst_shift = -ENODEV,
934 .emufree_shift = -ENODEV,
935 .autoidle_shift = -ENODEV,
936};
937
938static const struct sysc_capabilities sysc_34xx_sr = {
939 .type = TI_SYSC_OMAP34XX_SR,
940 .sysc_mask = SYSC_OMAP2_CLOCKACTIVITY,
941 .regbits = &sysc_regbits_omap34xx_sr,
942 .mod_quirks = SYSC_QUIRK_USE_CLOCKACT | SYSC_QUIRK_UNCACHED,
943};
944
945/*
946 * SmartReflex sysc found on omap36xx and later
947 */
948static const struct sysc_regbits sysc_regbits_omap36xx_sr = {
949 .dmadisable_shift = -ENODEV,
950 .midle_shift = -ENODEV,
951 .sidle_shift = 24,
952 .clkact_shift = -ENODEV,
953 .enwkup_shift = 26,
954 .srst_shift = -ENODEV,
955 .emufree_shift = -ENODEV,
956 .autoidle_shift = -ENODEV,
957};
958
959static const struct sysc_capabilities sysc_36xx_sr = {
960 .type = TI_SYSC_OMAP36XX_SR,
Tony Lindgren3267c082018-01-22 09:32:53 -0800961 .sysc_mask = SYSC_OMAP3_SR_ENAWAKEUP,
Tony Lindgren70a65242017-12-15 09:41:09 -0800962 .regbits = &sysc_regbits_omap36xx_sr,
963 .mod_quirks = SYSC_QUIRK_UNCACHED,
964};
965
966static const struct sysc_capabilities sysc_omap4_sr = {
967 .type = TI_SYSC_OMAP4_SR,
968 .regbits = &sysc_regbits_omap36xx_sr,
969};
970
971/*
972 * McASP register bits found on omap4 and later
973 */
974static const struct sysc_regbits sysc_regbits_omap4_mcasp = {
975 .dmadisable_shift = -ENODEV,
976 .midle_shift = -ENODEV,
977 .sidle_shift = 0,
978 .clkact_shift = -ENODEV,
979 .enwkup_shift = -ENODEV,
980 .srst_shift = -ENODEV,
981 .emufree_shift = -ENODEV,
982 .autoidle_shift = -ENODEV,
983};
984
985static const struct sysc_capabilities sysc_omap4_mcasp = {
986 .type = TI_SYSC_OMAP4_MCASP,
987 .regbits = &sysc_regbits_omap4_mcasp,
988};
989
990/*
991 * FS USB host found on omap4 and later
992 */
993static const struct sysc_regbits sysc_regbits_omap4_usb_host_fs = {
994 .dmadisable_shift = -ENODEV,
995 .midle_shift = -ENODEV,
996 .sidle_shift = 24,
997 .clkact_shift = -ENODEV,
998 .enwkup_shift = 26,
999 .srst_shift = -ENODEV,
1000 .emufree_shift = -ENODEV,
1001 .autoidle_shift = -ENODEV,
1002};
1003
1004static const struct sysc_capabilities sysc_omap4_usb_host_fs = {
1005 .type = TI_SYSC_OMAP4_USB_HOST_FS,
1006 .sysc_mask = SYSC_OMAP2_ENAWAKEUP,
1007 .regbits = &sysc_regbits_omap4_usb_host_fs,
1008};
1009
1010static int sysc_init_match(struct sysc *ddata)
1011{
1012 const struct sysc_capabilities *cap;
1013
1014 cap = of_device_get_match_data(ddata->dev);
1015 if (!cap)
1016 return -EINVAL;
1017
1018 ddata->cap = cap;
1019 if (ddata->cap)
1020 ddata->cfg.quirks |= ddata->cap->mod_quirks;
1021
1022 return 0;
1023}
1024
Tony Lindgren76f0f772018-02-23 08:28:45 -08001025static void ti_sysc_idle(struct work_struct *work)
1026{
1027 struct sysc *ddata;
1028
1029 ddata = container_of(work, struct sysc, idle_work.work);
1030
1031 if (pm_runtime_active(ddata->dev))
1032 pm_runtime_put_sync(ddata->dev);
1033}
1034
Tony Lindgren0eecc632017-10-10 14:23:43 -07001035static int sysc_probe(struct platform_device *pdev)
1036{
Tony Lindgren0eecc632017-10-10 14:23:43 -07001037 struct sysc *ddata;
1038 int error;
1039
1040 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
1041 if (!ddata)
1042 return -ENOMEM;
1043
1044 ddata->dev = &pdev->dev;
Tony Lindgren566a9b052017-12-15 09:41:19 -08001045 platform_set_drvdata(pdev, ddata);
Tony Lindgren0eecc632017-10-10 14:23:43 -07001046
Tony Lindgren70a65242017-12-15 09:41:09 -08001047 error = sysc_init_match(ddata);
1048 if (error)
1049 return error;
1050
Tony Lindgren566a9b052017-12-15 09:41:19 -08001051 error = sysc_init_dts_quirks(ddata);
1052 if (error)
1053 goto unprepare;
1054
Tony Lindgren0eecc632017-10-10 14:23:43 -07001055 error = sysc_get_clocks(ddata);
1056 if (error)
1057 return error;
1058
1059 error = sysc_map_and_check_registers(ddata);
1060 if (error)
1061 goto unprepare;
1062
Tony Lindgrenc5a2de92017-12-15 09:41:23 -08001063 error = sysc_init_sysc_mask(ddata);
1064 if (error)
1065 goto unprepare;
1066
1067 error = sysc_init_idlemodes(ddata);
1068 if (error)
1069 goto unprepare;
1070
1071 error = sysc_init_syss_mask(ddata);
1072 if (error)
1073 goto unprepare;
1074
Tony Lindgren0eecc632017-10-10 14:23:43 -07001075 pm_runtime_enable(ddata->dev);
Tony Lindgren566a9b052017-12-15 09:41:19 -08001076
1077 error = sysc_init_module(ddata);
1078 if (error)
1079 goto unprepare;
1080
Tony Lindgren0eecc632017-10-10 14:23:43 -07001081 error = pm_runtime_get_sync(ddata->dev);
1082 if (error < 0) {
1083 pm_runtime_put_noidle(ddata->dev);
1084 pm_runtime_disable(ddata->dev);
1085 goto unprepare;
1086 }
1087
Tony Lindgren0eecc632017-10-10 14:23:43 -07001088 sysc_show_registers(ddata);
1089
Tony Lindgren2c355ff2018-02-22 13:58:03 -08001090 ddata->dev->type = &sysc_device_type;
Tony Lindgren0eecc632017-10-10 14:23:43 -07001091 error = of_platform_populate(ddata->dev->of_node,
1092 NULL, NULL, ddata->dev);
1093 if (error)
1094 goto err;
1095
Tony Lindgren76f0f772018-02-23 08:28:45 -08001096 INIT_DELAYED_WORK(&ddata->idle_work, ti_sysc_idle);
1097
1098 /* At least earlycon won't survive without deferred idle */
1099 if (ddata->cfg.quirks & (SYSC_QUIRK_NO_IDLE_ON_INIT |
1100 SYSC_QUIRK_NO_RESET_ON_INIT)) {
1101 schedule_delayed_work(&ddata->idle_work, 3000);
1102 } else {
1103 pm_runtime_put(&pdev->dev);
1104 }
Tony Lindgren0eecc632017-10-10 14:23:43 -07001105
1106 return 0;
1107
1108err:
Tony Lindgren0eecc632017-10-10 14:23:43 -07001109 pm_runtime_put_sync(&pdev->dev);
1110 pm_runtime_disable(&pdev->dev);
1111unprepare:
1112 sysc_unprepare(ddata);
1113
1114 return error;
1115}
1116
Tony Lindgren684be5a2017-10-13 10:48:40 -07001117static int sysc_remove(struct platform_device *pdev)
1118{
1119 struct sysc *ddata = platform_get_drvdata(pdev);
1120 int error;
1121
Tony Lindgren76f0f772018-02-23 08:28:45 -08001122 cancel_delayed_work_sync(&ddata->idle_work);
1123
Tony Lindgren684be5a2017-10-13 10:48:40 -07001124 error = pm_runtime_get_sync(ddata->dev);
1125 if (error < 0) {
1126 pm_runtime_put_noidle(ddata->dev);
1127 pm_runtime_disable(ddata->dev);
1128 goto unprepare;
1129 }
1130
1131 of_platform_depopulate(&pdev->dev);
1132
Tony Lindgren684be5a2017-10-13 10:48:40 -07001133 pm_runtime_put_sync(&pdev->dev);
1134 pm_runtime_disable(&pdev->dev);
1135
1136unprepare:
1137 sysc_unprepare(ddata);
1138
1139 return 0;
1140}
1141
Tony Lindgren0eecc632017-10-10 14:23:43 -07001142static const struct of_device_id sysc_match[] = {
Tony Lindgren70a65242017-12-15 09:41:09 -08001143 { .compatible = "ti,sysc-omap2", .data = &sysc_omap2, },
1144 { .compatible = "ti,sysc-omap2-timer", .data = &sysc_omap2_timer, },
1145 { .compatible = "ti,sysc-omap4", .data = &sysc_omap4, },
1146 { .compatible = "ti,sysc-omap4-timer", .data = &sysc_omap4_timer, },
1147 { .compatible = "ti,sysc-omap4-simple", .data = &sysc_omap4_simple, },
1148 { .compatible = "ti,sysc-omap3430-sr", .data = &sysc_34xx_sr, },
1149 { .compatible = "ti,sysc-omap3630-sr", .data = &sysc_36xx_sr, },
1150 { .compatible = "ti,sysc-omap4-sr", .data = &sysc_omap4_sr, },
1151 { .compatible = "ti,sysc-omap3-sham", .data = &sysc_omap3_sham, },
1152 { .compatible = "ti,sysc-omap-aes", .data = &sysc_omap3_aes, },
1153 { .compatible = "ti,sysc-mcasp", .data = &sysc_omap4_mcasp, },
1154 { .compatible = "ti,sysc-usb-host-fs",
1155 .data = &sysc_omap4_usb_host_fs, },
Tony Lindgren0eecc632017-10-10 14:23:43 -07001156 { },
1157};
1158MODULE_DEVICE_TABLE(of, sysc_match);
1159
1160static struct platform_driver sysc_driver = {
1161 .probe = sysc_probe,
Tony Lindgren684be5a2017-10-13 10:48:40 -07001162 .remove = sysc_remove,
Tony Lindgren0eecc632017-10-10 14:23:43 -07001163 .driver = {
1164 .name = "ti-sysc",
1165 .of_match_table = sysc_match,
1166 .pm = &sysc_pm_ops,
1167 },
1168};
Tony Lindgren2c355ff2018-02-22 13:58:03 -08001169
1170static int __init sysc_init(void)
1171{
1172 bus_register_notifier(&platform_bus_type, &sysc_nb);
1173
1174 return platform_driver_register(&sysc_driver);
1175}
1176module_init(sysc_init);
1177
1178static void __exit sysc_exit(void)
1179{
1180 bus_unregister_notifier(&platform_bus_type, &sysc_nb);
1181 platform_driver_unregister(&sysc_driver);
1182}
1183module_exit(sysc_exit);
Tony Lindgren0eecc632017-10-10 14:23:43 -07001184
1185MODULE_DESCRIPTION("TI sysc interconnect target driver");
1186MODULE_LICENSE("GPL v2");