diff --git a/arch/sw_64/include/asm/clock.h b/arch/sw_64/include/asm/clock.h index af6872ed9edbea4f6ab3f6b176bd0bc8398f9158..8a6548aa0a0dd7b9cce5f5667e046ff2887025a0 100644 --- a/arch/sw_64/include/asm/clock.h +++ b/arch/sw_64/include/asm/clock.h @@ -11,8 +11,6 @@ struct clk; -extern struct cpufreq_frequency_table sw64_clockmod_table[]; - extern char curruent_policy[CPUFREQ_NAME_LEN]; struct clk_ops { @@ -44,7 +42,7 @@ struct clk { int clk_init(void); -void sw64_set_rate(unsigned long rate); +void sw64_set_rate(unsigned int index); struct clk *sw64_clk_get(struct device *dev, const char *id); diff --git a/arch/sw_64/kernel/clock.c b/arch/sw_64/kernel/clock.c index fac832803bd45910cac2540e6cc060d2e3c374e6..8f2bec5fd7825dcfd455d766c6472f6bcac43a68 100644 --- a/arch/sw_64/kernel/clock.c +++ b/arch/sw_64/kernel/clock.c @@ -1,9 +1,4 @@ // SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/sw/kernel/setup.c - * - * Copyright (C) 1995 Linus Torvalds - */ #include #include @@ -11,6 +6,7 @@ #include #include +#include #include #include #include @@ -29,73 +25,7 @@ #define CORE_PLL0_CFG_SHIFT 4 #define CORE_PLL2_CFG_SHIFT 18 -char curruent_policy[CPUFREQ_NAME_LEN]; - -/* Minimum CLK support */ -enum { - DC_0, DC_1, DC_2, DC_3, DC_4, DC_5, DC_6, DC_7, DC_8, - DC_9, DC_10, DC_11, DC_12, DC_13, DC_14, DC_15, DC_16, DC_RESV -}; - -static int cpu_freq[14] = { - 0, 1200, 1800, 1900, - 1950, 2000, 2050, 2100, - 2150, 2200, 2250, 2300, - 2350, 2400 }; - -struct cpufreq_frequency_table sw64_clockmod_table[] = { - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {0, DC_1, 0}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {0, DC_2, 0}, - {-1, DC_RESV, CPUFREQ_ENTRY_INVALID}, - {0, DC_3, 0}, - {0, DC_4, 0}, - {0, DC_5, 0}, - {0, DC_6, 0}, - {0, DC_7, 0}, - {0, DC_8, 0}, - {0, DC_9, 0}, - {0, DC_10, 0}, - {0, DC_11, 0}, - {0, DC_12, 0}, - {0, DC_13, 0}, -{-1, DC_RESV, CPUFREQ_TABLE_END}, -}; -EXPORT_SYMBOL_GPL(sw64_clockmod_table); +char curruent_policy[CPUFREQ_NAME_LEN]; static struct clk cpu_clk = { .name = "cpu_clk", @@ -113,13 +43,13 @@ unsigned int __sw64_cpufreq_get(struct cpufreq_policy *policy) { int i; u64 val; + struct cpufreq_frequency_table *ft = policy->freq_table; - val = sw64_io_read(0, CLK_CTL); - val = val >> CORE_PLL2_CFG_SHIFT; + val = sw64_io_read(0, CLK_CTL) >> CORE_PLL2_CFG_SHIFT; - for (i = 0; i < sizeof(cpu_freq)/sizeof(int); i++) { - if (cpu_freq[val] == cpu_freq[i]) - return cpu_freq[i]; + for (i = 0; ft[i].frequency != CPUFREQ_TABLE_END; i++) { + if (val == ft[i].driver_data) + return ft[i].frequency; } return 0; } @@ -131,61 +61,41 @@ void sw64_store_policy(struct cpufreq_policy *policy) } EXPORT_SYMBOL_GPL(sw64_store_policy); -void sw64_set_rate(unsigned long rate) +void sw64_set_rate(unsigned int index) { unsigned int i, val; - int index = -1; + int cpu_num; - rate /= 1000000; + cpu_num = sw64_chip->get_cpu_num(); - for (i = 0; i < sizeof(cpu_freq)/sizeof(int); i++) { - if (rate == cpu_freq[i]) { - index = i; - update_cpu_freq(cpu_freq[i]); - break; - } - } - - if (index < 0) - return; + for (i = 0; i < cpu_num; i++) { + sw64_io_write(i, CLK_CTL, CORE_CLK2_R | CORE_CLK2_V | CLK_PRT); + val = sw64_io_read(i, CLK_CTL); - sw64_io_write(0, CLK_CTL, CORE_CLK2_R | CORE_CLK2_V | CLK_PRT); - sw64_io_write(1, CLK_CTL, CORE_CLK2_R | CORE_CLK2_V | CLK_PRT); - val = sw64_io_read(0, CLK_CTL); + sw64_io_write(i, CLK_CTL, val | index << CORE_PLL2_CFG_SHIFT); - sw64_io_write(0, CLK_CTL, val | index << CORE_PLL2_CFG_SHIFT); - sw64_io_write(1, CLK_CTL, val | index << CORE_PLL2_CFG_SHIFT); + udelay(1); - udelay(1); + sw64_io_write(i, CLK_CTL, CORE_CLK2_V | CLK_PRT + | index << CORE_PLL2_CFG_SHIFT); + val = sw64_io_read(i, CLK_CTL); - sw64_io_write(0, CLK_CTL, CORE_CLK2_V | CLK_PRT - | index << CORE_PLL2_CFG_SHIFT); - sw64_io_write(1, CLK_CTL, CORE_CLK2_V | CLK_PRT - | index << CORE_PLL2_CFG_SHIFT); - val = sw64_io_read(0, CLK_CTL); + /* LV1 select PLL1/PLL2 */ + sw64_io_write(i, CLU_LV1_SEL, CLK_LV1_SEL_MUXA | CLK_LV1_SEL_PRT); - /* LV1 select PLL1/PLL2 */ - sw64_io_write(0, CLU_LV1_SEL, CLK_LV1_SEL_MUXA | CLK_LV1_SEL_PRT); - sw64_io_write(1, CLU_LV1_SEL, CLK_LV1_SEL_MUXA | CLK_LV1_SEL_PRT); + /* Set CLK_CTL PLL0 */ + sw64_io_write(i, CLK_CTL, val | CORE_CLK0_R | CORE_CLK0_V); - /* Set CLK_CTL PLL0 */ - sw64_io_write(0, CLK_CTL, val | CORE_CLK0_R | CORE_CLK0_V); - sw64_io_write(1, CLK_CTL, val | CORE_CLK0_R | CORE_CLK0_V); + sw64_io_write(i, CLK_CTL, val | CORE_CLK0_R | CORE_CLK0_V + | index << CORE_PLL0_CFG_SHIFT); - sw64_io_write(0, CLK_CTL, val | CORE_CLK0_R | CORE_CLK0_V - | index << CORE_PLL0_CFG_SHIFT); - sw64_io_write(1, CLK_CTL, val | CORE_CLK0_R | CORE_CLK0_V - | index << CORE_PLL0_CFG_SHIFT); + udelay(1); - udelay(1); + sw64_io_write(i, CLK_CTL, val | CORE_CLK0_V + | index << CORE_PLL0_CFG_SHIFT); - sw64_io_write(0, CLK_CTL, val | CORE_CLK0_V - | index << CORE_PLL0_CFG_SHIFT); - sw64_io_write(1, CLK_CTL, val | CORE_CLK0_V - | index << CORE_PLL0_CFG_SHIFT); - - /* LV1 select PLL0/PLL1 */ - sw64_io_write(0, CLU_LV1_SEL, CLK_LV1_SEL_MUXB | CLK_LV1_SEL_PRT); - sw64_io_write(1, CLU_LV1_SEL, CLK_LV1_SEL_MUXB | CLK_LV1_SEL_PRT); + /* LV1 select PLL0/PLL1 */ + sw64_io_write(i, CLU_LV1_SEL, CLK_LV1_SEL_MUXB | CLK_LV1_SEL_PRT); + } } EXPORT_SYMBOL_GPL(sw64_set_rate); diff --git a/drivers/cpufreq/sw64_cpufreq.c b/drivers/cpufreq/sw64_cpufreq.c index 819d8f1437e284e4da4bd381527f895916426843..74622a3ad8971ebf75f108a7f876662a2f288490 100644 --- a/drivers/cpufreq/sw64_cpufreq.c +++ b/drivers/cpufreq/sw64_cpufreq.c @@ -21,11 +21,40 @@ #include #include +#include + +#define CRYSTAL_BIT (1UL << 34) static uint nowait; static struct clk *cpuclk; +/* Minimum CLK support */ +enum { + DC_0, DC_1, DC_2, DC_3, DC_4, DC_5, DC_6, DC_7, DC_8, + DC_9, DC_10, DC_11, DC_12, DC_13, DC_14, DC_15, DC_RESV +}; + +static struct cpufreq_frequency_table freq_table[] = { + {0, DC_0, CPUFREQ_ENTRY_INVALID}, + {0, DC_1, 0}, + {0, DC_2, 0}, + {0, DC_3, 0}, + {0, DC_4, 0}, + {0, DC_5, 0}, + {0, DC_6, 0}, + {0, DC_7, 0}, + {0, DC_8, 0}, + {0, DC_9, 0}, + {0, DC_10, 0}, + {0, DC_11, 0}, + {0, DC_12, 0}, + {0, DC_13, 0}, + {0, DC_14, 0}, + {0, DC_15, 0}, + {-1, DC_RESV, CPUFREQ_TABLE_END}, +}; + static int sw64_cpu_freq_notifier(struct notifier_block *nb, unsigned long val, void *data); @@ -37,12 +66,10 @@ static int sw64_cpu_freq_notifier(struct notifier_block *nb, unsigned long val, void *data) { struct cpufreq_freqs *freqs = (struct cpufreq_freqs *)data; - unsigned long cpu; + unsigned long cpu = freqs->policy->cpu; - for_each_online_cpu(cpu) { - if (val == CPUFREQ_POSTCHANGE) - sw64_update_clockevents(cpu, freqs->new * 1000); - } + if (val == CPUFREQ_POSTCHANGE) + sw64_update_clockevents(cpu, freqs->new * 1000000); return 0; } @@ -57,7 +84,7 @@ static unsigned int sw64_cpufreq_get(unsigned int cpu) return 0; } - return __sw64_cpufreq_get(policy) * 1000; + return __sw64_cpufreq_get(policy); } /* @@ -66,22 +93,23 @@ static unsigned int sw64_cpufreq_get(unsigned int cpu) static int sw64_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) { - unsigned long freq; + unsigned int cpu = policy->cpu; - freq = 50000 * index; + if (!cpu_online(cpu)) + return -ENODEV; sw64_store_policy(policy); /* setting the cpu frequency */ - sw64_set_rate(freq * 1000); + sw64_set_rate(index); return 0; } static int sw64_cpufreq_cpu_init(struct cpufreq_policy *policy) { - unsigned long rate; int i; + unsigned long max_rate, freq_off; cpuclk = sw64_clk_get(NULL, "cpu_clk"); if (IS_ERR(cpuclk)) { @@ -89,27 +117,36 @@ static int sw64_cpufreq_cpu_init(struct cpufreq_policy *policy) return PTR_ERR(cpuclk); } - rate = get_cpu_freq() / 1000; + max_rate = get_cpu_freq() / 1000000; - /* clock table init */ - for (i = 0; - (sw64_clockmod_table[i].frequency != CPUFREQ_TABLE_END); - i++) - if (sw64_clockmod_table[i].frequency == 0) - sw64_clockmod_table[i].frequency = (rate * i) / 48; + if (sw64_io_read(0, INIT_CTL) & CRYSTAL_BIT) + freq_off = 50; + else + freq_off = 60; - sw64_set_rate(rate * 1000); + /* clock table init */ + for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { + if (i == 1) + freq_table[i].frequency = freq_off * 24; + if (i == 2) + freq_table[i].frequency = freq_off * 36; + if (i > 2) + freq_table[i].frequency = freq_off * 38 + ((i - 3) * freq_off); + + if (freq_table[i].frequency == max_rate) + freq_table[i + 1].frequency = CPUFREQ_TABLE_END; + } policy->clk = cpuclk; - cpufreq_generic_init(policy, &sw64_clockmod_table[0], 0); + cpufreq_generic_init(policy, freq_table, 0); return 0; } static int sw64_cpufreq_verify(struct cpufreq_policy_data *policy) { - return cpufreq_frequency_table_verify(policy, &sw64_clockmod_table[0]); + return cpufreq_frequency_table_verify(policy, freq_table); } static int sw64_cpufreq_exit(struct cpufreq_policy *policy)