1*8e4b7721SAndrew Bresticker /* 2*8e4b7721SAndrew Bresticker * Copyright (C) 2014 Google, Inc. 3*8e4b7721SAndrew Bresticker * 4*8e4b7721SAndrew Bresticker * This program is free software; you can redistribute it and/or modify it 5*8e4b7721SAndrew Bresticker * under the terms and conditions of the GNU General Public License, 6*8e4b7721SAndrew Bresticker * version 2, as published by the Free Software Foundation. 7*8e4b7721SAndrew Bresticker */ 8*8e4b7721SAndrew Bresticker 9*8e4b7721SAndrew Bresticker #include <linux/clk-provider.h> 10*8e4b7721SAndrew Bresticker #include <linux/kernel.h> 11*8e4b7721SAndrew Bresticker #include <linux/of.h> 12*8e4b7721SAndrew Bresticker #include <linux/of_address.h> 13*8e4b7721SAndrew Bresticker #include <linux/slab.h> 14*8e4b7721SAndrew Bresticker 15*8e4b7721SAndrew Bresticker #include "clk.h" 16*8e4b7721SAndrew Bresticker 17*8e4b7721SAndrew Bresticker struct pistachio_clk_provider * 18*8e4b7721SAndrew Bresticker pistachio_clk_alloc_provider(struct device_node *node, unsigned int num_clks) 19*8e4b7721SAndrew Bresticker { 20*8e4b7721SAndrew Bresticker struct pistachio_clk_provider *p; 21*8e4b7721SAndrew Bresticker 22*8e4b7721SAndrew Bresticker p = kzalloc(sizeof(*p), GFP_KERNEL); 23*8e4b7721SAndrew Bresticker if (!p) 24*8e4b7721SAndrew Bresticker return p; 25*8e4b7721SAndrew Bresticker 26*8e4b7721SAndrew Bresticker p->clk_data.clks = kcalloc(num_clks, sizeof(struct clk *), GFP_KERNEL); 27*8e4b7721SAndrew Bresticker if (!p->clk_data.clks) 28*8e4b7721SAndrew Bresticker goto free_provider; 29*8e4b7721SAndrew Bresticker p->clk_data.clk_num = num_clks; 30*8e4b7721SAndrew Bresticker p->node = node; 31*8e4b7721SAndrew Bresticker p->base = of_iomap(node, 0); 32*8e4b7721SAndrew Bresticker if (!p->base) { 33*8e4b7721SAndrew Bresticker pr_err("Failed to map clock provider registers\n"); 34*8e4b7721SAndrew Bresticker goto free_clks; 35*8e4b7721SAndrew Bresticker } 36*8e4b7721SAndrew Bresticker 37*8e4b7721SAndrew Bresticker return p; 38*8e4b7721SAndrew Bresticker 39*8e4b7721SAndrew Bresticker free_clks: 40*8e4b7721SAndrew Bresticker kfree(p->clk_data.clks); 41*8e4b7721SAndrew Bresticker free_provider: 42*8e4b7721SAndrew Bresticker kfree(p); 43*8e4b7721SAndrew Bresticker return NULL; 44*8e4b7721SAndrew Bresticker } 45*8e4b7721SAndrew Bresticker 46*8e4b7721SAndrew Bresticker void pistachio_clk_register_provider(struct pistachio_clk_provider *p) 47*8e4b7721SAndrew Bresticker { 48*8e4b7721SAndrew Bresticker unsigned int i; 49*8e4b7721SAndrew Bresticker 50*8e4b7721SAndrew Bresticker for (i = 0; i < p->clk_data.clk_num; i++) { 51*8e4b7721SAndrew Bresticker if (IS_ERR(p->clk_data.clks[i])) 52*8e4b7721SAndrew Bresticker pr_warn("Failed to register clock %d: %ld\n", i, 53*8e4b7721SAndrew Bresticker PTR_ERR(p->clk_data.clks[i])); 54*8e4b7721SAndrew Bresticker } 55*8e4b7721SAndrew Bresticker 56*8e4b7721SAndrew Bresticker of_clk_add_provider(p->node, of_clk_src_onecell_get, &p->clk_data); 57*8e4b7721SAndrew Bresticker } 58*8e4b7721SAndrew Bresticker 59*8e4b7721SAndrew Bresticker void pistachio_clk_register_gate(struct pistachio_clk_provider *p, 60*8e4b7721SAndrew Bresticker struct pistachio_gate *gate, 61*8e4b7721SAndrew Bresticker unsigned int num) 62*8e4b7721SAndrew Bresticker { 63*8e4b7721SAndrew Bresticker struct clk *clk; 64*8e4b7721SAndrew Bresticker unsigned int i; 65*8e4b7721SAndrew Bresticker 66*8e4b7721SAndrew Bresticker for (i = 0; i < num; i++) { 67*8e4b7721SAndrew Bresticker clk = clk_register_gate(NULL, gate[i].name, gate[i].parent, 68*8e4b7721SAndrew Bresticker CLK_SET_RATE_PARENT, 69*8e4b7721SAndrew Bresticker p->base + gate[i].reg, gate[i].shift, 70*8e4b7721SAndrew Bresticker 0, NULL); 71*8e4b7721SAndrew Bresticker p->clk_data.clks[gate[i].id] = clk; 72*8e4b7721SAndrew Bresticker } 73*8e4b7721SAndrew Bresticker } 74*8e4b7721SAndrew Bresticker 75*8e4b7721SAndrew Bresticker void pistachio_clk_register_mux(struct pistachio_clk_provider *p, 76*8e4b7721SAndrew Bresticker struct pistachio_mux *mux, 77*8e4b7721SAndrew Bresticker unsigned int num) 78*8e4b7721SAndrew Bresticker { 79*8e4b7721SAndrew Bresticker struct clk *clk; 80*8e4b7721SAndrew Bresticker unsigned int i; 81*8e4b7721SAndrew Bresticker 82*8e4b7721SAndrew Bresticker for (i = 0; i < num; i++) { 83*8e4b7721SAndrew Bresticker clk = clk_register_mux(NULL, mux[i].name, mux[i].parents, 84*8e4b7721SAndrew Bresticker mux[i].num_parents, 85*8e4b7721SAndrew Bresticker CLK_SET_RATE_NO_REPARENT, 86*8e4b7721SAndrew Bresticker p->base + mux[i].reg, mux[i].shift, 87*8e4b7721SAndrew Bresticker get_count_order(mux[i].num_parents), 88*8e4b7721SAndrew Bresticker 0, NULL); 89*8e4b7721SAndrew Bresticker p->clk_data.clks[mux[i].id] = clk; 90*8e4b7721SAndrew Bresticker } 91*8e4b7721SAndrew Bresticker } 92*8e4b7721SAndrew Bresticker 93*8e4b7721SAndrew Bresticker void pistachio_clk_register_div(struct pistachio_clk_provider *p, 94*8e4b7721SAndrew Bresticker struct pistachio_div *div, 95*8e4b7721SAndrew Bresticker unsigned int num) 96*8e4b7721SAndrew Bresticker { 97*8e4b7721SAndrew Bresticker struct clk *clk; 98*8e4b7721SAndrew Bresticker unsigned int i; 99*8e4b7721SAndrew Bresticker 100*8e4b7721SAndrew Bresticker for (i = 0; i < num; i++) { 101*8e4b7721SAndrew Bresticker clk = clk_register_divider(NULL, div[i].name, div[i].parent, 102*8e4b7721SAndrew Bresticker 0, p->base + div[i].reg, 0, 103*8e4b7721SAndrew Bresticker div[i].width, div[i].div_flags, 104*8e4b7721SAndrew Bresticker NULL); 105*8e4b7721SAndrew Bresticker p->clk_data.clks[div[i].id] = clk; 106*8e4b7721SAndrew Bresticker } 107*8e4b7721SAndrew Bresticker } 108*8e4b7721SAndrew Bresticker 109*8e4b7721SAndrew Bresticker void pistachio_clk_register_fixed_factor(struct pistachio_clk_provider *p, 110*8e4b7721SAndrew Bresticker struct pistachio_fixed_factor *ff, 111*8e4b7721SAndrew Bresticker unsigned int num) 112*8e4b7721SAndrew Bresticker { 113*8e4b7721SAndrew Bresticker struct clk *clk; 114*8e4b7721SAndrew Bresticker unsigned int i; 115*8e4b7721SAndrew Bresticker 116*8e4b7721SAndrew Bresticker for (i = 0; i < num; i++) { 117*8e4b7721SAndrew Bresticker clk = clk_register_fixed_factor(NULL, ff[i].name, ff[i].parent, 118*8e4b7721SAndrew Bresticker 0, 1, ff[i].div); 119*8e4b7721SAndrew Bresticker p->clk_data.clks[ff[i].id] = clk; 120*8e4b7721SAndrew Bresticker } 121*8e4b7721SAndrew Bresticker } 122*8e4b7721SAndrew Bresticker 123*8e4b7721SAndrew Bresticker void pistachio_clk_force_enable(struct pistachio_clk_provider *p, 124*8e4b7721SAndrew Bresticker unsigned int *clk_ids, unsigned int num) 125*8e4b7721SAndrew Bresticker { 126*8e4b7721SAndrew Bresticker unsigned int i; 127*8e4b7721SAndrew Bresticker int err; 128*8e4b7721SAndrew Bresticker 129*8e4b7721SAndrew Bresticker for (i = 0; i < num; i++) { 130*8e4b7721SAndrew Bresticker struct clk *clk = p->clk_data.clks[clk_ids[i]]; 131*8e4b7721SAndrew Bresticker 132*8e4b7721SAndrew Bresticker if (IS_ERR(clk)) 133*8e4b7721SAndrew Bresticker continue; 134*8e4b7721SAndrew Bresticker 135*8e4b7721SAndrew Bresticker err = clk_prepare_enable(clk); 136*8e4b7721SAndrew Bresticker if (err) 137*8e4b7721SAndrew Bresticker pr_err("Failed to enable clock %s: %d\n", 138*8e4b7721SAndrew Bresticker __clk_get_name(clk), err); 139*8e4b7721SAndrew Bresticker } 140*8e4b7721SAndrew Bresticker } 141