1 /* 2 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 */ 10 11 #include <linux/clk-provider.h> 12 #include <linux/clkdev.h> 13 #include <linux/clk/at91_pmc.h> 14 #include <linux/of.h> 15 #include <linux/of_address.h> 16 #include <linux/io.h> 17 #include <linux/irq.h> 18 #include <linux/of_irq.h> 19 #include <linux/interrupt.h> 20 #include <linux/wait.h> 21 #include <linux/sched.h> 22 23 #include "pmc.h" 24 25 #define SYSTEM_MAX_ID 31 26 27 #define SYSTEM_MAX_NAME_SZ 32 28 29 #define to_clk_system(hw) container_of(hw, struct clk_system, hw) 30 struct clk_system { 31 struct clk_hw hw; 32 struct at91_pmc *pmc; 33 unsigned int irq; 34 wait_queue_head_t wait; 35 u8 id; 36 }; 37 38 static inline int is_pck(int id) 39 { 40 return (id >= 8) && (id <= 15); 41 } 42 static irqreturn_t clk_system_irq_handler(int irq, void *dev_id) 43 { 44 struct clk_system *sys = (struct clk_system *)dev_id; 45 46 wake_up(&sys->wait); 47 disable_irq_nosync(sys->irq); 48 49 return IRQ_HANDLED; 50 } 51 52 static int clk_system_prepare(struct clk_hw *hw) 53 { 54 struct clk_system *sys = to_clk_system(hw); 55 struct at91_pmc *pmc = sys->pmc; 56 u32 mask = 1 << sys->id; 57 58 pmc_write(pmc, AT91_PMC_SCER, mask); 59 60 if (!is_pck(sys->id)) 61 return 0; 62 63 while (!(pmc_read(pmc, AT91_PMC_SR) & mask)) { 64 if (sys->irq) { 65 enable_irq(sys->irq); 66 wait_event(sys->wait, 67 pmc_read(pmc, AT91_PMC_SR) & mask); 68 } else 69 cpu_relax(); 70 } 71 return 0; 72 } 73 74 static void clk_system_unprepare(struct clk_hw *hw) 75 { 76 struct clk_system *sys = to_clk_system(hw); 77 struct at91_pmc *pmc = sys->pmc; 78 79 pmc_write(pmc, AT91_PMC_SCDR, 1 << sys->id); 80 } 81 82 static int clk_system_is_prepared(struct clk_hw *hw) 83 { 84 struct clk_system *sys = to_clk_system(hw); 85 struct at91_pmc *pmc = sys->pmc; 86 87 if (!(pmc_read(pmc, AT91_PMC_SCSR) & (1 << sys->id))) 88 return 0; 89 90 if (!is_pck(sys->id)) 91 return 1; 92 93 return !!(pmc_read(pmc, AT91_PMC_SR) & (1 << sys->id)); 94 } 95 96 static const struct clk_ops system_ops = { 97 .prepare = clk_system_prepare, 98 .unprepare = clk_system_unprepare, 99 .is_prepared = clk_system_is_prepared, 100 }; 101 102 static struct clk * __init 103 at91_clk_register_system(struct at91_pmc *pmc, const char *name, 104 const char *parent_name, u8 id, int irq) 105 { 106 struct clk_system *sys; 107 struct clk *clk = NULL; 108 struct clk_init_data init; 109 int ret; 110 111 if (!parent_name || id > SYSTEM_MAX_ID) 112 return ERR_PTR(-EINVAL); 113 114 sys = kzalloc(sizeof(*sys), GFP_KERNEL); 115 if (!sys) 116 return ERR_PTR(-ENOMEM); 117 118 init.name = name; 119 init.ops = &system_ops; 120 init.parent_names = &parent_name; 121 init.num_parents = 1; 122 init.flags = CLK_SET_RATE_PARENT; 123 124 sys->id = id; 125 sys->hw.init = &init; 126 sys->pmc = pmc; 127 sys->irq = irq; 128 if (irq) { 129 init_waitqueue_head(&sys->wait); 130 irq_set_status_flags(sys->irq, IRQ_NOAUTOEN); 131 ret = request_irq(sys->irq, clk_system_irq_handler, 132 IRQF_TRIGGER_HIGH, name, sys); 133 if (ret) { 134 kfree(sys); 135 return ERR_PTR(ret); 136 } 137 } 138 139 clk = clk_register(NULL, &sys->hw); 140 if (IS_ERR(clk)) { 141 free_irq(sys->irq, sys); 142 kfree(sys); 143 } 144 145 return clk; 146 } 147 148 static void __init 149 of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc) 150 { 151 int num; 152 int irq = 0; 153 u32 id; 154 struct clk *clk; 155 const char *name; 156 struct device_node *sysclknp; 157 const char *parent_name; 158 159 num = of_get_child_count(np); 160 if (num > (SYSTEM_MAX_ID + 1)) 161 return; 162 163 for_each_child_of_node(np, sysclknp) { 164 if (of_property_read_u32(sysclknp, "reg", &id)) 165 continue; 166 167 if (of_property_read_string(np, "clock-output-names", &name)) 168 name = sysclknp->name; 169 170 if (is_pck(id)) 171 irq = irq_of_parse_and_map(sysclknp, 0); 172 173 parent_name = of_clk_get_parent_name(sysclknp, 0); 174 175 clk = at91_clk_register_system(pmc, name, parent_name, id, irq); 176 if (IS_ERR(clk)) 177 continue; 178 179 of_clk_add_provider(sysclknp, of_clk_src_simple_get, clk); 180 } 181 } 182 183 void __init of_at91rm9200_clk_sys_setup(struct device_node *np, 184 struct at91_pmc *pmc) 185 { 186 of_at91_clk_sys_setup(np, pmc); 187 } 188