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 /* 123 * CLK_IGNORE_UNUSED is used to avoid ddrck switch off. 124 * TODO : we should implement a driver supporting at91 ddr controller 125 * (see drivers/memory) which would request and enable the ddrck clock. 126 * When this is done we will be able to remove CLK_IGNORE_UNUSED flag. 127 */ 128 init.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED; 129 130 sys->id = id; 131 sys->hw.init = &init; 132 sys->pmc = pmc; 133 sys->irq = irq; 134 if (irq) { 135 init_waitqueue_head(&sys->wait); 136 irq_set_status_flags(sys->irq, IRQ_NOAUTOEN); 137 ret = request_irq(sys->irq, clk_system_irq_handler, 138 IRQF_TRIGGER_HIGH, name, sys); 139 if (ret) 140 return ERR_PTR(ret); 141 } 142 143 clk = clk_register(NULL, &sys->hw); 144 if (IS_ERR(clk)) 145 kfree(sys); 146 147 return clk; 148 } 149 150 static void __init 151 of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc) 152 { 153 int num; 154 int irq = 0; 155 u32 id; 156 struct clk *clk; 157 const char *name; 158 struct device_node *sysclknp; 159 const char *parent_name; 160 161 num = of_get_child_count(np); 162 if (num > (SYSTEM_MAX_ID + 1)) 163 return; 164 165 for_each_child_of_node(np, sysclknp) { 166 if (of_property_read_u32(sysclknp, "reg", &id)) 167 continue; 168 169 if (of_property_read_string(np, "clock-output-names", &name)) 170 name = sysclknp->name; 171 172 if (is_pck(id)) 173 irq = irq_of_parse_and_map(sysclknp, 0); 174 175 parent_name = of_clk_get_parent_name(sysclknp, 0); 176 177 clk = at91_clk_register_system(pmc, name, parent_name, id, irq); 178 if (IS_ERR(clk)) 179 continue; 180 181 of_clk_add_provider(sysclknp, of_clk_src_simple_get, clk); 182 } 183 } 184 185 void __init of_at91rm9200_clk_sys_setup(struct device_node *np, 186 struct at91_pmc *pmc) 187 { 188 of_at91_clk_sys_setup(np, pmc); 189 } 190