|  | @@ -154,3 +154,197 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 | 
	
		
			
				|  |  |  	 * the clock may have been made this way by choice.
 | 
	
		
			
				|  |  |  	 */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	WARN_ON(clk->ops == NULL);
 | 
	
		
			
				|  |  | +	WARN_ON(clk->ops && clk->ops->set_rate == NULL);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (clk->ops == NULL || clk->ops->set_rate == NULL)
 | 
	
		
			
				|  |  | +		return -EINVAL;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	spin_lock_irqsave(&clocks_lock, flags);
 | 
	
		
			
				|  |  | +	ret = (clk->ops->set_rate)(clk, rate);
 | 
	
		
			
				|  |  | +	spin_unlock_irqrestore(&clocks_lock, flags);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return ret;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct clk *clk_get_parent(struct clk *clk)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	return clk->parent;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +int clk_set_parent(struct clk *clk, struct clk *parent)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	unsigned long flags;
 | 
	
		
			
				|  |  | +	int ret = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (IS_ERR_OR_NULL(clk) || IS_ERR_OR_NULL(parent))
 | 
	
		
			
				|  |  | +		return -EINVAL;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	spin_lock_irqsave(&clocks_lock, flags);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (clk->ops && clk->ops->set_parent)
 | 
	
		
			
				|  |  | +		ret = (clk->ops->set_parent)(clk, parent);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	spin_unlock_irqrestore(&clocks_lock, flags);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return ret;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +EXPORT_SYMBOL(clk_enable);
 | 
	
		
			
				|  |  | +EXPORT_SYMBOL(clk_disable);
 | 
	
		
			
				|  |  | +EXPORT_SYMBOL(clk_get_rate);
 | 
	
		
			
				|  |  | +EXPORT_SYMBOL(clk_round_rate);
 | 
	
		
			
				|  |  | +EXPORT_SYMBOL(clk_set_rate);
 | 
	
		
			
				|  |  | +EXPORT_SYMBOL(clk_get_parent);
 | 
	
		
			
				|  |  | +EXPORT_SYMBOL(clk_set_parent);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* base clocks */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +int clk_default_setrate(struct clk *clk, unsigned long rate)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	clk->rate = rate;
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct clk_ops clk_ops_def_setrate = {
 | 
	
		
			
				|  |  | +	.set_rate	= clk_default_setrate,
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct clk clk_xtal = {
 | 
	
		
			
				|  |  | +	.name		= "xtal",
 | 
	
		
			
				|  |  | +	.rate		= 0,
 | 
	
		
			
				|  |  | +	.parent		= NULL,
 | 
	
		
			
				|  |  | +	.ctrlbit	= 0,
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct clk clk_ext = {
 | 
	
		
			
				|  |  | +	.name		= "ext",
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct clk clk_epll = {
 | 
	
		
			
				|  |  | +	.name		= "epll",
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct clk clk_mpll = {
 | 
	
		
			
				|  |  | +	.name		= "mpll",
 | 
	
		
			
				|  |  | +	.ops		= &clk_ops_def_setrate,
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct clk clk_upll = {
 | 
	
		
			
				|  |  | +	.name		= "upll",
 | 
	
		
			
				|  |  | +	.parent		= NULL,
 | 
	
		
			
				|  |  | +	.ctrlbit	= 0,
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct clk clk_f = {
 | 
	
		
			
				|  |  | +	.name		= "fclk",
 | 
	
		
			
				|  |  | +	.rate		= 0,
 | 
	
		
			
				|  |  | +	.parent		= &clk_mpll,
 | 
	
		
			
				|  |  | +	.ctrlbit	= 0,
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct clk clk_h = {
 | 
	
		
			
				|  |  | +	.name		= "hclk",
 | 
	
		
			
				|  |  | +	.rate		= 0,
 | 
	
		
			
				|  |  | +	.parent		= NULL,
 | 
	
		
			
				|  |  | +	.ctrlbit	= 0,
 | 
	
		
			
				|  |  | +	.ops		= &clk_ops_def_setrate,
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct clk clk_p = {
 | 
	
		
			
				|  |  | +	.name		= "pclk",
 | 
	
		
			
				|  |  | +	.rate		= 0,
 | 
	
		
			
				|  |  | +	.parent		= NULL,
 | 
	
		
			
				|  |  | +	.ctrlbit	= 0,
 | 
	
		
			
				|  |  | +	.ops		= &clk_ops_def_setrate,
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct clk clk_usb_bus = {
 | 
	
		
			
				|  |  | +	.name		= "usb-bus",
 | 
	
		
			
				|  |  | +	.rate		= 0,
 | 
	
		
			
				|  |  | +	.parent		= &clk_upll,
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct clk s3c24xx_uclk = {
 | 
	
		
			
				|  |  | +	.name		= "uclk",
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* initialise the clock system */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * s3c24xx_register_clock() - register a clock
 | 
	
		
			
				|  |  | + * @clk: The clock to register
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Add the specified clock to the list of clocks known by the system.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +int s3c24xx_register_clock(struct clk *clk)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	if (clk->enable == NULL)
 | 
	
		
			
				|  |  | +		clk->enable = clk_null_enable;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* fill up the clk_lookup structure and register it*/
 | 
	
		
			
				|  |  | +	clk->lookup.dev_id = clk->devname;
 | 
	
		
			
				|  |  | +	clk->lookup.con_id = clk->name;
 | 
	
		
			
				|  |  | +	clk->lookup.clk = clk;
 | 
	
		
			
				|  |  | +	clkdev_add(&clk->lookup);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * s3c24xx_register_clocks() - register an array of clock pointers
 | 
	
		
			
				|  |  | + * @clks: Pointer to an array of struct clk pointers
 | 
	
		
			
				|  |  | + * @nr_clks: The number of clocks in the @clks array.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Call s3c24xx_register_clock() for all the clock pointers contained
 | 
	
		
			
				|  |  | + * in the @clks list. Returns the number of failures.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +int s3c24xx_register_clocks(struct clk **clks, int nr_clks)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	int fails = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	for (; nr_clks > 0; nr_clks--, clks++) {
 | 
	
		
			
				|  |  | +		if (s3c24xx_register_clock(*clks) < 0) {
 | 
	
		
			
				|  |  | +			struct clk *clk = *clks;
 | 
	
		
			
				|  |  | +			printk(KERN_ERR "%s: failed to register %p: %s\n",
 | 
	
		
			
				|  |  | +			       __func__, clk, clk->name);
 | 
	
		
			
				|  |  | +			fails++;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return fails;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * s3c_register_clocks() - register an array of clocks
 | 
	
		
			
				|  |  | + * @clkp: Pointer to the first clock in the array.
 | 
	
		
			
				|  |  | + * @nr_clks: Number of clocks to register.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Call s3c24xx_register_clock() on the @clkp array given, printing an
 | 
	
		
			
				|  |  | + * error if it fails to register the clock (unlikely).
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +void __init s3c_register_clocks(struct clk *clkp, int nr_clks)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	int ret;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	for (; nr_clks > 0; nr_clks--, clkp++) {
 | 
	
		
			
				|  |  | +		ret = s3c24xx_register_clock(clkp);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		if (ret < 0) {
 | 
	
		
			
				|  |  | +			printk(KERN_ERR "Failed to register clock %s (%d)\n",
 | 
	
		
			
				|  |  | +			       clkp->name, ret);
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * s3c_disable_clocks() - disable an array of clocks
 | 
	
		
			
				|  |  | + * @clkp: Pointer to the first clock in the array.
 | 
	
		
			
				|  |  | + * @nr_clks: Number of clocks to register.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * for internal use only at initialisation time. disable the clocks in the
 | 
	
		
			
				|  |  | + * @clkp array.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void __init s3c_disable_clocks(struct clk *clkp, int nr_clks)
 |