Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * cpu-sa1100.c: clock scaling for the SA1100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2000 2001, The Delft University of Technology
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * - Johan Pouwelse (J.A.Pouwelse@its.tudelft.nl): initial version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * - Erik Mouw (J.A.K.Mouw@its.tudelft.nl):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *   - major rewrite for linux-2.3.99
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *   - rewritten for the more generic power management scheme in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  *     linux-2.4.5-rmk1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * This software has been developed while working on the LART
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  * computing board (http://www.lartmaker.nl/), which is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  * sponsored by the Mobile Multi-media Communications
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * (http://www.mobimedia.org/) and Ubiquitous Communications
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * (http://www.ubicom.tudelft.nl/) projects.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * The authors can be reached at:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  *  Erik Mouw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  *  Information and Communication Theory Group
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  *  Faculty of Information Technology and Systems
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  *  Delft University of Technology
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  *  P.O. Box 5031
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  *  2600 GA Delft
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  *  The Netherlands
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  * Theory of operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  * ====================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  * Clock scaling can be used to lower the power consumption of the CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  * core. This will give you a somewhat longer running time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)  * The SA-1100 has a single register to change the core clock speed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)  *   PPCR      0x90020014    PLL config
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)  * However, the DRAM timings are closely related to the core clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  * speed, so we need to change these, too. The used registers are:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  *   MDCNFG    0xA0000000    DRAM config
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  *   MDCAS0    0xA0000004    Access waveform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)  *   MDCAS1    0xA0000008    Access waveform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)  *   MDCAS2    0xA000000C    Access waveform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  * Care must be taken to change the DRAM parameters the correct way,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  * because otherwise the DRAM becomes unusable and the kernel will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  * crash.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  * The simple solution to avoid a kernel crash is to put the actual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  * clock change in ROM and jump to that code from the kernel. The main
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * disadvantage is that the ROM has to be modified, which is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * possible on all SA-1100 platforms. Another disadvantage is that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * jumping to ROM makes clock switching unnecessary complicated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  * The idea behind this driver is that the memory configuration can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  * changed while running from DRAM (even with interrupts turned on!)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  * as long as all re-configuration steps yield a valid DRAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  * configuration. The advantages are clear: it will run on all SA-1100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  * platforms, and the code is very simple.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  * If you really want to understand what is going on in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  * sa1100_update_dram_timings(), you'll have to read sections 8.2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  * 9.5.7.3, and 10.2 from the "Intel StrongARM SA-1100 Microprocessor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  * Developers Manual" (available for free from Intel).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) #include <linux/cpufreq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) #include <asm/cputype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) #include <mach/generic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) #include <mach/hardware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) struct sa1100_dram_regs {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	int speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	u32 mdcnfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	u32 mdcas0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	u32 mdcas1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	u32 mdcas2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) static struct cpufreq_driver sa1100_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) static struct sa1100_dram_regs sa1100_dram_settings[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	/*speed,     mdcnfg,     mdcas0,     mdcas1,     mdcas2,   clock freq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	{ 59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/*  59.0 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	{ 73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/*  73.7 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	{ 88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/*  88.5 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	{103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 103.2 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	{118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff},/* 118.0 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	{132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff},/* 132.7 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	{147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff},/* 147.5 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	{162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff},/* 162.2 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	{176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff},/* 176.9 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	{191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff},/* 191.7 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	{206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 206.4 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	{221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 221.2 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	{235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1},/* 235.9 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	{250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 250.7 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	{265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 265.4 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	{280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87},/* 280.2 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	{ 0, 0, 0, 0, 0 } /* last entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static void sa1100_update_dram_timings(int current_speed, int new_speed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	struct sa1100_dram_regs *settings = sa1100_dram_settings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	/* find speed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	while (settings->speed != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		if (new_speed == settings->speed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		settings++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	if (settings->speed == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		panic("%s: couldn't find dram setting for speed %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		      __func__, new_speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	/* No risk, no fun: run with interrupts on! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	if (new_speed > current_speed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		/* We're going FASTER, so first relax the memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		 * timings before changing the core frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		/* Half the memory access clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		MDCNFG |= MDCNFG_CDB2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		/* The order of these statements IS important, keep 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		 * pulses!!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		MDCAS2 = settings->mdcas2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		MDCAS1 = settings->mdcas1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		MDCAS0 = settings->mdcas0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		MDCNFG = settings->mdcnfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		/* We're going SLOWER: first decrease the core
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		 * frequency and then tighten the memory settings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		/* Half the memory access clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		MDCNFG |= MDCNFG_CDB2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		/* The order of these statements IS important, keep 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		 * pulses!!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		MDCAS0 = settings->mdcas0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		MDCAS1 = settings->mdcas1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		MDCAS2 = settings->mdcas2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		MDCNFG = settings->mdcnfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static int sa1100_target(struct cpufreq_policy *policy, unsigned int ppcr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	unsigned int cur = sa11x0_getspeed(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	unsigned int new_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	new_freq = sa11x0_freq_table[ppcr].frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	if (new_freq > cur)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		sa1100_update_dram_timings(cur, new_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	PPCR = ppcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	if (new_freq < cur)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		sa1100_update_dram_timings(cur, new_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	cpufreq_generic_init(policy, sa11x0_freq_table, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static struct cpufreq_driver sa1100_driver __refdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	.flags		= CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 			  CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	.verify		= cpufreq_generic_frequency_table_verify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	.target_index	= sa1100_target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	.get		= sa11x0_getspeed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	.init		= sa1100_cpu_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	.name		= "sa1100",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static int __init sa1100_dram_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	if (cpu_is_sa1100())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		return cpufreq_register_driver(&sa1100_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) arch_initcall(sa1100_dram_init);