/* * Copyright (C) 2010 ST-Ericsson * Copyright (C) 2009 STMicrolectronics * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ /** * struct clkops - ux500 clock operations * @enable: function to enable the clock * @disable: function to disable the clock * @get_rate: function to get the current clock rate * * This structure contains function pointers to functions that will be used to * control the clock. All of these functions are optional. If get_rate is * NULL, the rate in the struct clk will be used. */ extern int __init clk_init(void); struct clkops { void (*enable) (struct clk *); void (*disable) (struct clk *); unsigned long (*get_rate) (struct clk *); }; /** * struct clk - ux500 clock structure * @ops: pointer to clkops struct used to control this clock * @name: name, for debugging * @enabled: refcount. positive if enabled, zero if disabled * @rate: fixed rate for clocks which don't implement * ops->getrate * @prcmu_cg_off: address offset of the combined enable/disable register * (used on u8500v1) * @prcmu_cg_bit: bit in the combined enable/disable register (used on * u8500v1) * @prcmu_cg_mgt: address of the enable/disable register (used on * u8500ed) * @cluster: peripheral cluster number * @prcc_bus: bit for the bus clock in the peripheral's CLKRST * @prcc_kernel: bit for the kernel clock in the peripheral's CLKRST. * -1 if no kernel clock exists. * @parent_cluster: pointer to parent's cluster clk struct * @parent_periph: pointer to parent's peripheral clk struct * * Peripherals are organised into clusters, and each cluster has an associated * bus clock. Some peripherals also have a parent peripheral clock. * * In order to enable a clock for a peripheral, we need to enable: * (1) the parent cluster (bus) clock at the PRCMU level * (2) the parent peripheral clock (if any) at the PRCMU level * (3) the peripheral's bus & kernel clock at the PRCC level * * (1) and (2) are handled by defining clk structs (DEFINE_PRCMU_CLK) for each * of the cluster and peripheral clocks, and hooking these as the parents of * the individual peripheral clocks. * * (3) is handled by specifying the bits in the PRCC control registers required * to enable these clocks and modifying them in the ->enable and * ->disable callbacks of the peripheral clocks (DEFINE_PRCC_CLK). * * This structure describes both the PRCMU-level clocks and PRCC-level clocks. * The prcmu_* fields are only used for the PRCMU clocks, and the cluster, * prcc, and parent pointers are only used for the PRCC-level clocks. */ struct clk { const struct clkops *ops; const char *name; unsigned int enabled; unsigned long rate; struct list_head list; /* These three are only for PRCMU clks */ unsigned int prcmu_cg_off; unsigned int prcmu_cg_bit; unsigned int prcmu_cg_mgt; /* The rest are only for PRCC clks */ int cluster; unsigned int prcc_bus; unsigned int prcc_kernel; struct clk *parent_cluster; struct clk *parent_periph; }; #define DEFINE_PRCMU_CLK(_name, _cg_off, _cg_bit, _reg) \ struct clk clk_##_name = { \ .name = #_name, \ .ops = &clk_prcmu_ops, \ .prcmu_cg_off = _cg_off, \ .prcmu_cg_bit = _cg_bit, \ .prcmu_cg_mgt = PRCM_##_reg##_MGT \ } #define DEFINE_PRCMU_CLK_RATE(_name, _cg_off, _cg_bit, _reg, _rate) \ struct clk clk_##_name = { \ .name = #_name, \ .ops = &clk_prcmu_ops, \ .prcmu_cg_off = _cg_off, \ .prcmu_cg_bit = _cg_bit, \ .rate = _rate, \ .prcmu_cg_mgt = PRCM_##_reg##_MGT \ } #define DEFINE_PRCC_CLK(_pclust, _name, _bus_en, _kernel_en, _kernclk) \ struct clk clk_##_name = { \ .name = #_name, \ .ops = &clk_prcc_ops, \ .cluster = _pclust, \ .prcc_bus = _bus_en, \ .prcc_kernel = _kernel_en, \ .parent_cluster = &clk_per##_pclust##clk, \ .parent_periph = _kernclk \ } #define CLK(_clk, _devname, _conname) \ { \ .clk = &clk_##_clk, \ .dev_id = _devname, \ .con_id = _conname, \ }