123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651 |
- /*
- *
- * arch/arm/mach-meson/clock.c
- *
- * Copyright (C) 2010 AMLOGIC, INC.
- *
- * License terms: GNU General Public License (GPL) version 2
- * Define clocks in the app platform.
- *
- */
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/clk.h>
- #include <linux/init.h>
- #include <linux/spinlock.h>
- #include <linux/clkdev.h>
- #include <mach/clock.h>
- #include <mach/hardware.h>
- #include <mach/clk_set.h>
- #include <mach/am_regs.h>
- #include <mach/power_gate.h>
- static DEFINE_SPINLOCK(clockfw_lock);
- #ifdef CONFIG_INIT_A9_CLOCK_FREQ
- static unsigned long __initdata init_clock = CONFIG_INIT_A9_CLOCK;
- #else
- static unsigned long __initdata init_clock = 0;
- #endif
- // -----------------------------------------
- // clk_util_clk_msr
- // -----------------------------------------
- // from twister_core.v
- //
- // .clk0 ( am_ring_osc_clk_out[0] ),
- // .clk1 ( am_ring_osc_clk_out[1] ),
- // .clk2 ( ext_clk_to_msr_i ),
- // .clk3 ( cts_a9_clk ),
- // .clk4 ( cts_a9_periph_clk ),
- // .clk5 ( cts_a9_axi_clk ),
- // .clk6 ( cts_a9_at_clk ),
- // .clk7 ( cts_a9_apb_clk ),
- // .clk8 ( cts_arc625_clk ),
- // .clk9 ( sys_pll_div3 ),
- // .clk10 ( ddr_pll_clk ),
- // .clk11 ( other_pll_clk ),
- // .clk12 ( aud_pll_clk ),
- // .clk13 ( demod_pll_clk240 ),
- // .clk14 ( demod_pll_adc_clk ),
- // .clk15 ( demod_pll_wifi_adc_clk ),
- // .clk16 ( demod_pll_adc_clk_57 ),
- // .clk17 ( demod_pll_clk400 ),
- // .clk18 ( demod_pll_wifi_dac_clk ),
- // .clk19 ( vid_pll_clk ),
- // .clk20 ( vid_pll_ref_clk ),
- // .clk21 ( HDMI_CH0_TMDSCLK ),
- //
- // For Example
- //
- // unsigend long clk81_clk = clk_util_clk_msr( 2, // mux select 2
- // 50 ); // measure for 50uS
- //
- // returns a value in "clk81_clk" in Hz
- //
- // The "uS_gate_time" can be anything between 1uS and 65535 uS, but the limitation is
- // the circuit will only count 65536 clocks. Therefore the uS_gate_time is limited by
- //
- // uS_gate_time <= 65535/(expect clock frequency in MHz)
- //
- // For example, if the expected frequency is 400Mhz, then the uS_gate_time should
- // be less than 163.
- //
- // Your measurement resolution is:
- //
- // 100% / (uS_gate_time * measure_val )
- //
- //
- //unsigned int clk_util_clk_msr_rl(unsigned int clk_mux)
- unsigned int clk_util_clk_msr(unsigned int clk_mux)
- {
- unsigned int regval = 0;
- WRITE_CBUS_REG(MSR_CLK_REG0, 0);
- // Set the measurement gate to 64uS
- CLEAR_CBUS_REG_MASK(MSR_CLK_REG0, 0xffff);
- SET_CBUS_REG_MASK(MSR_CLK_REG0, (64 - 1)); //64uS is enough for measure the frequence?
- // Disable continuous measurement
- // disable interrupts
- CLEAR_CBUS_REG_MASK(MSR_CLK_REG0, ((1 << 18) | (1 << 17)));
- CLEAR_CBUS_REG_MASK(MSR_CLK_REG0, (0x1f << 20));
- SET_CBUS_REG_MASK(MSR_CLK_REG0, (clk_mux << 20) | // Select MUX
- (1 << 19) | // enable the clock
- (1 << 16)); //enable measuring
- // Wait for the measurement to be done
- regval = READ_CBUS_REG(MSR_CLK_REG0);
- do {
- regval = READ_CBUS_REG(MSR_CLK_REG0);
- } while (regval & (1 << 31));
- // disable measuring
- CLEAR_CBUS_REG_MASK(MSR_CLK_REG0, (1 << 16));
- regval = (READ_CBUS_REG(MSR_CLK_REG2) + 31) & 0x000FFFFF;
- // Return value in MHz*measured_val
- return (regval >> 6);
- }
- long clk_round_rate(struct clk *clk, unsigned long rate)
- {
- if (rate < clk->min)
- return clk->min;
- if (rate > clk->max)
- return clk->max;
- return rate;
- }
- EXPORT_SYMBOL(clk_round_rate);
- unsigned long clk_get_rate(struct clk *clk)
- {
- if (!clk)
- return 0;
- if (clk->get_rate)
- return clk->get_rate(clk);
- return clk->rate;
- }
- EXPORT_SYMBOL(clk_get_rate);
- int clk_set_rate(struct clk *clk, unsigned long rate)
- {
- unsigned long flags;
- int ret;
- if (clk == NULL || clk->set_rate == NULL)
- return -EINVAL;
- spin_lock_irqsave(&clockfw_lock, flags);
- ret = clk->set_rate(clk, rate);
- spin_unlock_irqrestore(&clockfw_lock, flags);
- return ret;
- }
- EXPORT_SYMBOL(clk_set_rate);
- static unsigned long xtal_get_rate(struct clk *clk)
- {
- unsigned long rate;
- rate = get_xtal_clock(); /*refresh from register */
- clk->rate = rate;
- return rate;
- }
- static int clk_set_rate_sys_pll(struct clk *clk, unsigned long rate)
- {
- unsigned long r = rate;
- int ret;
- if (r < 1000)
- r = r * 1000000;
- ret = sys_clkpll_setting(0, r);
- if (ret == 0)
- clk->rate = r;
- return ret;
- }
- static int clk_set_rate_other_pll(struct clk *clk, unsigned long rate)
- {
- unsigned long r = rate;
- int ret;
- if (r < 1000)
- r = r * 1000000;
- ret = other_pll_setting(0, r);
- if (ret == 0)
- clk->rate = r;
- return ret;
- }
- static int clk_set_rate_clk81(struct clk *clk, unsigned long rate)
- {
- unsigned long r = rate;
- struct clk *father_clk;
- unsigned long r1;
- int ret;
- int divider = 4;
- if (r < 1000)
- r = r * 1000000;
- if (r < 100000000)
- divider = 8;
- father_clk = clk_get_sys("clk_other_pll", NULL);
- r1 = clk_get_rate(father_clk);
- if (r1 != r * divider) {
- ret = father_clk->set_rate(father_clk, r * divider);
- if (ret != 0)
- return ret;
- }
- clk->rate = r;
- WRITE_MPEG_REG(HHI_MPEG_CLK_CNTL, (1 << 12) | // select other PLL
- ((divider - 1) << 0) | // div1
- (1 << 7) | // cntl_hi_mpeg_div_en, enable gating
- (1 << 8)); // Connect clk81 to the PLL divider output
- return 0;
- }
- static int clk_set_rate_a9_clk(struct clk *clk, unsigned long rate)
- {
- unsigned long r = rate;
- struct clk *father_clk;
- unsigned long r1;
- int ret;
- if (r < 1000)
- r = r * 1000000;
- father_clk = clk_get_sys("clk_sys_pll", NULL);
- r1 = clk_get_rate(father_clk);
- if (!r1)
- return -1;
- if (r1 != r * 2 && r != 0) {
- ret = father_clk->set_rate(father_clk, r * 2);
- if (ret != 0)
- return ret;
- }
- clk->rate = r;
- WRITE_MPEG_REG(HHI_A9_CLK_CNTL, (0 << 10) | // 0 - sys_pll_clk, 1 - audio_pll_clk
- (1 << 0) | // 1 - sys/audio pll clk, 0 - XTAL
- (1 << 4) | // APB_CLK_ENABLE
- (1 << 5) | // AT_CLK_ENABLE
- (0 << 2) | // div1
- (1 << 7)); // Connect A9 to the PLL divider output
- return 0;
- }
- static struct clk xtal_clk = {
- .name = "clk_xtal",
- .rate = 24000000,
- .get_rate = xtal_get_rate,
- .set_rate = NULL,
- };
- static struct clk clk_sys_pll = {
- .name = "clk_sys_pll",
- .rate = 1200000000,
- .min = 200000000,
- .max = 2000000000,
- .set_rate = clk_set_rate_sys_pll,
- };
- static struct clk clk_other_pll = {
- .name = "clk_other_pll",
- .rate = 750000000,
- .min = 200000000,
- .max = 800000000,
- .set_rate = clk_set_rate_other_pll,
- };
- static struct clk clk_ddr_pll = {
- .name = "clk_ddr",
- .rate = 400000000,
- .set_rate = NULL,
- };
- static struct clk clk81 = {
- .name = "clk81",
- .rate = 187500000,
- .min = 100000000,
- .max = 400000000,
- .set_rate = clk_set_rate_clk81,
- };
- static struct clk a9_clk = {
- .name = "a9_clk",
- .rate = 600000000,
- .min = 200000000,
- #if defined(CONFIG_MACH_MESON_8726M_REFC03) || defined(CONFIG_MACH_MESON_8726M_REFC06)
- .max = 750000000,
- #elif defined(CONFIG_MACH_MESON_8726M_REFC08)
- .max = 800000000,
- #else
- .max = 850000000,
- #endif
- .set_rate = clk_set_rate_a9_clk,
- };
- REGISTER_CLK(AHB_BRIDGE);
- REGISTER_CLK(AHB_SRAM);
- REGISTER_CLK(AIU_ADC);
- REGISTER_CLK(AIU_MIXER_REG);
- REGISTER_CLK(AIU_AUD_MIXER);
- REGISTER_CLK(AIU_AIFIFO2);
- REGISTER_CLK(AIU_AMCLK_MEASURE);
- REGISTER_CLK(AIU_I2S_OUT);
- REGISTER_CLK(AIU_IEC958);
- REGISTER_CLK(AIU_AI_TOP_GLUE);
- REGISTER_CLK(AIU_AUD_DAC);
- REGISTER_CLK(AIU_ICE958_AMCLK);
- REGISTER_CLK(AIU_I2S_DAC_AMCLK);
- REGISTER_CLK(AIU_I2S_SLOW);
- REGISTER_CLK(AIU_AUD_DAC_CLK);
- REGISTER_CLK(ASSIST_MISC);
- REGISTER_CLK(AMRISC);
- REGISTER_CLK(AUD_BUF);
- REGISTER_CLK(AUD_IN);
- REGISTER_CLK(BLK_MOV);
- REGISTER_CLK(BT656_IN);
- REGISTER_CLK(DEMUX);
- REGISTER_CLK(MMC_DDR);
- REGISTER_CLK(DDR);
- REGISTER_CLK(ETHERNET);
- REGISTER_CLK(GE2D);
- REGISTER_CLK(HDMI_MPEG_DOMAIN);
- REGISTER_CLK(HIU_PARSER_TOP);
- REGISTER_CLK(HIU_PARSER);
- REGISTER_CLK(ISA);
- REGISTER_CLK(MEDIA_CPU);
- REGISTER_CLK(MISC_USB0_TO_DDR);
- REGISTER_CLK(MISC_USB1_TO_DDR);
- REGISTER_CLK(MISC_SATA_TO_DDR);
- REGISTER_CLK(AHB_CONTROL_BUS);
- REGISTER_CLK(AHB_DATA_BUS);
- REGISTER_CLK(AXI_BUS);
- REGISTER_CLK(ROM_CLK);
- REGISTER_CLK(EFUSE);
- REGISTER_CLK(AHB_ARB0);
- REGISTER_CLK(RESET);
- REGISTER_CLK(MDEC_CLK_PIC_DC);
- REGISTER_CLK(MDEC_CLK_DBLK);
- REGISTER_CLK(MDEC_CLK_PSC);
- REGISTER_CLK(MDEC_CLK_ASSIST);
- REGISTER_CLK(MC_CLK);
- REGISTER_CLK(IQIDCT_CLK);
- REGISTER_CLK(VLD_CLK);
- REGISTER_CLK(NAND);
- REGISTER_CLK(RESERVED0);
- REGISTER_CLK(VGHL_PWM);
- REGISTER_CLK(LED_PWM);
- REGISTER_CLK(UART1);
- REGISTER_CLK(SDIO);
- REGISTER_CLK(ASYNC_FIFO);
- REGISTER_CLK(STREAM);
- REGISTER_CLK(RTC);
- REGISTER_CLK(UART0);
- REGISTER_CLK(RANDOM_NUM_GEN);
- REGISTER_CLK(SMART_CARD_MPEG_DOMAIN);
- REGISTER_CLK(SMART_CARD);
- REGISTER_CLK(SAR_ADC);
- REGISTER_CLK(I2C);
- REGISTER_CLK(IR_REMOTE);
- REGISTER_CLK(_1200XXX);
- REGISTER_CLK(SATA);
- REGISTER_CLK(SPI1);
- REGISTER_CLK(USB1);
- REGISTER_CLK(USB0);
- REGISTER_CLK(VI_CORE);
- REGISTER_CLK(LCD);
- REGISTER_CLK(ENC480P_MPEG_DOMAIN);
- REGISTER_CLK(ENC480I);
- REGISTER_CLK(VENC_MISC);
- REGISTER_CLK(ENC480P);
- REGISTER_CLK(HDMI);
- REGISTER_CLK(VCLK3_DAC);
- REGISTER_CLK(VCLK3_MISC);
- REGISTER_CLK(VCLK3_DVI);
- REGISTER_CLK(VCLK2_VIU);
- REGISTER_CLK(VCLK2_VENC_DVI);
- REGISTER_CLK(VCLK2_VENC_ENC480P);
- REGISTER_CLK(VCLK2_VENC_BIST);
- REGISTER_CLK(VCLK1_VENC_656);
- REGISTER_CLK(VCLK1_VENC_DVI);
- REGISTER_CLK(VCLK1_VENC_ENCI);
- REGISTER_CLK(VCLK1_VENC_BIST);
- REGISTER_CLK(VIDEO_IN);
- REGISTER_CLK(WIFI);
- static struct clk_lookup lookups[] = {
- {
- .dev_id = "clk_xtal",
- .clk = &xtal_clk,
- },
- {
- .dev_id = "clk_sys_pll",
- .clk = &clk_sys_pll,
- },
- {
- .dev_id = "clk_other_pll",
- .clk = &clk_other_pll,
- },
- {
- .dev_id = "clk_ddr_pll",
- .clk = &clk_ddr_pll,
- },
- {
- .dev_id = "clk81",
- .clk = &clk81,
- },
- {
- .dev_id = "a9_clk",
- .clk = &a9_clk,
- },
- CLK_LOOKUP_ITEM(AHB_BRIDGE),
- CLK_LOOKUP_ITEM(AHB_SRAM),
- CLK_LOOKUP_ITEM(AIU_ADC),
- CLK_LOOKUP_ITEM(AIU_MIXER_REG),
- CLK_LOOKUP_ITEM(AIU_AUD_MIXER),
- CLK_LOOKUP_ITEM(AIU_AIFIFO2),
- CLK_LOOKUP_ITEM(AIU_AMCLK_MEASURE),
- CLK_LOOKUP_ITEM(AIU_I2S_OUT),
- CLK_LOOKUP_ITEM(AIU_IEC958),
- CLK_LOOKUP_ITEM(AIU_AI_TOP_GLUE),
- CLK_LOOKUP_ITEM(AIU_AUD_DAC),
- CLK_LOOKUP_ITEM(AIU_ICE958_AMCLK),
- CLK_LOOKUP_ITEM(AIU_I2S_DAC_AMCLK),
- CLK_LOOKUP_ITEM(AIU_I2S_SLOW),
- CLK_LOOKUP_ITEM(AIU_AUD_DAC_CLK),
- CLK_LOOKUP_ITEM(ASSIST_MISC),
- CLK_LOOKUP_ITEM(AMRISC),
- CLK_LOOKUP_ITEM(AUD_BUF),
- CLK_LOOKUP_ITEM(AUD_IN),
- CLK_LOOKUP_ITEM(BLK_MOV),
- CLK_LOOKUP_ITEM(BT656_IN),
- CLK_LOOKUP_ITEM(DEMUX),
- CLK_LOOKUP_ITEM(MMC_DDR),
- CLK_LOOKUP_ITEM(DDR),
- CLK_LOOKUP_ITEM(ETHERNET),
- CLK_LOOKUP_ITEM(GE2D),
- CLK_LOOKUP_ITEM(HDMI_MPEG_DOMAIN),
- CLK_LOOKUP_ITEM(HIU_PARSER_TOP),
- CLK_LOOKUP_ITEM(HIU_PARSER),
- CLK_LOOKUP_ITEM(ISA),
- CLK_LOOKUP_ITEM(MEDIA_CPU),
- CLK_LOOKUP_ITEM(MISC_USB0_TO_DDR),
- CLK_LOOKUP_ITEM(MISC_USB1_TO_DDR),
- CLK_LOOKUP_ITEM(MISC_SATA_TO_DDR),
- CLK_LOOKUP_ITEM(AHB_CONTROL_BUS),
- CLK_LOOKUP_ITEM(AHB_DATA_BUS),
- CLK_LOOKUP_ITEM(AXI_BUS),
- CLK_LOOKUP_ITEM(ROM_CLK),
- CLK_LOOKUP_ITEM(EFUSE),
- CLK_LOOKUP_ITEM(AHB_ARB0),
- CLK_LOOKUP_ITEM(RESET),
- CLK_LOOKUP_ITEM(MDEC_CLK_PIC_DC),
- CLK_LOOKUP_ITEM(MDEC_CLK_DBLK),
- CLK_LOOKUP_ITEM(MDEC_CLK_PSC),
- CLK_LOOKUP_ITEM(MDEC_CLK_ASSIST),
- CLK_LOOKUP_ITEM(MC_CLK),
- CLK_LOOKUP_ITEM(IQIDCT_CLK),
- CLK_LOOKUP_ITEM(VLD_CLK),
- CLK_LOOKUP_ITEM(NAND),
- CLK_LOOKUP_ITEM(RESERVED0),
- CLK_LOOKUP_ITEM(VGHL_PWM),
- CLK_LOOKUP_ITEM(LED_PWM),
- CLK_LOOKUP_ITEM(UART1),
- CLK_LOOKUP_ITEM(SDIO),
- CLK_LOOKUP_ITEM(ASYNC_FIFO),
- CLK_LOOKUP_ITEM(STREAM),
- CLK_LOOKUP_ITEM(RTC),
- CLK_LOOKUP_ITEM(UART0),
- CLK_LOOKUP_ITEM(RANDOM_NUM_GEN),
- CLK_LOOKUP_ITEM(SMART_CARD_MPEG_DOMAIN),
- CLK_LOOKUP_ITEM(SMART_CARD),
- CLK_LOOKUP_ITEM(SAR_ADC),
- CLK_LOOKUP_ITEM(I2C),
- CLK_LOOKUP_ITEM(IR_REMOTE),
- CLK_LOOKUP_ITEM(_1200XXX),
- CLK_LOOKUP_ITEM(SATA),
- CLK_LOOKUP_ITEM(SPI1),
- CLK_LOOKUP_ITEM(USB1),
- CLK_LOOKUP_ITEM(USB0),
- CLK_LOOKUP_ITEM(VI_CORE),
- CLK_LOOKUP_ITEM(LCD),
- CLK_LOOKUP_ITEM(ENC480P_MPEG_DOMAIN),
- CLK_LOOKUP_ITEM(ENC480I),
- CLK_LOOKUP_ITEM(VENC_MISC),
- CLK_LOOKUP_ITEM(ENC480P),
- CLK_LOOKUP_ITEM(HDMI),
- CLK_LOOKUP_ITEM(VCLK3_DAC),
- CLK_LOOKUP_ITEM(VCLK3_MISC),
- CLK_LOOKUP_ITEM(VCLK3_DVI),
- CLK_LOOKUP_ITEM(VCLK2_VIU),
- CLK_LOOKUP_ITEM(VCLK2_VENC_DVI),
- CLK_LOOKUP_ITEM(VCLK2_VENC_ENC480P),
- CLK_LOOKUP_ITEM(VCLK2_VENC_BIST),
- CLK_LOOKUP_ITEM(VCLK1_VENC_656),
- CLK_LOOKUP_ITEM(VCLK1_VENC_DVI),
- CLK_LOOKUP_ITEM(VCLK1_VENC_ENCI),
- CLK_LOOKUP_ITEM(VCLK1_VENC_BIST),
- CLK_LOOKUP_ITEM(VIDEO_IN),
- CLK_LOOKUP_ITEM(WIFI)
- };
- static int __init meson_clock_init(void)
- {
- if (init_clock && init_clock != a9_clk.rate) {
- if (sys_clkpll_setting(0, init_clock << 1) == 0) {
- a9_clk.rate = init_clock;
- clk_sys_pll.rate = init_clock << 1;
- }
- }
- /* Register the lookups */
- clkdev_add_table(lookups, ARRAY_SIZE(lookups));
- return 0;
- }
- /* initialize clocking early to be available later in the boot */
- core_initcall(meson_clock_init);
- unsigned long long clkparse(const char *ptr, char **retptr)
- {
- char *endptr; /* local pointer to end of parsed string */
- unsigned long long ret = simple_strtoull(ptr, &endptr, 0);
- switch (*endptr) {
- case 'G':
- case 'g':
- ret *= 1000;
- case 'M':
- case 'm':
- ret *= 1000;
- case 'K':
- case 'k':
- ret *= 1000;
- endptr++;
- default:
- break;
- }
- if (retptr)
- *retptr = endptr;
- return ret;
- }
- static int __init a9_clock_setup(char *ptr)
- {
- init_clock = clkparse(ptr, 0);
- if (sys_clkpll_setting(0, init_clock << 1) == 0) {
- a9_clk.rate = init_clock;
- clk_sys_pll.rate = init_clock << 1;
- }
- return 0;
- }
- __setup("a9_clk=", a9_clock_setup);
- static int __init clk81_clock_setup(char *ptr)
- {
- int clock = clkparse(ptr, 0);
- int divider = 4;
- if (clock < 100000000)
- divider = 8;
- if (other_pll_setting(0, clock * divider) == 0) {
- /* todo: uart baudrate depends on clk81, assume 115200 baudrate */
- int baudrate = (clock / (115200 * 4)) - 1;
- clk_other_pll.rate = clock * divider;
- clk81.rate = clock;
- WRITE_MPEG_REG(HHI_MPEG_CLK_CNTL, // MPEG clk81 set to other/4
- (1 << 12) | // select other PLL
- ((divider - 1) << 0) | // div1
- (1 << 7) | // cntl_hi_mpeg_div_en, enable gating
- (1 << 8)); // Connect clk81 to the PLL divider output
- CLEAR_CBUS_REG_MASK(UART0_CONTROL, (1 << 19) | 0xFFF);
- SET_CBUS_REG_MASK(UART0_CONTROL, (baudrate & 0xfff));
- CLEAR_CBUS_REG_MASK(UART1_CONTROL, (1 << 19) | 0xFFF);
- SET_CBUS_REG_MASK(UART1_CONTROL, (baudrate & 0xfff));
- }
- return 0;
- }
- __setup("clk81=", clk81_clock_setup);
- int clk_enable(struct clk *clk)
- {
- unsigned long flags;
- spin_lock_irqsave(&clockfw_lock, flags);
- if (clk->clock_index >= 0 && clk->clock_index < GCLK_IDX_MAX
- && clk->clock_gate_reg_adr != 0) {
- if (GCLK_ref[clk->clock_index]++ == 0) {
- SET_CBUS_REG_MASK(clk->clock_gate_reg_adr,
- clk->clock_gate_reg_mask);
- }
- }
- spin_unlock_irqrestore(&clockfw_lock, flags);
- return 0;
- }
- EXPORT_SYMBOL(clk_enable);
- void clk_disable(struct clk *clk)
- {
- unsigned long flags;
- spin_lock_irqsave(&clockfw_lock, flags);
- if (clk->clock_index >= 0 && clk->clock_index < GCLK_IDX_MAX
- && clk->clock_gate_reg_adr != 0) {
- if ((GCLK_ref[clk->clock_index] != 0)
- && (--GCLK_ref[clk->clock_index] == 0))
- CLEAR_CBUS_REG_MASK(clk->clock_gate_reg_adr,
- clk->clock_gate_reg_mask);
- }
- spin_unlock_irqrestore(&clockfw_lock, flags);
- }
- EXPORT_SYMBOL(clk_disable);
|