1 /* 2 * clkgen-mux.c: ST GEN-MUX Clock driver 3 * 4 * Copyright (C) 2014 STMicroelectronics (R&D) Limited 5 * 6 * Authors: Stephen Gallimore <stephen.gallimore@st.com> 7 * Pankaj Dev <pankaj.dev@st.com> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 */ 15 16 #include <linux/slab.h> 17 #include <linux/of_address.h> 18 #include <linux/clk.h> 19 #include <linux/clk-provider.h> 20 #include "clkgen.h" 21 22 static const char ** __init clkgen_mux_get_parents(struct device_node *np, 23 int *num_parents) 24 { 25 const char **parents; 26 unsigned int nparents; 27 28 nparents = of_clk_get_parent_count(np); 29 if (WARN_ON(!nparents)) 30 return ERR_PTR(-EINVAL); 31 32 parents = kcalloc(nparents, sizeof(const char *), GFP_KERNEL); 33 if (!parents) 34 return ERR_PTR(-ENOMEM); 35 36 *num_parents = of_clk_parent_fill(np, parents, nparents); 37 return parents; 38 } 39 40 struct clkgen_mux_data { 41 u32 offset; 42 u8 shift; 43 u8 width; 44 spinlock_t *lock; 45 unsigned long clk_flags; 46 u8 mux_flags; 47 }; 48 49 static struct clkgen_mux_data stih407_a9_mux_data = { 50 .offset = 0x1a4, 51 .shift = 0, 52 .width = 2, 53 .lock = &clkgen_a9_lock, 54 }; 55 56 static void __init st_of_clkgen_mux_setup(struct device_node *np, 57 struct clkgen_mux_data *data) 58 { 59 struct clk *clk; 60 void __iomem *reg; 61 const char **parents; 62 int num_parents = 0; 63 64 reg = of_iomap(np, 0); 65 if (!reg) { 66 pr_err("%s: Failed to get base address\n", __func__); 67 return; 68 } 69 70 parents = clkgen_mux_get_parents(np, &num_parents); 71 if (IS_ERR(parents)) { 72 pr_err("%s: Failed to get parents (%ld)\n", 73 __func__, PTR_ERR(parents)); 74 goto err_parents; 75 } 76 77 clk = clk_register_mux(NULL, np->name, parents, num_parents, 78 data->clk_flags | CLK_SET_RATE_PARENT, 79 reg + data->offset, 80 data->shift, data->width, data->mux_flags, 81 data->lock); 82 if (IS_ERR(clk)) 83 goto err; 84 85 pr_debug("%s: parent %s rate %u\n", 86 __clk_get_name(clk), 87 __clk_get_name(clk_get_parent(clk)), 88 (unsigned int)clk_get_rate(clk)); 89 90 kfree(parents); 91 of_clk_add_provider(np, of_clk_src_simple_get, clk); 92 return; 93 94 err: 95 kfree(parents); 96 err_parents: 97 iounmap(reg); 98 } 99 100 static void __init st_of_clkgen_a9_mux_setup(struct device_node *np) 101 { 102 st_of_clkgen_mux_setup(np, &stih407_a9_mux_data); 103 } 104 CLK_OF_DECLARE(clkgen_a9mux, "st,stih407-clkgen-a9-mux", 105 st_of_clkgen_a9_mux_setup); 106