1*80eded6cSBoris BREZILLON /* 2*80eded6cSBoris BREZILLON * drivers/clk/at91/clk-slow.c 3*80eded6cSBoris BREZILLON * 4*80eded6cSBoris BREZILLON * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> 5*80eded6cSBoris BREZILLON * 6*80eded6cSBoris BREZILLON * This program is free software; you can redistribute it and/or modify 7*80eded6cSBoris BREZILLON * it under the terms of the GNU General Public License as published by 8*80eded6cSBoris BREZILLON * the Free Software Foundation; either version 2 of the License, or 9*80eded6cSBoris BREZILLON * (at your option) any later version. 10*80eded6cSBoris BREZILLON * 11*80eded6cSBoris BREZILLON */ 12*80eded6cSBoris BREZILLON 13*80eded6cSBoris BREZILLON #include <linux/clk-provider.h> 14*80eded6cSBoris BREZILLON #include <linux/clkdev.h> 15*80eded6cSBoris BREZILLON #include <linux/clk/at91_pmc.h> 16*80eded6cSBoris BREZILLON #include <linux/delay.h> 17*80eded6cSBoris BREZILLON #include <linux/of.h> 18*80eded6cSBoris BREZILLON #include <linux/of_address.h> 19*80eded6cSBoris BREZILLON #include <linux/of_irq.h> 20*80eded6cSBoris BREZILLON #include <linux/io.h> 21*80eded6cSBoris BREZILLON #include <linux/interrupt.h> 22*80eded6cSBoris BREZILLON #include <linux/irq.h> 23*80eded6cSBoris BREZILLON #include <linux/sched.h> 24*80eded6cSBoris BREZILLON #include <linux/wait.h> 25*80eded6cSBoris BREZILLON 26*80eded6cSBoris BREZILLON #include "pmc.h" 27*80eded6cSBoris BREZILLON #include "sckc.h" 28*80eded6cSBoris BREZILLON 29*80eded6cSBoris BREZILLON #define SLOW_CLOCK_FREQ 32768 30*80eded6cSBoris BREZILLON #define SLOWCK_SW_CYCLES 5 31*80eded6cSBoris BREZILLON #define SLOWCK_SW_TIME_USEC ((SLOWCK_SW_CYCLES * USEC_PER_SEC) / \ 32*80eded6cSBoris BREZILLON SLOW_CLOCK_FREQ) 33*80eded6cSBoris BREZILLON 34*80eded6cSBoris BREZILLON #define AT91_SCKC_CR 0x00 35*80eded6cSBoris BREZILLON #define AT91_SCKC_RCEN (1 << 0) 36*80eded6cSBoris BREZILLON #define AT91_SCKC_OSC32EN (1 << 1) 37*80eded6cSBoris BREZILLON #define AT91_SCKC_OSC32BYP (1 << 2) 38*80eded6cSBoris BREZILLON #define AT91_SCKC_OSCSEL (1 << 3) 39*80eded6cSBoris BREZILLON 40*80eded6cSBoris BREZILLON struct clk_slow_osc { 41*80eded6cSBoris BREZILLON struct clk_hw hw; 42*80eded6cSBoris BREZILLON void __iomem *sckcr; 43*80eded6cSBoris BREZILLON unsigned long startup_usec; 44*80eded6cSBoris BREZILLON }; 45*80eded6cSBoris BREZILLON 46*80eded6cSBoris BREZILLON #define to_clk_slow_osc(hw) container_of(hw, struct clk_slow_osc, hw) 47*80eded6cSBoris BREZILLON 48*80eded6cSBoris BREZILLON struct clk_slow_rc_osc { 49*80eded6cSBoris BREZILLON struct clk_hw hw; 50*80eded6cSBoris BREZILLON void __iomem *sckcr; 51*80eded6cSBoris BREZILLON unsigned long frequency; 52*80eded6cSBoris BREZILLON unsigned long accuracy; 53*80eded6cSBoris BREZILLON unsigned long startup_usec; 54*80eded6cSBoris BREZILLON }; 55*80eded6cSBoris BREZILLON 56*80eded6cSBoris BREZILLON #define to_clk_slow_rc_osc(hw) container_of(hw, struct clk_slow_rc_osc, hw) 57*80eded6cSBoris BREZILLON 58*80eded6cSBoris BREZILLON struct clk_sam9260_slow { 59*80eded6cSBoris BREZILLON struct clk_hw hw; 60*80eded6cSBoris BREZILLON struct at91_pmc *pmc; 61*80eded6cSBoris BREZILLON }; 62*80eded6cSBoris BREZILLON 63*80eded6cSBoris BREZILLON #define to_clk_sam9260_slow(hw) container_of(hw, struct clk_sam9260_slow, hw) 64*80eded6cSBoris BREZILLON 65*80eded6cSBoris BREZILLON struct clk_sam9x5_slow { 66*80eded6cSBoris BREZILLON struct clk_hw hw; 67*80eded6cSBoris BREZILLON void __iomem *sckcr; 68*80eded6cSBoris BREZILLON u8 parent; 69*80eded6cSBoris BREZILLON }; 70*80eded6cSBoris BREZILLON 71*80eded6cSBoris BREZILLON #define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw) 72*80eded6cSBoris BREZILLON 73*80eded6cSBoris BREZILLON 74*80eded6cSBoris BREZILLON static int clk_slow_osc_prepare(struct clk_hw *hw) 75*80eded6cSBoris BREZILLON { 76*80eded6cSBoris BREZILLON struct clk_slow_osc *osc = to_clk_slow_osc(hw); 77*80eded6cSBoris BREZILLON void __iomem *sckcr = osc->sckcr; 78*80eded6cSBoris BREZILLON u32 tmp = readl(sckcr); 79*80eded6cSBoris BREZILLON 80*80eded6cSBoris BREZILLON if (tmp & AT91_SCKC_OSC32BYP) 81*80eded6cSBoris BREZILLON return 0; 82*80eded6cSBoris BREZILLON 83*80eded6cSBoris BREZILLON writel(tmp | AT91_SCKC_OSC32EN, sckcr); 84*80eded6cSBoris BREZILLON 85*80eded6cSBoris BREZILLON usleep_range(osc->startup_usec, osc->startup_usec + 1); 86*80eded6cSBoris BREZILLON 87*80eded6cSBoris BREZILLON return 0; 88*80eded6cSBoris BREZILLON } 89*80eded6cSBoris BREZILLON 90*80eded6cSBoris BREZILLON static void clk_slow_osc_unprepare(struct clk_hw *hw) 91*80eded6cSBoris BREZILLON { 92*80eded6cSBoris BREZILLON struct clk_slow_osc *osc = to_clk_slow_osc(hw); 93*80eded6cSBoris BREZILLON void __iomem *sckcr = osc->sckcr; 94*80eded6cSBoris BREZILLON u32 tmp = readl(sckcr); 95*80eded6cSBoris BREZILLON 96*80eded6cSBoris BREZILLON if (tmp & AT91_SCKC_OSC32BYP) 97*80eded6cSBoris BREZILLON return; 98*80eded6cSBoris BREZILLON 99*80eded6cSBoris BREZILLON writel(tmp & ~AT91_SCKC_OSC32EN, sckcr); 100*80eded6cSBoris BREZILLON } 101*80eded6cSBoris BREZILLON 102*80eded6cSBoris BREZILLON static int clk_slow_osc_is_prepared(struct clk_hw *hw) 103*80eded6cSBoris BREZILLON { 104*80eded6cSBoris BREZILLON struct clk_slow_osc *osc = to_clk_slow_osc(hw); 105*80eded6cSBoris BREZILLON void __iomem *sckcr = osc->sckcr; 106*80eded6cSBoris BREZILLON u32 tmp = readl(sckcr); 107*80eded6cSBoris BREZILLON 108*80eded6cSBoris BREZILLON if (tmp & AT91_SCKC_OSC32BYP) 109*80eded6cSBoris BREZILLON return 1; 110*80eded6cSBoris BREZILLON 111*80eded6cSBoris BREZILLON return !!(tmp & AT91_SCKC_OSC32EN); 112*80eded6cSBoris BREZILLON } 113*80eded6cSBoris BREZILLON 114*80eded6cSBoris BREZILLON static const struct clk_ops slow_osc_ops = { 115*80eded6cSBoris BREZILLON .prepare = clk_slow_osc_prepare, 116*80eded6cSBoris BREZILLON .unprepare = clk_slow_osc_unprepare, 117*80eded6cSBoris BREZILLON .is_prepared = clk_slow_osc_is_prepared, 118*80eded6cSBoris BREZILLON }; 119*80eded6cSBoris BREZILLON 120*80eded6cSBoris BREZILLON static struct clk * __init 121*80eded6cSBoris BREZILLON at91_clk_register_slow_osc(void __iomem *sckcr, 122*80eded6cSBoris BREZILLON const char *name, 123*80eded6cSBoris BREZILLON const char *parent_name, 124*80eded6cSBoris BREZILLON unsigned long startup, 125*80eded6cSBoris BREZILLON bool bypass) 126*80eded6cSBoris BREZILLON { 127*80eded6cSBoris BREZILLON struct clk_slow_osc *osc; 128*80eded6cSBoris BREZILLON struct clk *clk = NULL; 129*80eded6cSBoris BREZILLON struct clk_init_data init; 130*80eded6cSBoris BREZILLON 131*80eded6cSBoris BREZILLON if (!sckcr || !name || !parent_name) 132*80eded6cSBoris BREZILLON return ERR_PTR(-EINVAL); 133*80eded6cSBoris BREZILLON 134*80eded6cSBoris BREZILLON osc = kzalloc(sizeof(*osc), GFP_KERNEL); 135*80eded6cSBoris BREZILLON if (!osc) 136*80eded6cSBoris BREZILLON return ERR_PTR(-ENOMEM); 137*80eded6cSBoris BREZILLON 138*80eded6cSBoris BREZILLON init.name = name; 139*80eded6cSBoris BREZILLON init.ops = &slow_osc_ops; 140*80eded6cSBoris BREZILLON init.parent_names = &parent_name; 141*80eded6cSBoris BREZILLON init.num_parents = 1; 142*80eded6cSBoris BREZILLON init.flags = CLK_IGNORE_UNUSED; 143*80eded6cSBoris BREZILLON 144*80eded6cSBoris BREZILLON osc->hw.init = &init; 145*80eded6cSBoris BREZILLON osc->sckcr = sckcr; 146*80eded6cSBoris BREZILLON osc->startup_usec = startup; 147*80eded6cSBoris BREZILLON 148*80eded6cSBoris BREZILLON if (bypass) 149*80eded6cSBoris BREZILLON writel((readl(sckcr) & ~AT91_SCKC_OSC32EN) | AT91_SCKC_OSC32BYP, 150*80eded6cSBoris BREZILLON sckcr); 151*80eded6cSBoris BREZILLON 152*80eded6cSBoris BREZILLON clk = clk_register(NULL, &osc->hw); 153*80eded6cSBoris BREZILLON if (IS_ERR(clk)) 154*80eded6cSBoris BREZILLON kfree(osc); 155*80eded6cSBoris BREZILLON 156*80eded6cSBoris BREZILLON return clk; 157*80eded6cSBoris BREZILLON } 158*80eded6cSBoris BREZILLON 159*80eded6cSBoris BREZILLON void __init of_at91sam9x5_clk_slow_osc_setup(struct device_node *np, 160*80eded6cSBoris BREZILLON void __iomem *sckcr) 161*80eded6cSBoris BREZILLON { 162*80eded6cSBoris BREZILLON struct clk *clk; 163*80eded6cSBoris BREZILLON const char *parent_name; 164*80eded6cSBoris BREZILLON const char *name = np->name; 165*80eded6cSBoris BREZILLON u32 startup; 166*80eded6cSBoris BREZILLON bool bypass; 167*80eded6cSBoris BREZILLON 168*80eded6cSBoris BREZILLON parent_name = of_clk_get_parent_name(np, 0); 169*80eded6cSBoris BREZILLON of_property_read_string(np, "clock-output-names", &name); 170*80eded6cSBoris BREZILLON of_property_read_u32(np, "atmel,startup-time-usec", &startup); 171*80eded6cSBoris BREZILLON bypass = of_property_read_bool(np, "atmel,osc-bypass"); 172*80eded6cSBoris BREZILLON 173*80eded6cSBoris BREZILLON clk = at91_clk_register_slow_osc(sckcr, name, parent_name, startup, 174*80eded6cSBoris BREZILLON bypass); 175*80eded6cSBoris BREZILLON if (IS_ERR(clk)) 176*80eded6cSBoris BREZILLON return; 177*80eded6cSBoris BREZILLON 178*80eded6cSBoris BREZILLON of_clk_add_provider(np, of_clk_src_simple_get, clk); 179*80eded6cSBoris BREZILLON } 180*80eded6cSBoris BREZILLON 181*80eded6cSBoris BREZILLON static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw, 182*80eded6cSBoris BREZILLON unsigned long parent_rate) 183*80eded6cSBoris BREZILLON { 184*80eded6cSBoris BREZILLON struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); 185*80eded6cSBoris BREZILLON 186*80eded6cSBoris BREZILLON return osc->frequency; 187*80eded6cSBoris BREZILLON } 188*80eded6cSBoris BREZILLON 189*80eded6cSBoris BREZILLON static unsigned long clk_slow_rc_osc_recalc_accuracy(struct clk_hw *hw, 190*80eded6cSBoris BREZILLON unsigned long parent_acc) 191*80eded6cSBoris BREZILLON { 192*80eded6cSBoris BREZILLON struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); 193*80eded6cSBoris BREZILLON 194*80eded6cSBoris BREZILLON return osc->accuracy; 195*80eded6cSBoris BREZILLON } 196*80eded6cSBoris BREZILLON 197*80eded6cSBoris BREZILLON static int clk_slow_rc_osc_prepare(struct clk_hw *hw) 198*80eded6cSBoris BREZILLON { 199*80eded6cSBoris BREZILLON struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); 200*80eded6cSBoris BREZILLON void __iomem *sckcr = osc->sckcr; 201*80eded6cSBoris BREZILLON 202*80eded6cSBoris BREZILLON writel(readl(sckcr) | AT91_SCKC_RCEN, sckcr); 203*80eded6cSBoris BREZILLON 204*80eded6cSBoris BREZILLON usleep_range(osc->startup_usec, osc->startup_usec + 1); 205*80eded6cSBoris BREZILLON 206*80eded6cSBoris BREZILLON return 0; 207*80eded6cSBoris BREZILLON } 208*80eded6cSBoris BREZILLON 209*80eded6cSBoris BREZILLON static void clk_slow_rc_osc_unprepare(struct clk_hw *hw) 210*80eded6cSBoris BREZILLON { 211*80eded6cSBoris BREZILLON struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); 212*80eded6cSBoris BREZILLON void __iomem *sckcr = osc->sckcr; 213*80eded6cSBoris BREZILLON 214*80eded6cSBoris BREZILLON writel(readl(sckcr) & ~AT91_SCKC_RCEN, sckcr); 215*80eded6cSBoris BREZILLON } 216*80eded6cSBoris BREZILLON 217*80eded6cSBoris BREZILLON static int clk_slow_rc_osc_is_prepared(struct clk_hw *hw) 218*80eded6cSBoris BREZILLON { 219*80eded6cSBoris BREZILLON struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); 220*80eded6cSBoris BREZILLON 221*80eded6cSBoris BREZILLON return !!(readl(osc->sckcr) & AT91_SCKC_RCEN); 222*80eded6cSBoris BREZILLON } 223*80eded6cSBoris BREZILLON 224*80eded6cSBoris BREZILLON static const struct clk_ops slow_rc_osc_ops = { 225*80eded6cSBoris BREZILLON .prepare = clk_slow_rc_osc_prepare, 226*80eded6cSBoris BREZILLON .unprepare = clk_slow_rc_osc_unprepare, 227*80eded6cSBoris BREZILLON .is_prepared = clk_slow_rc_osc_is_prepared, 228*80eded6cSBoris BREZILLON .recalc_rate = clk_slow_rc_osc_recalc_rate, 229*80eded6cSBoris BREZILLON .recalc_accuracy = clk_slow_rc_osc_recalc_accuracy, 230*80eded6cSBoris BREZILLON }; 231*80eded6cSBoris BREZILLON 232*80eded6cSBoris BREZILLON static struct clk * __init 233*80eded6cSBoris BREZILLON at91_clk_register_slow_rc_osc(void __iomem *sckcr, 234*80eded6cSBoris BREZILLON const char *name, 235*80eded6cSBoris BREZILLON unsigned long frequency, 236*80eded6cSBoris BREZILLON unsigned long accuracy, 237*80eded6cSBoris BREZILLON unsigned long startup) 238*80eded6cSBoris BREZILLON { 239*80eded6cSBoris BREZILLON struct clk_slow_rc_osc *osc; 240*80eded6cSBoris BREZILLON struct clk *clk = NULL; 241*80eded6cSBoris BREZILLON struct clk_init_data init; 242*80eded6cSBoris BREZILLON 243*80eded6cSBoris BREZILLON if (!sckcr || !name) 244*80eded6cSBoris BREZILLON return ERR_PTR(-EINVAL); 245*80eded6cSBoris BREZILLON 246*80eded6cSBoris BREZILLON osc = kzalloc(sizeof(*osc), GFP_KERNEL); 247*80eded6cSBoris BREZILLON if (!osc) 248*80eded6cSBoris BREZILLON return ERR_PTR(-ENOMEM); 249*80eded6cSBoris BREZILLON 250*80eded6cSBoris BREZILLON init.name = name; 251*80eded6cSBoris BREZILLON init.ops = &slow_rc_osc_ops; 252*80eded6cSBoris BREZILLON init.parent_names = NULL; 253*80eded6cSBoris BREZILLON init.num_parents = 0; 254*80eded6cSBoris BREZILLON init.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED; 255*80eded6cSBoris BREZILLON 256*80eded6cSBoris BREZILLON osc->hw.init = &init; 257*80eded6cSBoris BREZILLON osc->sckcr = sckcr; 258*80eded6cSBoris BREZILLON osc->frequency = frequency; 259*80eded6cSBoris BREZILLON osc->accuracy = accuracy; 260*80eded6cSBoris BREZILLON osc->startup_usec = startup; 261*80eded6cSBoris BREZILLON 262*80eded6cSBoris BREZILLON clk = clk_register(NULL, &osc->hw); 263*80eded6cSBoris BREZILLON if (IS_ERR(clk)) 264*80eded6cSBoris BREZILLON kfree(osc); 265*80eded6cSBoris BREZILLON 266*80eded6cSBoris BREZILLON return clk; 267*80eded6cSBoris BREZILLON } 268*80eded6cSBoris BREZILLON 269*80eded6cSBoris BREZILLON void __init of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np, 270*80eded6cSBoris BREZILLON void __iomem *sckcr) 271*80eded6cSBoris BREZILLON { 272*80eded6cSBoris BREZILLON struct clk *clk; 273*80eded6cSBoris BREZILLON u32 frequency = 0; 274*80eded6cSBoris BREZILLON u32 accuracy = 0; 275*80eded6cSBoris BREZILLON u32 startup = 0; 276*80eded6cSBoris BREZILLON const char *name = np->name; 277*80eded6cSBoris BREZILLON 278*80eded6cSBoris BREZILLON of_property_read_string(np, "clock-output-names", &name); 279*80eded6cSBoris BREZILLON of_property_read_u32(np, "clock-frequency", &frequency); 280*80eded6cSBoris BREZILLON of_property_read_u32(np, "clock-accuracy", &accuracy); 281*80eded6cSBoris BREZILLON of_property_read_u32(np, "atmel,startup-time-usec", &startup); 282*80eded6cSBoris BREZILLON 283*80eded6cSBoris BREZILLON clk = at91_clk_register_slow_rc_osc(sckcr, name, frequency, accuracy, 284*80eded6cSBoris BREZILLON startup); 285*80eded6cSBoris BREZILLON if (IS_ERR(clk)) 286*80eded6cSBoris BREZILLON return; 287*80eded6cSBoris BREZILLON 288*80eded6cSBoris BREZILLON of_clk_add_provider(np, of_clk_src_simple_get, clk); 289*80eded6cSBoris BREZILLON } 290*80eded6cSBoris BREZILLON 291*80eded6cSBoris BREZILLON static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index) 292*80eded6cSBoris BREZILLON { 293*80eded6cSBoris BREZILLON struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw); 294*80eded6cSBoris BREZILLON void __iomem *sckcr = slowck->sckcr; 295*80eded6cSBoris BREZILLON u32 tmp; 296*80eded6cSBoris BREZILLON 297*80eded6cSBoris BREZILLON if (index > 1) 298*80eded6cSBoris BREZILLON return -EINVAL; 299*80eded6cSBoris BREZILLON 300*80eded6cSBoris BREZILLON tmp = readl(sckcr); 301*80eded6cSBoris BREZILLON 302*80eded6cSBoris BREZILLON if ((!index && !(tmp & AT91_SCKC_OSCSEL)) || 303*80eded6cSBoris BREZILLON (index && (tmp & AT91_SCKC_OSCSEL))) 304*80eded6cSBoris BREZILLON return 0; 305*80eded6cSBoris BREZILLON 306*80eded6cSBoris BREZILLON if (index) 307*80eded6cSBoris BREZILLON tmp |= AT91_SCKC_OSCSEL; 308*80eded6cSBoris BREZILLON else 309*80eded6cSBoris BREZILLON tmp &= ~AT91_SCKC_OSCSEL; 310*80eded6cSBoris BREZILLON 311*80eded6cSBoris BREZILLON writel(tmp, sckcr); 312*80eded6cSBoris BREZILLON 313*80eded6cSBoris BREZILLON usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1); 314*80eded6cSBoris BREZILLON 315*80eded6cSBoris BREZILLON return 0; 316*80eded6cSBoris BREZILLON } 317*80eded6cSBoris BREZILLON 318*80eded6cSBoris BREZILLON static u8 clk_sam9x5_slow_get_parent(struct clk_hw *hw) 319*80eded6cSBoris BREZILLON { 320*80eded6cSBoris BREZILLON struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw); 321*80eded6cSBoris BREZILLON 322*80eded6cSBoris BREZILLON return !!(readl(slowck->sckcr) & AT91_SCKC_OSCSEL); 323*80eded6cSBoris BREZILLON } 324*80eded6cSBoris BREZILLON 325*80eded6cSBoris BREZILLON static const struct clk_ops sam9x5_slow_ops = { 326*80eded6cSBoris BREZILLON .set_parent = clk_sam9x5_slow_set_parent, 327*80eded6cSBoris BREZILLON .get_parent = clk_sam9x5_slow_get_parent, 328*80eded6cSBoris BREZILLON }; 329*80eded6cSBoris BREZILLON 330*80eded6cSBoris BREZILLON static struct clk * __init 331*80eded6cSBoris BREZILLON at91_clk_register_sam9x5_slow(void __iomem *sckcr, 332*80eded6cSBoris BREZILLON const char *name, 333*80eded6cSBoris BREZILLON const char **parent_names, 334*80eded6cSBoris BREZILLON int num_parents) 335*80eded6cSBoris BREZILLON { 336*80eded6cSBoris BREZILLON struct clk_sam9x5_slow *slowck; 337*80eded6cSBoris BREZILLON struct clk *clk = NULL; 338*80eded6cSBoris BREZILLON struct clk_init_data init; 339*80eded6cSBoris BREZILLON 340*80eded6cSBoris BREZILLON if (!sckcr || !name || !parent_names || !num_parents) 341*80eded6cSBoris BREZILLON return ERR_PTR(-EINVAL); 342*80eded6cSBoris BREZILLON 343*80eded6cSBoris BREZILLON slowck = kzalloc(sizeof(*slowck), GFP_KERNEL); 344*80eded6cSBoris BREZILLON if (!slowck) 345*80eded6cSBoris BREZILLON return ERR_PTR(-ENOMEM); 346*80eded6cSBoris BREZILLON 347*80eded6cSBoris BREZILLON init.name = name; 348*80eded6cSBoris BREZILLON init.ops = &sam9x5_slow_ops; 349*80eded6cSBoris BREZILLON init.parent_names = parent_names; 350*80eded6cSBoris BREZILLON init.num_parents = num_parents; 351*80eded6cSBoris BREZILLON init.flags = 0; 352*80eded6cSBoris BREZILLON 353*80eded6cSBoris BREZILLON slowck->hw.init = &init; 354*80eded6cSBoris BREZILLON slowck->sckcr = sckcr; 355*80eded6cSBoris BREZILLON slowck->parent = !!(readl(sckcr) & AT91_SCKC_OSCSEL); 356*80eded6cSBoris BREZILLON 357*80eded6cSBoris BREZILLON clk = clk_register(NULL, &slowck->hw); 358*80eded6cSBoris BREZILLON if (IS_ERR(clk)) 359*80eded6cSBoris BREZILLON kfree(slowck); 360*80eded6cSBoris BREZILLON 361*80eded6cSBoris BREZILLON return clk; 362*80eded6cSBoris BREZILLON } 363*80eded6cSBoris BREZILLON 364*80eded6cSBoris BREZILLON void __init of_at91sam9x5_clk_slow_setup(struct device_node *np, 365*80eded6cSBoris BREZILLON void __iomem *sckcr) 366*80eded6cSBoris BREZILLON { 367*80eded6cSBoris BREZILLON struct clk *clk; 368*80eded6cSBoris BREZILLON const char *parent_names[2]; 369*80eded6cSBoris BREZILLON int num_parents; 370*80eded6cSBoris BREZILLON const char *name = np->name; 371*80eded6cSBoris BREZILLON int i; 372*80eded6cSBoris BREZILLON 373*80eded6cSBoris BREZILLON num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells"); 374*80eded6cSBoris BREZILLON if (num_parents <= 0 || num_parents > 2) 375*80eded6cSBoris BREZILLON return; 376*80eded6cSBoris BREZILLON 377*80eded6cSBoris BREZILLON for (i = 0; i < num_parents; ++i) { 378*80eded6cSBoris BREZILLON parent_names[i] = of_clk_get_parent_name(np, i); 379*80eded6cSBoris BREZILLON if (!parent_names[i]) 380*80eded6cSBoris BREZILLON return; 381*80eded6cSBoris BREZILLON } 382*80eded6cSBoris BREZILLON 383*80eded6cSBoris BREZILLON of_property_read_string(np, "clock-output-names", &name); 384*80eded6cSBoris BREZILLON 385*80eded6cSBoris BREZILLON clk = at91_clk_register_sam9x5_slow(sckcr, name, parent_names, 386*80eded6cSBoris BREZILLON num_parents); 387*80eded6cSBoris BREZILLON if (IS_ERR(clk)) 388*80eded6cSBoris BREZILLON return; 389*80eded6cSBoris BREZILLON 390*80eded6cSBoris BREZILLON of_clk_add_provider(np, of_clk_src_simple_get, clk); 391*80eded6cSBoris BREZILLON } 392*80eded6cSBoris BREZILLON 393*80eded6cSBoris BREZILLON static u8 clk_sam9260_slow_get_parent(struct clk_hw *hw) 394*80eded6cSBoris BREZILLON { 395*80eded6cSBoris BREZILLON struct clk_sam9260_slow *slowck = to_clk_sam9260_slow(hw); 396*80eded6cSBoris BREZILLON 397*80eded6cSBoris BREZILLON return !!(pmc_read(slowck->pmc, AT91_PMC_SR) & AT91_PMC_OSCSEL); 398*80eded6cSBoris BREZILLON } 399*80eded6cSBoris BREZILLON 400*80eded6cSBoris BREZILLON static const struct clk_ops sam9260_slow_ops = { 401*80eded6cSBoris BREZILLON .get_parent = clk_sam9260_slow_get_parent, 402*80eded6cSBoris BREZILLON }; 403*80eded6cSBoris BREZILLON 404*80eded6cSBoris BREZILLON static struct clk * __init 405*80eded6cSBoris BREZILLON at91_clk_register_sam9260_slow(struct at91_pmc *pmc, 406*80eded6cSBoris BREZILLON const char *name, 407*80eded6cSBoris BREZILLON const char **parent_names, 408*80eded6cSBoris BREZILLON int num_parents) 409*80eded6cSBoris BREZILLON { 410*80eded6cSBoris BREZILLON struct clk_sam9260_slow *slowck; 411*80eded6cSBoris BREZILLON struct clk *clk = NULL; 412*80eded6cSBoris BREZILLON struct clk_init_data init; 413*80eded6cSBoris BREZILLON 414*80eded6cSBoris BREZILLON if (!pmc || !name) 415*80eded6cSBoris BREZILLON return ERR_PTR(-EINVAL); 416*80eded6cSBoris BREZILLON 417*80eded6cSBoris BREZILLON if (!parent_names || !num_parents) 418*80eded6cSBoris BREZILLON return ERR_PTR(-EINVAL); 419*80eded6cSBoris BREZILLON 420*80eded6cSBoris BREZILLON slowck = kzalloc(sizeof(*slowck), GFP_KERNEL); 421*80eded6cSBoris BREZILLON if (!slowck) 422*80eded6cSBoris BREZILLON return ERR_PTR(-ENOMEM); 423*80eded6cSBoris BREZILLON 424*80eded6cSBoris BREZILLON init.name = name; 425*80eded6cSBoris BREZILLON init.ops = &sam9260_slow_ops; 426*80eded6cSBoris BREZILLON init.parent_names = parent_names; 427*80eded6cSBoris BREZILLON init.num_parents = num_parents; 428*80eded6cSBoris BREZILLON init.flags = 0; 429*80eded6cSBoris BREZILLON 430*80eded6cSBoris BREZILLON slowck->hw.init = &init; 431*80eded6cSBoris BREZILLON slowck->pmc = pmc; 432*80eded6cSBoris BREZILLON 433*80eded6cSBoris BREZILLON clk = clk_register(NULL, &slowck->hw); 434*80eded6cSBoris BREZILLON if (IS_ERR(clk)) 435*80eded6cSBoris BREZILLON kfree(slowck); 436*80eded6cSBoris BREZILLON 437*80eded6cSBoris BREZILLON return clk; 438*80eded6cSBoris BREZILLON } 439*80eded6cSBoris BREZILLON 440*80eded6cSBoris BREZILLON void __init of_at91sam9260_clk_slow_setup(struct device_node *np, 441*80eded6cSBoris BREZILLON struct at91_pmc *pmc) 442*80eded6cSBoris BREZILLON { 443*80eded6cSBoris BREZILLON struct clk *clk; 444*80eded6cSBoris BREZILLON const char *parent_names[2]; 445*80eded6cSBoris BREZILLON int num_parents; 446*80eded6cSBoris BREZILLON const char *name = np->name; 447*80eded6cSBoris BREZILLON int i; 448*80eded6cSBoris BREZILLON 449*80eded6cSBoris BREZILLON num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells"); 450*80eded6cSBoris BREZILLON if (num_parents <= 0 || num_parents > 1) 451*80eded6cSBoris BREZILLON return; 452*80eded6cSBoris BREZILLON 453*80eded6cSBoris BREZILLON for (i = 0; i < num_parents; ++i) { 454*80eded6cSBoris BREZILLON parent_names[i] = of_clk_get_parent_name(np, i); 455*80eded6cSBoris BREZILLON if (!parent_names[i]) 456*80eded6cSBoris BREZILLON return; 457*80eded6cSBoris BREZILLON } 458*80eded6cSBoris BREZILLON 459*80eded6cSBoris BREZILLON of_property_read_string(np, "clock-output-names", &name); 460*80eded6cSBoris BREZILLON 461*80eded6cSBoris BREZILLON clk = at91_clk_register_sam9260_slow(pmc, name, parent_names, 462*80eded6cSBoris BREZILLON num_parents); 463*80eded6cSBoris BREZILLON if (IS_ERR(clk)) 464*80eded6cSBoris BREZILLON return; 465*80eded6cSBoris BREZILLON 466*80eded6cSBoris BREZILLON of_clk_add_provider(np, of_clk_src_simple_get, clk); 467*80eded6cSBoris BREZILLON } 468