Hi Sergio Paracuellos!
I found there are still some areas that need improvement.
>+
>+static unsigned long rt3883_bus_recalc_rate(struct clk_hw *hw,
>+ unsigned long parent_rate)
>+{
>+ struct mtmips_clk *clk = to_mtmips_clk(hw);
>+ struct regmap *sysc = clk->priv->sysc;
>+ u32 ddr2;
>+ u32 t;
>+
>+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
>+ ddr2 = t & RT3883_SYSCFG0_DRAM_TYPE_DDR2;
>+
>+ switch (parent_rate) {
>+ case 250000000:
>+ return (ddr2) ? 125000000 : 83000000;
>+ case 384000000:
>+ return (ddr2) ? 128000000 : 96000000;
>+ case 480000000:
>+ return (ddr2) ? 160000000 : 120000000;
>+ case 500000000:
>+ return (ddr2) ? 166000000 : 125000000;
>+ default:
>+ WARN_ON_ONCE(parent_rate == 0);
drivers/clk/ralink/clk-mtmips.c: In function 'rt3883_bus_recalc_rate':
drivers/clk/ralink/clk-mtmips.c:502:1: error: control reaches end of non-void function [-Werror=return-type]
502 | }
| ^
Build error here, need to return a value, `parent_rate / 4` should be okay.
It seems that the program will never run into this default case.
>+ }
>+}
>+
>+
>+static const struct of_device_id mtmips_clk_of_match[] = {
>+ { .compatible = "ralink,rt2880-reset" },
>+ { .compatible = "ralink,rt2880-sysc" },
>+ { .compatible = "ralink,rt3050-sysc" },
>+ { .compatible = "ralink,rt3050-sysc" },
There are two `ralink,rt3050-sysc`. I think the second one should be
`ralink,rt3052-sysc`.
>+ { .compatible = "ralink,rt3352-sysc" },
>+ { .compatible = "ralink,rt3883-sysc" },
>+ { .compatible = "ralink,rt5350-sysc" },
>+ { .compatible = "ralink,mt7620a-sysc" },
>+ { .compatible = "ralink,mt7620-sysc" },
>+ { .compatible = "ralink,mt7628-sysc" },
>+ { .compatible = "ralink,mt7688-sysc" },
>+ {}
>+};
>+
> void __init plat_time_init(void)
> {
>+ struct of_phandle_args clkspec;
> struct clk *clk;
>+ int cpu_clk_idx;
>
> ralink_of_remap();
>
>- ralink_clk_init();
>- clk = clk_get_sys("cpu", NULL);
>+ cpu_clk_idx = clk_cpu_index();
>+ if (cpu_clk_idx == -1)
>+ panic("unable to get CPU clock index");
>+
>+ of_clk_init(NULL);
>+ clkspec.np = of_find_node_by_name(NULL, "sysc");
The node name should be "syscon" as the example node name in the
dt-bindings document is "syscon".
>+ clkspec.args_count = 1;
>+ clkspec.args[0] = cpu_clk_idx;
>+ clk = of_clk_get_from_provider(&clkspec);
> if (IS_ERR(clk))
> panic("unable to get CPU clock, err=%ld", PTR_ERR(clk));
> pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
It seems that the clock calculation logic of the mt7620 has changed.
The kernel got an incorrect clock frequency 3480MHz. The correct CPU
clock should be 580MHz = 3480MHz / 6.
I will test and report mt7628 later.
mt7620 dmesg:
[ 0.000000] Linux version 5.15.117 (db@Aspire-V-Nitro) (mipsel-openwrt-linux-musl-gcc (OpenWrt GCC 12.3.0 r23471+7-816fcf88f6) 12.3.0, GNU ld (GNU Binutils) 2.40.0) #0 Sat Jun 17 08:41:01 2023
[ 0.000000] Board has DDR2
[ 0.000000] Analog PMU set to hw control
[ 0.000000] Digital PMU set to hw control
[ 0.000000] SoC Type: MediaTek MT7620A ver:2 eco:6
[ 0.000000] printk: bootconsole [early0] enabled
[ 0.000000] CPU0 revision is: 00019650 (MIPS 24KEc)
[ 0.000000] MIPS: machine is Haier HW-L1W
[ 0.000000] Initrd not found or empty - disabling initrd
[ 0.000000] Primary instruction cache 64kB, VIPT, 4-way, linesize 32 bytes.
[ 0.000000] Primary data cache 32kB, 4-way, PIPT, no aliases, linesize 32 bytes
[ 0.000000] Zone ranges:
[ 0.000000] Normal [mem 0x0000000000000000-0x0000000007ffffff]
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x0000000000000000-0x0000000007ffffff]
[ 0.000000] Initmem setup node 0 [mem 0x0000000000000000-0x0000000007ffffff]
[ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 32480
[ 0.000000] Kernel command line: console=ttyS0,115200 rootfstype=squashfs,jffs2
[ 0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536 bytes, linear)
[ 0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes, linear)
[ 0.000000] Writing ErrCtl register=00064000
[ 0.000000] Readback ErrCtl register=00064000
[ 0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
[ 0.000000] Memory: 120992K/131072K available (5518K kernel code, 600K rwdata, 1192K rodata, 1192K init, 215K bss, 10080K reserved, 0K cma-reserved)
[ 0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[ 0.000000] NR_IRQS: 256
[ 0.000000] CPU Clock: 3480MHz
[ 0.000000] clocksource: systick: mask: 0xffff max_cycles: 0xffff, max_idle_ns: 583261500 ns
[ 0.000000] systick: enable autosleep mode
[ 0.000000] systick: running - mult: 214748, shift: 32
[ 0.000000] clocksource: MIPS: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1098425544 ns
[ 0.000000] sched_clock: 32 bits at 1740MHz, resolution 0ns, wraps every 1234186239ns
[ 0.001354] Calibrating delay loop... 385.84 BogoMIPS (lpj=1929216)
[ 0.012389] pid_max: default: 32768 minimum: 301
[ 0.013357] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[ 0.014589] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[ 0.017429] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[ 0.019103] futex hash table entries: 256 (order: -1, 3072 bytes, linear)
[ 0.020288] pinctrl core: initialized pinctrl subsystem
[ 0.021415] NET: Registered PF_NETLINK/PF_ROUTE protocol family
[ 0.105370] rt2880_gpio 10000600.gpio: registering 24 gpios
[ 0.106328] rt2880_gpio 10000600.gpio: registering 24 irq handlers
[ 0.107446] rt2880_gpio 10000688.gpio: registering 1 gpios
[ 0.108381] rt2880_gpio 10000688.gpio: registering 1 irq handlers
[ 0.109673] PCI host bridge to bus 0000:00
[ 0.110372] pci_bus 0000:00: root bus resource [mem 0x20000000-0x2fffffff]
[ 0.111528] pci_bus 0000:00: root bus resource [io 0x10160000-0x1016ffff]
[ 0.112695] pci_bus 0000:00: No busn resource found for root bus, will use [bus 00-ff]
[ 0.114046] pci 0000:00:00.0: [1814:0801] type 01 class 0x060400
[ 0.115059] pci 0000:00:00.0: reg 0x10: [mem 0x00000000-0x7fffffff]
[ 0.116118] pci 0000:00:00.0: reg 0x14: [mem 0x00000000-0x0000ffff]
[ 0.117195] pci 0000:00:00.0: supports D1
[ 0.117862] pci 0000:00:00.0: PME# supported from D0 D1 D3hot
[ 0.119156] pci 0000:00:00.0: bridge configuration invalid ([bus 00-00]), reconfiguring
[ 0.120556] pci 0000:01:00.0: [14c3:7650] type 00 class 0x028000
[ 0.121570] pci 0000:01:00.0: reg 0x10: [mem 0x00000000-0x000fffff]
[ 0.122658] pci 0000:01:00.0: PME# supported from D0 D3hot D3cold
[ 0.123749] pci 0000:01:00.1: [14c3:8650] type 00 class 0x0d1100
[ 0.124769] pci 0000:01:00.1: reg 0x10: [mem 0x00000000-0x000fffff]
[ 0.125844] pci 0000:01:00.1: supports D1
[ 0.126513] pci 0000:01:00.1: PME# supported from D0 D1 D3hot D3cold
[ 0.127897] pci_bus 0000:01: busn_res: [bus 01-ff] end is updated to 01
[ 0.129018] pci_bus 0000:00: busn_res: [bus 00-ff] end is updated to 01
[ 0.130138] pci 0000:00:00.0: BAR 0: no space for [mem size 0x80000000]
[ 0.131255] pci 0000:00:00.0: BAR 0: failed to assign [mem size 0x80000000]
[ 0.132434] pci 0000:00:00.0: BAR 8: assigned [mem 0x20000000-0x201fffff]
[ 0.133587] pci 0000:00:00.0: BAR 1: assigned [mem 0x20200000-0x2020ffff]
[ 0.134738] pci 0000:01:00.0: BAR 0: assigned [mem 0x20000000-0x200fffff]
[ 0.135890] pci 0000:01:00.1: BAR 0: assigned [mem 0x20100000-0x201fffff]
[ 0.137040] pci 0000:00:00.0: PCI bridge to [bus 01]
[ 0.137882] pci 0000:00:00.0: bridge window [mem 0x20000000-0x201fffff]
[ 0.139123] clocksource: Switched to clocksource MIPS
[ 0.140241] NET: Registered PF_INET protocol family
[ 0.141106] IP idents hash table entries: 2048 (order: 2, 16384 bytes, linear)
[ 0.142473] tcp_listen_portaddr_hash hash table entries: 512 (order: 0, 4096 bytes, linear)
[ 0.143893] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
[ 0.145199] TCP established hash table entries: 1024 (order: 0, 4096 bytes, linear)
[ 0.146499] TCP bind hash table entries: 1024 (order: 0, 4096 bytes, linear)
[ 0.147695] TCP: Hash tables configured (established 1024 bind 1024)
[ 0.148803] UDP hash table entries: 256 (order: 0, 4096 bytes, linear)
[ 0.149920] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes, linear)
[ 0.151177] NET: Registered PF_UNIX/PF_LOCAL protocol family
[ 0.152149] PCI: CLS 0 bytes, default 32
[ 0.152847] rt-timer 10000100.timer: failed get clock rate
[ 0.153771] rt-timer: probe of 10000100.timer failed with error -2
[ 0.155602] workingset: timestamp_bits=14 max_order=15 bucket_order=1
[ 0.157808] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[ 0.158792] jffs2: version 2.2 (NAND) (SUMMARY) (LZMA) (RTIME) (CMODE_PRIORITY) (c) 2001-2006 Red Hat, Inc.
[ 0.161032] Serial: 8250/16550 driver, 2 ports, IRQ sharing disabled
[ 0.162284] of_serial 10000c00.uartlite: failed to get clock: -2
[ 0.163300] of_serial: probe of 10000c00.uartlite failed with error -2
[ 0.164624] spi-rt2880 10000b00.spi: unable to get SYS clock
[ 0.165580] spi-rt2880: probe of 10000b00.spi failed with error -2
[ 0.171098] gsw: setting port4 to ephy mode
[ 0.171828] mtk_soc_eth 10100000.ethernet: generated random MAC address f6:6c:93:9a:c8:ca
[ 0.173208] mtk_soc_eth 10100000.ethernet: mdio-bus disabled
[ 0.174205] mtk_soc_eth 10100000.ethernet: loaded mt7620 driver
[ 0.175329] mtk_soc_eth 10100000.ethernet eth0: mediatek frame engine at 0xb0100000, irq 5
[ 0.176805] rt2880_wdt: probe of 10000120.watchdog failed with error -2
[ 0.178187] NET: Registered PF_INET6 protocol family
[ 0.179980] Segment Routing with IPv6
[ 0.180607] In-situ OAM (IOAM) with IPv6
[ 0.181290] NET: Registered PF_PACKET protocol family
[ 0.182148] 8021q: 802.1Q VLAN Support v1.8
[ 0.183347] Warning: unable to open an initial console.
[ 0.184558] /dev/root: Can't open blockdev
[ 0.185253] VFS: Cannot open root device "(null)" or unknown-block(0,0): error -6
[ 0.186516] Please append a correct "root=" boot option; here are the available partitions:
[ 0.187934] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
[ 0.189335] Rebooting in 1 seconds..
Thanks,
Shiji Yang
Hi Shiji Yang,
On Sat, Jun 17, 2023 at 2:55 PM Shiji Yang <yangshiji66@outlook.com> wrote:
>
> Hi Sergio Paracuellos!
>
> I found there are still some areas that need improvement.
Awesome! I did not expect to get testing before this is added to the
tree .As I have mentioned I have only tested this with Ralink 5350 ALL
One board. So thanks for testing this so far!! It is really helpful.
>
> >+
> >+static unsigned long rt3883_bus_recalc_rate(struct clk_hw *hw,
> >+ unsigned long parent_rate)
> >+{
> >+ struct mtmips_clk *clk = to_mtmips_clk(hw);
> >+ struct regmap *sysc = clk->priv->sysc;
> >+ u32 ddr2;
> >+ u32 t;
> >+
> >+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
> >+ ddr2 = t & RT3883_SYSCFG0_DRAM_TYPE_DDR2;
> >+
> >+ switch (parent_rate) {
> >+ case 250000000:
> >+ return (ddr2) ? 125000000 : 83000000;
> >+ case 384000000:
> >+ return (ddr2) ? 128000000 : 96000000;
> >+ case 480000000:
> >+ return (ddr2) ? 160000000 : 120000000;
> >+ case 500000000:
> >+ return (ddr2) ? 166000000 : 125000000;
> >+ default:
> >+ WARN_ON_ONCE(parent_rate == 0);
>
> drivers/clk/ralink/clk-mtmips.c: In function 'rt3883_bus_recalc_rate':
> drivers/clk/ralink/clk-mtmips.c:502:1: error: control reaches end of non-void function [-Werror=return-type]
> 502 | }
> | ^
>
> Build error here, need to return a value, `parent_rate / 4` should be okay.
> It seems that the program will never run into this default case.
Ouch, it was a BUG() call here before changing it to WARN_ON_ONCE so
yes a return is needed! Thanks!
>
> >+ }
> >+}
> >+
>
>
> >+
> >+static const struct of_device_id mtmips_clk_of_match[] = {
> >+ { .compatible = "ralink,rt2880-reset" },
> >+ { .compatible = "ralink,rt2880-sysc" },
> >+ { .compatible = "ralink,rt3050-sysc" },
> >+ { .compatible = "ralink,rt3050-sysc" },
>
> There are two `ralink,rt3050-sysc`. I think the second one should be
> `ralink,rt3052-sysc`.
True :)
>
> >+ { .compatible = "ralink,rt3352-sysc" },
> >+ { .compatible = "ralink,rt3883-sysc" },
> >+ { .compatible = "ralink,rt5350-sysc" },
> >+ { .compatible = "ralink,mt7620a-sysc" },
> >+ { .compatible = "ralink,mt7620-sysc" },
> >+ { .compatible = "ralink,mt7628-sysc" },
> >+ { .compatible = "ralink,mt7688-sysc" },
> >+ {}
> >+};
> >+
>
>
> > void __init plat_time_init(void)
> > {
> >+ struct of_phandle_args clkspec;
> > struct clk *clk;
> >+ int cpu_clk_idx;
> >
> > ralink_of_remap();
> >
> >- ralink_clk_init();
> >- clk = clk_get_sys("cpu", NULL);
> >+ cpu_clk_idx = clk_cpu_index();
> >+ if (cpu_clk_idx == -1)
> >+ panic("unable to get CPU clock index");
> >+
> >+ of_clk_init(NULL);
> >+ clkspec.np = of_find_node_by_name(NULL, "sysc");
>
> The node name should be "syscon" as the example node name in the
> dt-bindings document is "syscon".
sysc is label to get this node since it is the one shared by all
different dtsi files.
>
> >+ clkspec.args_count = 1;
> >+ clkspec.args[0] = cpu_clk_idx;
> >+ clk = of_clk_get_from_provider(&clkspec);
> > if (IS_ERR(clk))
> > panic("unable to get CPU clock, err=%ld", PTR_ERR(clk));
> > pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
>
>
> It seems that the clock calculation logic of the mt7620 has changed.
> The kernel got an incorrect clock frequency 3480MHz. The correct CPU
> clock should be 580MHz = 3480MHz / 6.
The only thing that changed a bit is the stuff with the CONFIG_USB
that I was told to change by Stephen. Can you check if that is the
problem with your bad cpu clock? Just comment the call
'mtmips_clk_regs_init' of the probe function.
>
> I will test and report mt7628 later.
Thanks!
>
> mt7620 dmesg:
> [ 0.000000] Linux version 5.15.117 (db@Aspire-V-Nitro) (mipsel-openwrt-linux-musl-gcc (OpenWrt GCC 12.3.0 r23471+7-816fcf88f6) 12.3.0, GNU ld (GNU Binutils) 2.40.0) #0 Sat Jun 17 08:41:01 2023
> [ 0.000000] Board has DDR2
> [ 0.000000] Analog PMU set to hw control
> [ 0.000000] Digital PMU set to hw control
> [ 0.000000] SoC Type: MediaTek MT7620A ver:2 eco:6
> [ 0.000000] printk: bootconsole [early0] enabled
> [ 0.000000] CPU0 revision is: 00019650 (MIPS 24KEc)
> [ 0.000000] MIPS: machine is Haier HW-L1W
> [ 0.000000] Initrd not found or empty - disabling initrd
> [ 0.000000] Primary instruction cache 64kB, VIPT, 4-way, linesize 32 bytes.
> [ 0.000000] Primary data cache 32kB, 4-way, PIPT, no aliases, linesize 32 bytes
> [ 0.000000] Zone ranges:
> [ 0.000000] Normal [mem 0x0000000000000000-0x0000000007ffffff]
> [ 0.000000] Movable zone start for each node
> [ 0.000000] Early memory node ranges
> [ 0.000000] node 0: [mem 0x0000000000000000-0x0000000007ffffff]
> [ 0.000000] Initmem setup node 0 [mem 0x0000000000000000-0x0000000007ffffff]
> [ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 32480
> [ 0.000000] Kernel command line: console=ttyS0,115200 rootfstype=squashfs,jffs2
> [ 0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536 bytes, linear)
> [ 0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes, linear)
> [ 0.000000] Writing ErrCtl register=00064000
> [ 0.000000] Readback ErrCtl register=00064000
> [ 0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
> [ 0.000000] Memory: 120992K/131072K available (5518K kernel code, 600K rwdata, 1192K rodata, 1192K init, 215K bss, 10080K reserved, 0K cma-reserved)
> [ 0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
> [ 0.000000] NR_IRQS: 256
> [ 0.000000] CPU Clock: 3480MHz
> [ 0.000000] clocksource: systick: mask: 0xffff max_cycles: 0xffff, max_idle_ns: 583261500 ns
> [ 0.000000] systick: enable autosleep mode
> [ 0.000000] systick: running - mult: 214748, shift: 32
> [ 0.000000] clocksource: MIPS: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1098425544 ns
> [ 0.000000] sched_clock: 32 bits at 1740MHz, resolution 0ns, wraps every 1234186239ns
> [ 0.001354] Calibrating delay loop... 385.84 BogoMIPS (lpj=1929216)
> [ 0.012389] pid_max: default: 32768 minimum: 301
> [ 0.013357] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
> [ 0.014589] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
> [ 0.017429] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
> [ 0.019103] futex hash table entries: 256 (order: -1, 3072 bytes, linear)
> [ 0.020288] pinctrl core: initialized pinctrl subsystem
> [ 0.021415] NET: Registered PF_NETLINK/PF_ROUTE protocol family
> [ 0.105370] rt2880_gpio 10000600.gpio: registering 24 gpios
> [ 0.106328] rt2880_gpio 10000600.gpio: registering 24 irq handlers
> [ 0.107446] rt2880_gpio 10000688.gpio: registering 1 gpios
> [ 0.108381] rt2880_gpio 10000688.gpio: registering 1 irq handlers
> [ 0.109673] PCI host bridge to bus 0000:00
> [ 0.110372] pci_bus 0000:00: root bus resource [mem 0x20000000-0x2fffffff]
> [ 0.111528] pci_bus 0000:00: root bus resource [io 0x10160000-0x1016ffff]
> [ 0.112695] pci_bus 0000:00: No busn resource found for root bus, will use [bus 00-ff]
> [ 0.114046] pci 0000:00:00.0: [1814:0801] type 01 class 0x060400
> [ 0.115059] pci 0000:00:00.0: reg 0x10: [mem 0x00000000-0x7fffffff]
> [ 0.116118] pci 0000:00:00.0: reg 0x14: [mem 0x00000000-0x0000ffff]
> [ 0.117195] pci 0000:00:00.0: supports D1
> [ 0.117862] pci 0000:00:00.0: PME# supported from D0 D1 D3hot
> [ 0.119156] pci 0000:00:00.0: bridge configuration invalid ([bus 00-00]), reconfiguring
> [ 0.120556] pci 0000:01:00.0: [14c3:7650] type 00 class 0x028000
> [ 0.121570] pci 0000:01:00.0: reg 0x10: [mem 0x00000000-0x000fffff]
> [ 0.122658] pci 0000:01:00.0: PME# supported from D0 D3hot D3cold
> [ 0.123749] pci 0000:01:00.1: [14c3:8650] type 00 class 0x0d1100
> [ 0.124769] pci 0000:01:00.1: reg 0x10: [mem 0x00000000-0x000fffff]
> [ 0.125844] pci 0000:01:00.1: supports D1
> [ 0.126513] pci 0000:01:00.1: PME# supported from D0 D1 D3hot D3cold
> [ 0.127897] pci_bus 0000:01: busn_res: [bus 01-ff] end is updated to 01
> [ 0.129018] pci_bus 0000:00: busn_res: [bus 00-ff] end is updated to 01
> [ 0.130138] pci 0000:00:00.0: BAR 0: no space for [mem size 0x80000000]
> [ 0.131255] pci 0000:00:00.0: BAR 0: failed to assign [mem size 0x80000000]
> [ 0.132434] pci 0000:00:00.0: BAR 8: assigned [mem 0x20000000-0x201fffff]
> [ 0.133587] pci 0000:00:00.0: BAR 1: assigned [mem 0x20200000-0x2020ffff]
> [ 0.134738] pci 0000:01:00.0: BAR 0: assigned [mem 0x20000000-0x200fffff]
> [ 0.135890] pci 0000:01:00.1: BAR 0: assigned [mem 0x20100000-0x201fffff]
> [ 0.137040] pci 0000:00:00.0: PCI bridge to [bus 01]
> [ 0.137882] pci 0000:00:00.0: bridge window [mem 0x20000000-0x201fffff]
> [ 0.139123] clocksource: Switched to clocksource MIPS
> [ 0.140241] NET: Registered PF_INET protocol family
> [ 0.141106] IP idents hash table entries: 2048 (order: 2, 16384 bytes, linear)
> [ 0.142473] tcp_listen_portaddr_hash hash table entries: 512 (order: 0, 4096 bytes, linear)
> [ 0.143893] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
> [ 0.145199] TCP established hash table entries: 1024 (order: 0, 4096 bytes, linear)
> [ 0.146499] TCP bind hash table entries: 1024 (order: 0, 4096 bytes, linear)
> [ 0.147695] TCP: Hash tables configured (established 1024 bind 1024)
> [ 0.148803] UDP hash table entries: 256 (order: 0, 4096 bytes, linear)
> [ 0.149920] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes, linear)
> [ 0.151177] NET: Registered PF_UNIX/PF_LOCAL protocol family
> [ 0.152149] PCI: CLS 0 bytes, default 32
> [ 0.152847] rt-timer 10000100.timer: failed get clock rate
> [ 0.153771] rt-timer: probe of 10000100.timer failed with error -2
> [ 0.155602] workingset: timestamp_bits=14 max_order=15 bucket_order=1
> [ 0.157808] squashfs: version 4.0 (2009/01/31) Phillip Lougher
> [ 0.158792] jffs2: version 2.2 (NAND) (SUMMARY) (LZMA) (RTIME) (CMODE_PRIORITY) (c) 2001-2006 Red Hat, Inc.
> [ 0.161032] Serial: 8250/16550 driver, 2 ports, IRQ sharing disabled
> [ 0.162284] of_serial 10000c00.uartlite: failed to get clock: -2
> [ 0.163300] of_serial: probe of 10000c00.uartlite failed with error -2
> [ 0.164624] spi-rt2880 10000b00.spi: unable to get SYS clock
> [ 0.165580] spi-rt2880: probe of 10000b00.spi failed with error -2
> [ 0.171098] gsw: setting port4 to ephy mode
> [ 0.171828] mtk_soc_eth 10100000.ethernet: generated random MAC address f6:6c:93:9a:c8:ca
> [ 0.173208] mtk_soc_eth 10100000.ethernet: mdio-bus disabled
> [ 0.174205] mtk_soc_eth 10100000.ethernet: loaded mt7620 driver
> [ 0.175329] mtk_soc_eth 10100000.ethernet eth0: mediatek frame engine at 0xb0100000, irq 5
> [ 0.176805] rt2880_wdt: probe of 10000120.watchdog failed with error -2
> [ 0.178187] NET: Registered PF_INET6 protocol family
> [ 0.179980] Segment Routing with IPv6
> [ 0.180607] In-situ OAM (IOAM) with IPv6
> [ 0.181290] NET: Registered PF_PACKET protocol family
> [ 0.182148] 8021q: 802.1Q VLAN Support v1.8
> [ 0.183347] Warning: unable to open an initial console.
> [ 0.184558] /dev/root: Can't open blockdev
> [ 0.185253] VFS: Cannot open root device "(null)" or unknown-block(0,0): error -6
> [ 0.186516] Please append a correct "root=" boot option; here are the available partitions:
> [ 0.187934] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
> [ 0.189335] Rebooting in 1 seconds..
>
>
> Thanks,
> Shiji Yang
Best regards,
Sergio Paracuellos
@@ -9,3 +9,10 @@ config CLK_MT7621
select MFD_SYSCON
help
This driver supports MediaTek MT7621 basic clocks.
+
+config CLK_MTMIPS
+ bool "Clock driver for MTMIPS SoCs"
+ depends on SOC_RT305X || SOC_RT288X || SOC_RT3883 || SOC_MT7620 || COMPILE_TEST
+ select MFD_SYSCON
+ help
+ This driver supports MTMIPS basic clocks.
@@ -1,2 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_CLK_MT7621) += clk-mt7621.o
+obj-$(CONFIG_CLK_MTMIPS) += clk-mtmips.o
new file mode 100644
@@ -0,0 +1,1134 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MTMIPS SoCs Clock Driver
+ * Author: Sergio Paracuellos <sergio.paracuellos@gmail.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+
+/* Configuration registers */
+#define SYSC_REG_SYSTEM_CONFIG 0x10
+#define SYSC_REG_CLKCFG0 0x2c
+#define SYSC_REG_RESET_CTRL 0x34
+#define SYSC_REG_CPU_SYS_CLKCFG 0x3c
+#define SYSC_REG_CPLL_CONFIG0 0x54
+#define SYSC_REG_CPLL_CONFIG1 0x58
+
+/* RT2880 SoC */
+#define RT2880_CONFIG_CPUCLK_SHIFT 20
+#define RT2880_CONFIG_CPUCLK_MASK 0x3
+#define RT2880_CONFIG_CPUCLK_250 0x0
+#define RT2880_CONFIG_CPUCLK_266 0x1
+#define RT2880_CONFIG_CPUCLK_280 0x2
+#define RT2880_CONFIG_CPUCLK_300 0x3
+
+/* RT305X SoC */
+#define RT305X_SYSCFG_CPUCLK_SHIFT 18
+#define RT305X_SYSCFG_CPUCLK_MASK 0x1
+#define RT305X_SYSCFG_CPUCLK_LOW 0x0
+#define RT305X_SYSCFG_CPUCLK_HIGH 0x1
+
+/* RT3352 SoC */
+#define RT3352_SYSCFG0_CPUCLK_SHIFT 8
+#define RT3352_SYSCFG0_CPUCLK_MASK 0x1
+#define RT3352_SYSCFG0_CPUCLK_LOW 0x0
+#define RT3352_SYSCFG0_CPUCLK_HIGH 0x1
+
+/* RT3383 SoC */
+#define RT3883_SYSCFG0_DRAM_TYPE_DDR2 BIT(17)
+#define RT3883_SYSCFG0_CPUCLK_SHIFT 8
+#define RT3883_SYSCFG0_CPUCLK_MASK 0x3
+#define RT3883_SYSCFG0_CPUCLK_250 0x0
+#define RT3883_SYSCFG0_CPUCLK_384 0x1
+#define RT3883_SYSCFG0_CPUCLK_480 0x2
+#define RT3883_SYSCFG0_CPUCLK_500 0x3
+
+/* RT5350 SoC */
+#define RT5350_CLKCFG0_XTAL_SEL BIT(20)
+#define RT5350_SYSCFG0_CPUCLK_SHIFT 8
+#define RT5350_SYSCFG0_CPUCLK_MASK 0x3
+#define RT5350_SYSCFG0_CPUCLK_360 0x0
+#define RT5350_SYSCFG0_CPUCLK_320 0x2
+#define RT5350_SYSCFG0_CPUCLK_300 0x3
+
+/* MT7620 and MT76x8 SoCs */
+#define MT7620_XTAL_FREQ_SEL BIT(6)
+#define CPLL_CFG0_SW_CFG BIT(31)
+#define CPLL_CFG0_PLL_MULT_RATIO_SHIFT 16
+#define CPLL_CFG0_PLL_MULT_RATIO_MASK 0x7
+#define CPLL_CFG0_LC_CURFCK BIT(15)
+#define CPLL_CFG0_BYPASS_REF_CLK BIT(14)
+#define CPLL_CFG0_PLL_DIV_RATIO_SHIFT 10
+#define CPLL_CFG0_PLL_DIV_RATIO_MASK 0x3
+#define CPLL_CFG1_CPU_AUX1 BIT(25)
+#define CPLL_CFG1_CPU_AUX0 BIT(24)
+#define CLKCFG0_PERI_CLK_SEL BIT(4)
+#define CPU_SYS_CLKCFG_OCP_RATIO_SHIFT 16
+#define CPU_SYS_CLKCFG_OCP_RATIO_MASK 0xf
+#define CPU_SYS_CLKCFG_OCP_RATIO_1 0 /* 1:1 (Reserved) */
+#define CPU_SYS_CLKCFG_OCP_RATIO_1_5 1 /* 1:1.5 (Reserved) */
+#define CPU_SYS_CLKCFG_OCP_RATIO_2 2 /* 1:2 */
+#define CPU_SYS_CLKCFG_OCP_RATIO_2_5 3 /* 1:2.5 (Reserved) */
+#define CPU_SYS_CLKCFG_OCP_RATIO_3 4 /* 1:3 */
+#define CPU_SYS_CLKCFG_OCP_RATIO_3_5 5 /* 1:3.5 (Reserved) */
+#define CPU_SYS_CLKCFG_OCP_RATIO_4 6 /* 1:4 */
+#define CPU_SYS_CLKCFG_OCP_RATIO_5 7 /* 1:5 */
+#define CPU_SYS_CLKCFG_OCP_RATIO_10 8 /* 1:10 */
+#define CPU_SYS_CLKCFG_CPU_FDIV_SHIFT 8
+#define CPU_SYS_CLKCFG_CPU_FDIV_MASK 0x1f
+#define CPU_SYS_CLKCFG_CPU_FFRAC_SHIFT 0
+#define CPU_SYS_CLKCFG_CPU_FFRAC_MASK 0x1f
+
+/* clock scaling */
+#define CLKCFG_FDIV_MASK 0x1f00
+#define CLKCFG_FDIV_USB_VAL 0x0300
+#define CLKCFG_FFRAC_MASK 0x001f
+#define CLKCFG_FFRAC_USB_VAL 0x0003
+
+struct mtmips_clk;
+struct mtmips_clk_fixed;
+struct mtmips_clk_factor;
+
+struct mtmips_clk_data {
+ struct mtmips_clk *clk_base;
+ size_t num_clk_base;
+ struct mtmips_clk_fixed *clk_fixed;
+ size_t num_clk_fixed;
+ struct mtmips_clk_factor *clk_factor;
+ size_t num_clk_factor;
+ struct mtmips_clk *clk_periph;
+ size_t num_clk_periph;
+};
+
+struct mtmips_clk_priv {
+ struct regmap *sysc;
+ const struct mtmips_clk_data *data;
+};
+
+struct mtmips_clk {
+ struct clk_hw hw;
+ struct mtmips_clk_priv *priv;
+};
+
+struct mtmips_clk_fixed {
+ const char *name;
+ const char *parent;
+ unsigned long rate;
+ struct clk_hw *hw;
+};
+
+struct mtmips_clk_factor {
+ const char *name;
+ const char *parent;
+ int mult;
+ int div;
+ unsigned long flags;
+ struct clk_hw *hw;
+};
+
+static unsigned long mtmips_pherip_clk_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return parent_rate;
+}
+
+static const struct clk_ops mtmips_periph_clk_ops = {
+ .recalc_rate = mtmips_pherip_clk_rate,
+};
+
+#define CLK_PERIPH(_name, _parent) { \
+ .init = &(const struct clk_init_data) { \
+ .name = _name, \
+ .ops = &mtmips_periph_clk_ops, \
+ .parent_data = &(const struct clk_parent_data) {\
+ .name = _parent, \
+ .fw_name = _parent \
+ }, \
+ .num_parents = 1, \
+ /* \
+ * There are drivers for these SoCs that are \
+ * older than clock driver and are not prepared \
+ * for the clock. We don't want the kernel to \
+ * disable anything so we add CLK_IS_CRITICAL \
+ * flag here. \
+ */ \
+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL \
+ }, \
+}
+
+static struct mtmips_clk rt2880_pherip_clks[] = {
+ { CLK_PERIPH("300100.timer", "bus") },
+ { CLK_PERIPH("300120.watchdog", "bus") },
+ { CLK_PERIPH("300500.uart", "bus") },
+ { CLK_PERIPH("300900.i2c", "bus") },
+ { CLK_PERIPH("300c00.uartlite", "bus") },
+ { CLK_PERIPH("400000.ethernet", "bus") },
+ { CLK_PERIPH("480000.wmac", "xtal") }
+};
+
+static struct mtmips_clk rt305x_pherip_clks[] = {
+ { CLK_PERIPH("10000900.i2c", "bus") },
+ { CLK_PERIPH("10000a00.i2s", "bus") },
+ { CLK_PERIPH("10000b00.spi", "bus") },
+ { CLK_PERIPH("10000b40.spi", "bus") },
+ { CLK_PERIPH("10000100.timer", "bus") },
+ { CLK_PERIPH("10000120.watchdog", "bus") },
+ { CLK_PERIPH("10000500.uart", "bus") },
+ { CLK_PERIPH("10000c00.uartlite", "bus") },
+ { CLK_PERIPH("10100000.ethernet", "bus") },
+ { CLK_PERIPH("10180000.wmac", "xtal") }
+};
+
+static struct mtmips_clk rt5350_pherip_clks[] = {
+ { CLK_PERIPH("10000900.i2c", "periph") },
+ { CLK_PERIPH("10000a00.i2s", "periph") },
+ { CLK_PERIPH("10000b00.spi", "bus") },
+ { CLK_PERIPH("10000b40.spi", "bus") },
+ { CLK_PERIPH("10000100.timer", "bus") },
+ { CLK_PERIPH("10000120.watchdog", "bus") },
+ { CLK_PERIPH("10000500.uart", "periph") },
+ { CLK_PERIPH("10000c00.uartlite", "periph") },
+ { CLK_PERIPH("10100000.ethernet", "bus") },
+ { CLK_PERIPH("10180000.wmac", "xtal") }
+};
+
+static struct mtmips_clk mt7620_pherip_clks[] = {
+ { CLK_PERIPH("10000100.timer", "periph") },
+ { CLK_PERIPH("10000120.watchdog", "periph") },
+ { CLK_PERIPH("10000900.i2c", "periph") },
+ { CLK_PERIPH("10000a00.i2s", "periph") },
+ { CLK_PERIPH("10000b00.spi", "bus") },
+ { CLK_PERIPH("10000b40.spi", "bus") },
+ { CLK_PERIPH("10000c00.uartlite", "periph") },
+ { CLK_PERIPH("10000d00.uart1", "periph") },
+ { CLK_PERIPH("10000e00.uart2", "periph") },
+ { CLK_PERIPH("10180000.wmac", "xtal") }
+};
+
+static struct mtmips_clk mt76x8_pherip_clks[] = {
+ { CLK_PERIPH("10000100.timer", "periph") },
+ { CLK_PERIPH("10000120.watchdog", "periph") },
+ { CLK_PERIPH("10000900.i2c", "periph") },
+ { CLK_PERIPH("10000a00.i2s", "pcmi2s") },
+ { CLK_PERIPH("10000b00.spi", "bus") },
+ { CLK_PERIPH("10000b40.spi", "bus") },
+ { CLK_PERIPH("10000c00.uartlite", "periph") },
+ { CLK_PERIPH("10000d00.uartlite", "periph") },
+ { CLK_PERIPH("10000e00.uartlite", "periph") },
+ { CLK_PERIPH("10000d00.uart1", "periph") },
+ { CLK_PERIPH("10000e00.uart2", "periph") },
+ { CLK_PERIPH("10180000.wmac", "xtal") }
+};
+
+static int mtmips_register_pherip_clocks(struct device_node *np,
+ struct clk_hw_onecell_data *clk_data,
+ struct mtmips_clk_priv *priv)
+{
+ struct clk_hw **hws = clk_data->hws;
+ struct mtmips_clk *sclk;
+ size_t idx_start = priv->data->num_clk_base + priv->data->num_clk_fixed +
+ priv->data->num_clk_factor;
+ int ret, i;
+
+ for (i = 0; i < priv->data->num_clk_periph; i++) {
+ int idx = (idx_start - 1) + i;
+
+ sclk = &priv->data->clk_periph[i];
+ ret = of_clk_hw_register(np, &sclk->hw);
+ if (ret) {
+ pr_err("Couldn't register peripheral clock %d\n", idx);
+ goto err_clk_unreg;
+ }
+
+ hws[idx] = &sclk->hw;
+ }
+
+ return 0;
+
+err_clk_unreg:
+ while (--i >= 0) {
+ sclk = &priv->data->clk_periph[i];
+ clk_hw_unregister(&sclk->hw);
+ }
+ return ret;
+}
+
+#define CLK_FIXED(_name, _parent, _rate) \
+ { \
+ .name = _name, \
+ .parent = _parent, \
+ .rate = _rate \
+ }
+
+static struct mtmips_clk_fixed rt305x_fixed_clocks[] = {
+ CLK_FIXED("xtal", NULL, 40000000)
+};
+
+static struct mtmips_clk_fixed rt3352_fixed_clocks[] = {
+ CLK_FIXED("periph", "xtal", 40000000)
+};
+
+static struct mtmips_clk_fixed mt76x8_fixed_clocks[] = {
+ CLK_FIXED("pcmi2s", "xtal", 480000000),
+ CLK_FIXED("periph", "xtal", 40000000)
+};
+
+static int mtmips_register_fixed_clocks(struct clk_hw_onecell_data *clk_data,
+ struct mtmips_clk_priv *priv)
+{
+ struct clk_hw **hws = clk_data->hws;
+ struct mtmips_clk_fixed *sclk;
+ size_t idx_start = priv->data->num_clk_base;
+ int ret, i;
+
+ for (i = 0; i < priv->data->num_clk_fixed; i++) {
+ int idx = (idx_start - 1) + i;
+
+ sclk = &priv->data->clk_fixed[i];
+ sclk->hw = clk_hw_register_fixed_rate(NULL, sclk->name,
+ sclk->parent, 0,
+ sclk->rate);
+ if (IS_ERR(sclk->hw)) {
+ pr_err("Couldn't register fixed clock %d\n", idx);
+ goto err_clk_unreg;
+ }
+
+ hws[idx] = sclk->hw;
+ }
+
+ return 0;
+
+err_clk_unreg:
+ while (--i >= 0) {
+ sclk = &priv->data->clk_fixed[i];
+ clk_hw_unregister_fixed_rate(sclk->hw);
+ }
+ return ret;
+}
+
+#define CLK_FACTOR(_name, _parent, _mult, _div) \
+ { \
+ .name = _name, \
+ .parent = _parent, \
+ .mult = _mult, \
+ .div = _div, \
+ .flags = CLK_SET_RATE_PARENT \
+ }
+
+static struct mtmips_clk_factor rt2880_factor_clocks[] = {
+ CLK_FACTOR("bus", "cpu", 1, 2)
+};
+
+static struct mtmips_clk_factor rt305x_factor_clocks[] = {
+ CLK_FACTOR("bus", "cpu", 1, 3)
+};
+
+static int mtmips_register_factor_clocks(struct clk_hw_onecell_data *clk_data,
+ struct mtmips_clk_priv *priv)
+{
+ struct clk_hw **hws = clk_data->hws;
+ struct mtmips_clk_factor *sclk;
+ size_t idx_start = priv->data->num_clk_base + priv->data->num_clk_fixed;
+ int ret, i;
+
+ for (i = 0; i < priv->data->num_clk_factor; i++) {
+ int idx = (idx_start - 1) + i;
+
+ sclk = &priv->data->clk_factor[i];
+ sclk->hw = clk_hw_register_fixed_factor(NULL, sclk->name,
+ sclk->parent, sclk->flags,
+ sclk->mult, sclk->div);
+ if (IS_ERR(sclk->hw)) {
+ pr_err("Couldn't register factor clock %d\n", idx);
+ goto err_clk_unreg;
+ }
+
+ hws[idx] = sclk->hw;
+ }
+
+ return 0;
+
+err_clk_unreg:
+ while (--i >= 0) {
+ sclk = &priv->data->clk_factor[i];
+ clk_hw_unregister_fixed_factor(sclk->hw);
+ }
+ return ret;
+}
+
+static inline struct mtmips_clk *to_mtmips_clk(struct clk_hw *hw)
+{
+ return container_of(hw, struct mtmips_clk, hw);
+}
+
+static unsigned long rt5350_xtal_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 val;
+
+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &val);
+ if (!(val & RT5350_CLKCFG0_XTAL_SEL))
+ return 20000000;
+
+ return 40000000;
+}
+
+static unsigned long rt5350_cpu_recalc_rate(struct clk_hw *hw,
+ unsigned long xtal_clk)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 t;
+
+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
+ t = (t >> RT5350_SYSCFG0_CPUCLK_SHIFT) & RT5350_SYSCFG0_CPUCLK_MASK;
+
+ switch (t) {
+ case RT5350_SYSCFG0_CPUCLK_360:
+ return 360000000;
+ case RT5350_SYSCFG0_CPUCLK_320:
+ return 320000000;
+ case RT5350_SYSCFG0_CPUCLK_300:
+ return 300000000;
+ default:
+ BUG();
+ }
+}
+
+static unsigned long rt5350_bus_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ if (parent_rate == 320000000)
+ return parent_rate / 4;
+
+ return parent_rate / 3;
+}
+
+static unsigned long rt3352_cpu_recalc_rate(struct clk_hw *hw,
+ unsigned long xtal_clk)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 t;
+
+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
+ t = (t >> RT3352_SYSCFG0_CPUCLK_SHIFT) & RT3352_SYSCFG0_CPUCLK_MASK;
+
+ switch (t) {
+ case RT3352_SYSCFG0_CPUCLK_LOW:
+ return 384000000;
+ case RT3352_SYSCFG0_CPUCLK_HIGH:
+ return 400000000;
+ default:
+ BUG();
+ }
+}
+
+static unsigned long rt305x_cpu_recalc_rate(struct clk_hw *hw,
+ unsigned long xtal_clk)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 t;
+
+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
+ t = (t >> RT305X_SYSCFG_CPUCLK_SHIFT) & RT305X_SYSCFG_CPUCLK_MASK;
+
+ switch (t) {
+ case RT305X_SYSCFG_CPUCLK_LOW:
+ return 320000000;
+ case RT305X_SYSCFG_CPUCLK_HIGH:
+ return 384000000;
+ default:
+ BUG();
+ }
+}
+
+static unsigned long rt3883_cpu_recalc_rate(struct clk_hw *hw,
+ unsigned long xtal_clk)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 t;
+
+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
+ t = (t >> RT3883_SYSCFG0_CPUCLK_SHIFT) & RT3883_SYSCFG0_CPUCLK_MASK;
+
+ switch (t) {
+ case RT3883_SYSCFG0_CPUCLK_250:
+ return 250000000;
+ case RT3883_SYSCFG0_CPUCLK_384:
+ return 384000000;
+ case RT3883_SYSCFG0_CPUCLK_480:
+ return 480000000;
+ case RT3883_SYSCFG0_CPUCLK_500:
+ return 500000000;
+ default:
+ BUG();
+ }
+}
+
+static unsigned long rt3883_bus_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 ddr2;
+ u32 t;
+
+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
+ ddr2 = t & RT3883_SYSCFG0_DRAM_TYPE_DDR2;
+
+ switch (parent_rate) {
+ case 250000000:
+ return (ddr2) ? 125000000 : 83000000;
+ case 384000000:
+ return (ddr2) ? 128000000 : 96000000;
+ case 480000000:
+ return (ddr2) ? 160000000 : 120000000;
+ case 500000000:
+ return (ddr2) ? 166000000 : 125000000;
+ default:
+ WARN_ON_ONCE(parent_rate == 0);
+ }
+}
+
+static unsigned long rt2880_cpu_recalc_rate(struct clk_hw *hw,
+ unsigned long xtal_clk)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 t;
+
+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
+ t = (t >> RT2880_CONFIG_CPUCLK_SHIFT) & RT2880_CONFIG_CPUCLK_MASK;
+
+ switch (t) {
+ case RT2880_CONFIG_CPUCLK_250:
+ return 250000000;
+ case RT2880_CONFIG_CPUCLK_266:
+ return 266000000;
+ case RT2880_CONFIG_CPUCLK_280:
+ return 280000000;
+ case RT2880_CONFIG_CPUCLK_300:
+ return 300000000;
+ default:
+ BUG();
+ }
+}
+
+static u32 mt7620_calc_rate(u32 ref_rate, u32 mul, u32 div)
+{
+ u64 t;
+
+ t = ref_rate;
+ t *= mul;
+ div_u64(t, div);
+
+ return t;
+}
+
+static unsigned long mt7620_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ static const u32 clk_divider[] = { 2, 3, 4, 8 };
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ unsigned long cpu_pll;
+ u32 t;
+ u32 mul;
+ u32 div;
+
+ regmap_read(sysc, SYSC_REG_CPLL_CONFIG0, &t);
+ if (t & CPLL_CFG0_BYPASS_REF_CLK) {
+ cpu_pll = parent_rate;
+ } else if ((t & CPLL_CFG0_SW_CFG) == 0) {
+ cpu_pll = 600000000;
+ } else {
+ mul = (t >> CPLL_CFG0_PLL_MULT_RATIO_SHIFT) &
+ CPLL_CFG0_PLL_MULT_RATIO_MASK;
+ mul += 24;
+ if (t & CPLL_CFG0_LC_CURFCK)
+ mul *= 2;
+
+ div = (t >> CPLL_CFG0_PLL_DIV_RATIO_SHIFT) &
+ CPLL_CFG0_PLL_DIV_RATIO_MASK;
+
+ WARN_ON_ONCE(div >= ARRAY_SIZE(clk_divider));
+
+ cpu_pll = mt7620_calc_rate(parent_rate, mul, clk_divider[div]);
+ }
+
+ regmap_read(sysc, SYSC_REG_CPLL_CONFIG1, &t);
+ if (t & CPLL_CFG1_CPU_AUX1)
+ return parent_rate;
+
+ if (t & CPLL_CFG1_CPU_AUX0)
+ return 480000000;
+
+ return cpu_pll;
+}
+
+static unsigned long mt7620_cpu_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 t;
+ u32 mul;
+ u32 div;
+
+ regmap_read(sysc, SYSC_REG_CPU_SYS_CLKCFG, &t);
+ mul = t & CPU_SYS_CLKCFG_CPU_FFRAC_MASK;
+ div = (t >> CPU_SYS_CLKCFG_CPU_FDIV_SHIFT) &
+ CPU_SYS_CLKCFG_CPU_FDIV_MASK;
+
+ return mt7620_calc_rate(parent_rate, mul, div);
+}
+
+static unsigned long mt7620_bus_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ static const u32 ocp_dividers[16] = {
+ [CPU_SYS_CLKCFG_OCP_RATIO_2] = 2,
+ [CPU_SYS_CLKCFG_OCP_RATIO_3] = 3,
+ [CPU_SYS_CLKCFG_OCP_RATIO_4] = 4,
+ [CPU_SYS_CLKCFG_OCP_RATIO_5] = 5,
+ [CPU_SYS_CLKCFG_OCP_RATIO_10] = 10,
+ };
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 t;
+ u32 ocp_ratio;
+ u32 div;
+
+ regmap_read(sysc, SYSC_REG_CPU_SYS_CLKCFG, &t);
+ ocp_ratio = (t >> CPU_SYS_CLKCFG_OCP_RATIO_SHIFT) &
+ CPU_SYS_CLKCFG_OCP_RATIO_MASK;
+
+ if (WARN_ON_ONCE(ocp_ratio >= ARRAY_SIZE(ocp_dividers)))
+ return parent_rate;
+
+ div = ocp_dividers[ocp_ratio];
+
+ if (WARN(!div, "invalid divider for OCP ratio %u", ocp_ratio))
+ return parent_rate;
+
+ return parent_rate / div;
+}
+
+static unsigned long mt7620_periph_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 t;
+
+ regmap_read(sysc, SYSC_REG_CLKCFG0, &t);
+ if (t & CLKCFG0_PERI_CLK_SEL)
+ return parent_rate;
+
+ return 40000000;
+}
+
+static unsigned long mt76x8_xtal_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct mtmips_clk *clk = to_mtmips_clk(hw);
+ struct regmap *sysc = clk->priv->sysc;
+ u32 t;
+
+ regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t);
+ if (t & MT7620_XTAL_FREQ_SEL)
+ return 40000000;
+
+ return 20000000;
+}
+
+static unsigned long mt76x8_cpu_recalc_rate(struct clk_hw *hw,
+ unsigned long xtal_clk)
+{
+ if (xtal_clk == 40000000)
+ return 580000000;
+
+ return 575000000;
+}
+
+#define CLK_BASE(_name, _parent, _recalc) { \
+ .init = &(const struct clk_init_data) { \
+ .name = _name, \
+ .ops = &(const struct clk_ops) { \
+ .recalc_rate = _recalc, \
+ }, \
+ .parent_data = &(const struct clk_parent_data) { \
+ .name = _parent, \
+ .fw_name = _parent \
+ }, \
+ .num_parents = _parent ? 1 : 0 \
+ }, \
+}
+
+static struct mtmips_clk rt2880_clks_base[] = {
+ { CLK_BASE("cpu", "xtal", rt2880_cpu_recalc_rate) }
+};
+
+static struct mtmips_clk rt305x_clks_base[] = {
+ { CLK_BASE("cpu", "xtal", rt305x_cpu_recalc_rate) }
+};
+
+static struct mtmips_clk rt3352_clks_base[] = {
+ { CLK_BASE("xtal", NULL, rt5350_xtal_recalc_rate) },
+ { CLK_BASE("cpu", "xtal", rt3352_cpu_recalc_rate) }
+};
+
+static struct mtmips_clk rt3883_clks_base[] = {
+ { CLK_BASE("cpu", "xtal", rt3883_cpu_recalc_rate) },
+ { CLK_BASE("bus", "cpu", rt3883_bus_recalc_rate) }
+};
+
+static struct mtmips_clk rt5350_clks_base[] = {
+ { CLK_BASE("xtal", NULL, rt5350_xtal_recalc_rate) },
+ { CLK_BASE("cpu", "xtal", rt5350_cpu_recalc_rate) },
+ { CLK_BASE("bus", "cpu", rt5350_bus_recalc_rate) }
+};
+
+static struct mtmips_clk mt7620_clks_base[] = {
+ { CLK_BASE("xtal", NULL, mt76x8_xtal_recalc_rate) },
+ { CLK_BASE("pll", "xtal", mt7620_pll_recalc_rate) },
+ { CLK_BASE("cpu", "pll", mt7620_cpu_recalc_rate) },
+ { CLK_BASE("periph", "xtal", mt7620_periph_recalc_rate) },
+ { CLK_BASE("bus", "cpu", mt7620_bus_recalc_rate) }
+};
+
+static struct mtmips_clk mt76x8_clks_base[] = {
+ { CLK_BASE("xtal", NULL, mt76x8_xtal_recalc_rate) },
+ { CLK_BASE("cpu", "xtal", mt76x8_cpu_recalc_rate) }
+};
+
+static int mtmips_register_clocks(struct device_node *np,
+ struct clk_hw_onecell_data *clk_data,
+ struct mtmips_clk_priv *priv)
+{
+ struct clk_hw **hws = clk_data->hws;
+ struct mtmips_clk *sclk;
+ int ret, i;
+
+ for (i = 0; i < priv->data->num_clk_base; i++) {
+ sclk = &priv->data->clk_base[i];
+ sclk->priv = priv;
+ ret = of_clk_hw_register(np, &sclk->hw);
+ if (ret) {
+ pr_err("Couldn't register top clock %i\n", i);
+ goto err_clk_unreg;
+ }
+
+ hws[i] = &sclk->hw;
+ }
+
+ return 0;
+
+err_clk_unreg:
+ while (--i >= 0) {
+ sclk = &priv->data->clk_base[i];
+ clk_hw_unregister(&sclk->hw);
+ }
+ return ret;
+}
+
+static const struct mtmips_clk_data rt2880_clk_data = {
+ .clk_base = rt2880_clks_base,
+ .num_clk_base = ARRAY_SIZE(rt2880_clks_base),
+ .clk_fixed = rt305x_fixed_clocks,
+ .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks),
+ .clk_factor = rt2880_factor_clocks,
+ .num_clk_factor = ARRAY_SIZE(rt2880_factor_clocks),
+ .clk_periph = rt2880_pherip_clks,
+ .num_clk_periph = ARRAY_SIZE(rt2880_pherip_clks),
+};
+
+static const struct mtmips_clk_data rt3050_clk_data = {
+ .clk_base = rt305x_clks_base,
+ .num_clk_base = ARRAY_SIZE(rt305x_clks_base),
+ .clk_fixed = rt305x_fixed_clocks,
+ .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks),
+ .clk_factor = rt305x_factor_clocks,
+ .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks),
+ .clk_periph = rt305x_pherip_clks,
+ .num_clk_periph = ARRAY_SIZE(rt305x_pherip_clks),
+};
+
+static const struct mtmips_clk_data rt3052_clk_data = {
+ .clk_base = rt305x_clks_base,
+ .num_clk_base = ARRAY_SIZE(rt305x_clks_base),
+ .clk_fixed = rt305x_fixed_clocks,
+ .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks),
+ .clk_factor = rt305x_factor_clocks,
+ .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks),
+ .clk_periph = rt305x_pherip_clks,
+ .num_clk_periph = ARRAY_SIZE(rt305x_pherip_clks),
+};
+
+static const struct mtmips_clk_data rt3352_clk_data = {
+ .clk_base = rt3352_clks_base,
+ .num_clk_base = ARRAY_SIZE(rt3352_clks_base),
+ .clk_fixed = rt3352_fixed_clocks,
+ .num_clk_fixed = ARRAY_SIZE(rt3352_fixed_clocks),
+ .clk_factor = rt305x_factor_clocks,
+ .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks),
+ .clk_periph = rt5350_pherip_clks,
+ .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks),
+};
+
+static const struct mtmips_clk_data rt3883_clk_data = {
+ .clk_base = rt3883_clks_base,
+ .num_clk_base = ARRAY_SIZE(rt3883_clks_base),
+ .clk_fixed = rt305x_fixed_clocks,
+ .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks),
+ .clk_factor = NULL,
+ .num_clk_factor = 0,
+ .clk_periph = rt5350_pherip_clks,
+ .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks),
+};
+
+static const struct mtmips_clk_data rt5350_clk_data = {
+ .clk_base = rt5350_clks_base,
+ .num_clk_base = ARRAY_SIZE(rt5350_clks_base),
+ .clk_fixed = rt3352_fixed_clocks,
+ .num_clk_fixed = ARRAY_SIZE(rt3352_fixed_clocks),
+ .clk_factor = NULL,
+ .num_clk_factor = 0,
+ .clk_periph = rt5350_pherip_clks,
+ .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks),
+};
+
+static const struct mtmips_clk_data mt7620_clk_data = {
+ .clk_base = mt7620_clks_base,
+ .num_clk_base = ARRAY_SIZE(mt7620_clks_base),
+ .clk_fixed = NULL,
+ .num_clk_fixed = 0,
+ .clk_factor = NULL,
+ .num_clk_factor = 0,
+ .clk_periph = mt7620_pherip_clks,
+ .num_clk_periph = ARRAY_SIZE(mt7620_pherip_clks),
+};
+
+static const struct mtmips_clk_data mt76x8_clk_data = {
+ .clk_base = mt76x8_clks_base,
+ .num_clk_base = ARRAY_SIZE(mt76x8_clks_base),
+ .clk_fixed = mt76x8_fixed_clocks,
+ .num_clk_fixed = ARRAY_SIZE(mt76x8_fixed_clocks),
+ .clk_factor = rt305x_factor_clocks,
+ .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks),
+ .clk_periph = mt76x8_pherip_clks,
+ .num_clk_periph = ARRAY_SIZE(mt76x8_pherip_clks),
+};
+
+static const struct of_device_id mtmips_of_match[] = {
+ {
+ .compatible = "ralink,rt2880-sysc",
+ .data = &rt2880_clk_data,
+ },
+ {
+ .compatible = "ralink,rt3050-sysc",
+ .data = &rt3050_clk_data,
+ },
+ {
+ .compatible = "ralink,rt3052-sysc",
+ .data = &rt3052_clk_data,
+ },
+ {
+ .compatible = "ralink,rt3352-sysc",
+ .data = &rt3352_clk_data,
+ },
+ {
+ .compatible = "ralink,rt3883-sysc",
+ .data = &rt3883_clk_data,
+ },
+ {
+ .compatible = "ralink,rt5350-sysc",
+ .data = &rt5350_clk_data,
+ },
+ {
+ .compatible = "ralink,mt7620a-sysc",
+ .data = &mt7620_clk_data,
+ },
+ {
+ .compatible = "ralink,mt7620-sysc",
+ .data = &mt7620_clk_data,
+ },
+ {
+ .compatible = "ralink,mt7628-sysc",
+ .data = &mt76x8_clk_data,
+ },
+ {
+ .compatible = "ralink,mt7688-sysc",
+ .data = &mt76x8_clk_data,
+ },
+ {}
+};
+
+static void __init mtmips_clk_regs_init(struct device_node *node,
+ struct mtmips_clk_priv *priv)
+{
+ u32 t;
+
+ if (!of_device_is_compatible(node, "ralink,mt7620-sysc"))
+ return;
+
+ /*
+ * When the CPU goes into sleep mode, the BUS
+ * clock will be too low for USB to function properly.
+ * Adjust the busses fractional divider to fix this
+ */
+ regmap_read(priv->sysc, SYSC_REG_CPU_SYS_CLKCFG, &t);
+ t &= ~(CLKCFG_FDIV_MASK | CLKCFG_FFRAC_MASK);
+ t |= CLKCFG_FDIV_USB_VAL | CLKCFG_FFRAC_USB_VAL;
+ regmap_write(priv->sysc, SYSC_REG_CPU_SYS_CLKCFG, t);
+}
+
+static void __init mtmips_clk_init(struct device_node *node)
+{
+ const struct of_device_id *match;
+ const struct mtmips_clk_data *data;
+ struct mtmips_clk_priv *priv;
+ struct clk_hw_onecell_data *clk_data;
+ int ret, i, count;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return;
+
+ priv->sysc = syscon_node_to_regmap(node);
+ if (IS_ERR(priv->sysc)) {
+ pr_err("Could not get sysc syscon regmap\n");
+ goto free_clk_priv;
+ }
+
+ mtmips_clk_regs_init(node, priv);
+
+ match = of_match_node(mtmips_of_match, node);
+ if (WARN_ON(!match))
+ return;
+
+ data = match->data;
+ priv->data = data;
+ count = priv->data->num_clk_base + priv->data->num_clk_fixed +
+ priv->data->num_clk_factor + priv->data->num_clk_periph;
+ clk_data = kzalloc(struct_size(clk_data, hws, count), GFP_KERNEL);
+ if (!clk_data)
+ goto free_clk_priv;
+
+ ret = mtmips_register_clocks(node, clk_data, priv);
+ if (ret) {
+ pr_err("Couldn't register top clocks\n");
+ goto free_clk_data;
+ }
+
+ ret = mtmips_register_fixed_clocks(clk_data, priv);
+ if (ret) {
+ pr_err("Couldn't register fixed clocks\n");
+ goto unreg_clk_top;
+ }
+
+ ret = mtmips_register_factor_clocks(clk_data, priv);
+ if (ret) {
+ pr_err("Couldn't register factor clocks\n");
+ goto unreg_clk_fixed;
+ }
+
+ ret = mtmips_register_pherip_clocks(node, clk_data, priv);
+ if (ret) {
+ pr_err("Couldn't register peripheral clocks\n");
+ goto unreg_clk_factor;
+ }
+
+ clk_data->num = count;
+
+ ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+ if (ret) {
+ pr_err("Couldn't add clk hw provider\n");
+ goto unreg_clk_periph;
+ }
+
+ return;
+
+unreg_clk_periph:
+ for (i = 0; i < priv->data->num_clk_periph; i++) {
+ struct mtmips_clk *sclk = &priv->data->clk_periph[i];
+
+ clk_hw_unregister(&sclk->hw);
+ }
+
+unreg_clk_factor:
+ for (i = 0; i < priv->data->num_clk_factor; i++) {
+ struct mtmips_clk_factor *sclk = &priv->data->clk_factor[i];
+
+ clk_hw_unregister_fixed_factor(sclk->hw);
+ }
+
+unreg_clk_fixed:
+ for (i = 0; i < priv->data->num_clk_fixed; i++) {
+ struct mtmips_clk_fixed *sclk = &priv->data->clk_fixed[i];
+
+ clk_hw_unregister_fixed_rate(sclk->hw);
+ }
+
+unreg_clk_top:
+ for (i = 0; i < priv->data->num_clk_base; i++) {
+ struct mtmips_clk *sclk = &priv->data->clk_base[i];
+
+ clk_hw_unregister(&sclk->hw);
+ }
+
+free_clk_data:
+ kfree(clk_data);
+
+free_clk_priv:
+ kfree(priv);
+}
+CLK_OF_DECLARE_DRIVER(rt2880_clk, "ralink,rt2880-sysc", mtmips_clk_init);
+CLK_OF_DECLARE_DRIVER(rt3050_clk, "ralink,rt3050-sysc", mtmips_clk_init);
+CLK_OF_DECLARE_DRIVER(rt3052_clk, "ralink,rt3052-sysc", mtmips_clk_init);
+CLK_OF_DECLARE_DRIVER(rt3352_clk, "ralink,rt3352-sysc", mtmips_clk_init);
+CLK_OF_DECLARE_DRIVER(rt3883_clk, "ralink,rt3883-sysc", mtmips_clk_init);
+CLK_OF_DECLARE_DRIVER(rt5350_clk, "ralink,rt5350-sysc", mtmips_clk_init);
+CLK_OF_DECLARE_DRIVER(mt7620a_clk, "ralink,mt7620a-sysc", mtmips_clk_init);
+CLK_OF_DECLARE_DRIVER(mt7620_clk, "ralink,mt7620-sysc", mtmips_clk_init);
+CLK_OF_DECLARE_DRIVER(mt7628_clk, "ralink,mt7628-sysc", mtmips_clk_init);
+CLK_OF_DECLARE_DRIVER(mt7688_clk, "ralink,mt7688-sysc", mtmips_clk_init);
+
+struct mtmips_rst {
+ struct reset_controller_dev rcdev;
+ struct regmap *sysc;
+};
+
+static struct mtmips_rst *to_mtmips_rst(struct reset_controller_dev *dev)
+{
+ return container_of(dev, struct mtmips_rst, rcdev);
+}
+
+static int mtmips_assert_device(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct mtmips_rst *data = to_mtmips_rst(rcdev);
+ struct regmap *sysc = data->sysc;
+
+ return regmap_update_bits(sysc, SYSC_REG_RESET_CTRL, BIT(id), BIT(id));
+}
+
+static int mtmips_deassert_device(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct mtmips_rst *data = to_mtmips_rst(rcdev);
+ struct regmap *sysc = data->sysc;
+
+ return regmap_update_bits(sysc, SYSC_REG_RESET_CTRL, BIT(id), 0);
+}
+
+static int mtmips_reset_device(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ int ret;
+
+ ret = mtmips_assert_device(rcdev, id);
+ if (ret < 0)
+ return ret;
+
+ return mtmips_deassert_device(rcdev, id);
+}
+
+static int mtmips_rst_xlate(struct reset_controller_dev *rcdev,
+ const struct of_phandle_args *reset_spec)
+{
+ unsigned long id = reset_spec->args[0];
+
+ if (id == 0 || id >= rcdev->nr_resets)
+ return -EINVAL;
+
+ return id;
+}
+
+static const struct reset_control_ops reset_ops = {
+ .reset = mtmips_reset_device,
+ .assert = mtmips_assert_device,
+ .deassert = mtmips_deassert_device
+};
+
+static int mtmips_reset_init(struct device *dev, struct regmap *sysc)
+{
+ struct mtmips_rst *rst_data;
+
+ rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL);
+ if (!rst_data)
+ return -ENOMEM;
+
+ rst_data->sysc = sysc;
+ rst_data->rcdev.ops = &reset_ops;
+ rst_data->rcdev.owner = THIS_MODULE;
+ rst_data->rcdev.nr_resets = 32;
+ rst_data->rcdev.of_reset_n_cells = 1;
+ rst_data->rcdev.of_xlate = mtmips_rst_xlate;
+ rst_data->rcdev.of_node = dev_of_node(dev);
+
+ return devm_reset_controller_register(dev, &rst_data->rcdev);
+}
+
+static int mtmips_clk_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
+ struct mtmips_clk_priv *priv;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->sysc = syscon_node_to_regmap(np);
+ if (IS_ERR(priv->sysc))
+ return dev_err_probe(dev, PTR_ERR(priv->sysc),
+ "Could not get sysc syscon regmap\n");
+
+ ret = mtmips_reset_init(dev, priv->sysc);
+ if (ret)
+ return dev_err_probe(dev, ret, "Could not init reset controller\n");
+
+ return 0;
+}
+
+static const struct of_device_id mtmips_clk_of_match[] = {
+ { .compatible = "ralink,rt2880-reset" },
+ { .compatible = "ralink,rt2880-sysc" },
+ { .compatible = "ralink,rt3050-sysc" },
+ { .compatible = "ralink,rt3050-sysc" },
+ { .compatible = "ralink,rt3352-sysc" },
+ { .compatible = "ralink,rt3883-sysc" },
+ { .compatible = "ralink,rt5350-sysc" },
+ { .compatible = "ralink,mt7620a-sysc" },
+ { .compatible = "ralink,mt7620-sysc" },
+ { .compatible = "ralink,mt7628-sysc" },
+ { .compatible = "ralink,mt7688-sysc" },
+ {}
+};
+
+static struct platform_driver mtmips_clk_driver = {
+ .probe = mtmips_clk_probe,
+ .driver = {
+ .name = "mtmips-clk",
+ .of_match_table = mtmips_clk_of_match,
+ },
+};
+
+static int __init mtmips_clk_reset_init(void)
+{
+ return platform_driver_register(&mtmips_clk_driver);
+}
+arch_initcall(mtmips_clk_reset_init);