root/drivers/clk/sunxi/clk-usb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sunxi_usb_reset_assert
  2. sunxi_usb_reset_deassert
  3. sunxi_usb_clk_setup
  4. sun4i_a10_usb_setup
  5. sun5i_a13_usb_setup
  6. sun6i_a31_usb_setup
  7. sun8i_a23_usb_setup
  8. sun8i_h3_usb_setup
  9. sun9i_a80_usb_mod_setup
  10. sun9i_a80_usb_phy_setup

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright 2013-2015 Emilio López
   4  *
   5  * Emilio López <emilio@elopez.com.ar>
   6  */
   7 
   8 #include <linux/clk.h>
   9 #include <linux/clk-provider.h>
  10 #include <linux/io.h>
  11 #include <linux/of.h>
  12 #include <linux/of_address.h>
  13 #include <linux/reset-controller.h>
  14 #include <linux/slab.h>
  15 #include <linux/spinlock.h>
  16 
  17 
  18 /**
  19  * sunxi_usb_reset... - reset bits in usb clk registers handling
  20  */
  21 
  22 struct usb_reset_data {
  23         void __iomem                    *reg;
  24         spinlock_t                      *lock;
  25         struct clk                      *clk;
  26         struct reset_controller_dev     rcdev;
  27 };
  28 
  29 static int sunxi_usb_reset_assert(struct reset_controller_dev *rcdev,
  30                               unsigned long id)
  31 {
  32         struct usb_reset_data *data = container_of(rcdev,
  33                                                    struct usb_reset_data,
  34                                                    rcdev);
  35         unsigned long flags;
  36         u32 reg;
  37 
  38         clk_prepare_enable(data->clk);
  39         spin_lock_irqsave(data->lock, flags);
  40 
  41         reg = readl(data->reg);
  42         writel(reg & ~BIT(id), data->reg);
  43 
  44         spin_unlock_irqrestore(data->lock, flags);
  45         clk_disable_unprepare(data->clk);
  46 
  47         return 0;
  48 }
  49 
  50 static int sunxi_usb_reset_deassert(struct reset_controller_dev *rcdev,
  51                                 unsigned long id)
  52 {
  53         struct usb_reset_data *data = container_of(rcdev,
  54                                                      struct usb_reset_data,
  55                                                      rcdev);
  56         unsigned long flags;
  57         u32 reg;
  58 
  59         clk_prepare_enable(data->clk);
  60         spin_lock_irqsave(data->lock, flags);
  61 
  62         reg = readl(data->reg);
  63         writel(reg | BIT(id), data->reg);
  64 
  65         spin_unlock_irqrestore(data->lock, flags);
  66         clk_disable_unprepare(data->clk);
  67 
  68         return 0;
  69 }
  70 
  71 static const struct reset_control_ops sunxi_usb_reset_ops = {
  72         .assert         = sunxi_usb_reset_assert,
  73         .deassert       = sunxi_usb_reset_deassert,
  74 };
  75 
  76 /**
  77  * sunxi_usb_clk_setup() - Setup function for usb gate clocks
  78  */
  79 
  80 #define SUNXI_USB_MAX_SIZE 32
  81 
  82 struct usb_clk_data {
  83         u32 clk_mask;
  84         u32 reset_mask;
  85         bool reset_needs_clk;
  86 };
  87 
  88 static void __init sunxi_usb_clk_setup(struct device_node *node,
  89                                        const struct usb_clk_data *data,
  90                                        spinlock_t *lock)
  91 {
  92         struct clk_onecell_data *clk_data;
  93         struct usb_reset_data *reset_data;
  94         const char *clk_parent;
  95         const char *clk_name;
  96         void __iomem *reg;
  97         int qty;
  98         int i = 0;
  99         int j = 0;
 100 
 101         reg = of_io_request_and_map(node, 0, of_node_full_name(node));
 102         if (IS_ERR(reg))
 103                 return;
 104 
 105         clk_parent = of_clk_get_parent_name(node, 0);
 106         if (!clk_parent)
 107                 return;
 108 
 109         /* Worst-case size approximation and memory allocation */
 110         qty = find_last_bit((unsigned long *)&data->clk_mask,
 111                             SUNXI_USB_MAX_SIZE);
 112 
 113         clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
 114         if (!clk_data)
 115                 return;
 116 
 117         clk_data->clks = kcalloc(qty + 1, sizeof(struct clk *), GFP_KERNEL);
 118         if (!clk_data->clks) {
 119                 kfree(clk_data);
 120                 return;
 121         }
 122 
 123         for_each_set_bit(i, (unsigned long *)&data->clk_mask,
 124                          SUNXI_USB_MAX_SIZE) {
 125                 of_property_read_string_index(node, "clock-output-names",
 126                                               j, &clk_name);
 127                 clk_data->clks[i] = clk_register_gate(NULL, clk_name,
 128                                                       clk_parent, 0,
 129                                                       reg, i, 0, lock);
 130                 WARN_ON(IS_ERR(clk_data->clks[i]));
 131 
 132                 j++;
 133         }
 134 
 135         /* Adjust to the real max */
 136         clk_data->clk_num = i;
 137 
 138         of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
 139 
 140         /* Register a reset controller for usb with reset bits */
 141         if (data->reset_mask == 0)
 142                 return;
 143 
 144         reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
 145         if (!reset_data)
 146                 return;
 147 
 148         if (data->reset_needs_clk) {
 149                 reset_data->clk = of_clk_get(node, 0);
 150                 if (IS_ERR(reset_data->clk)) {
 151                         pr_err("Could not get clock for reset controls\n");
 152                         kfree(reset_data);
 153                         return;
 154                 }
 155         }
 156 
 157         reset_data->reg = reg;
 158         reset_data->lock = lock;
 159         reset_data->rcdev.nr_resets = __fls(data->reset_mask) + 1;
 160         reset_data->rcdev.ops = &sunxi_usb_reset_ops;
 161         reset_data->rcdev.of_node = node;
 162         reset_controller_register(&reset_data->rcdev);
 163 }
 164 
 165 static const struct usb_clk_data sun4i_a10_usb_clk_data __initconst = {
 166         .clk_mask = BIT(8) | BIT(7) | BIT(6),
 167         .reset_mask = BIT(2) | BIT(1) | BIT(0),
 168 };
 169 
 170 static DEFINE_SPINLOCK(sun4i_a10_usb_lock);
 171 
 172 static void __init sun4i_a10_usb_setup(struct device_node *node)
 173 {
 174         sunxi_usb_clk_setup(node, &sun4i_a10_usb_clk_data, &sun4i_a10_usb_lock);
 175 }
 176 CLK_OF_DECLARE(sun4i_a10_usb, "allwinner,sun4i-a10-usb-clk", sun4i_a10_usb_setup);
 177 
 178 static const struct usb_clk_data sun5i_a13_usb_clk_data __initconst = {
 179         .clk_mask = BIT(8) | BIT(6),
 180         .reset_mask = BIT(1) | BIT(0),
 181 };
 182 
 183 static void __init sun5i_a13_usb_setup(struct device_node *node)
 184 {
 185         sunxi_usb_clk_setup(node, &sun5i_a13_usb_clk_data, &sun4i_a10_usb_lock);
 186 }
 187 CLK_OF_DECLARE(sun5i_a13_usb, "allwinner,sun5i-a13-usb-clk", sun5i_a13_usb_setup);
 188 
 189 static const struct usb_clk_data sun6i_a31_usb_clk_data __initconst = {
 190         .clk_mask = BIT(18) | BIT(17) | BIT(16) | BIT(10) | BIT(9) | BIT(8),
 191         .reset_mask = BIT(2) | BIT(1) | BIT(0),
 192 };
 193 
 194 static void __init sun6i_a31_usb_setup(struct device_node *node)
 195 {
 196         sunxi_usb_clk_setup(node, &sun6i_a31_usb_clk_data, &sun4i_a10_usb_lock);
 197 }
 198 CLK_OF_DECLARE(sun6i_a31_usb, "allwinner,sun6i-a31-usb-clk", sun6i_a31_usb_setup);
 199 
 200 static const struct usb_clk_data sun8i_a23_usb_clk_data __initconst = {
 201         .clk_mask = BIT(16) | BIT(11) | BIT(10) | BIT(9) | BIT(8),
 202         .reset_mask = BIT(2) | BIT(1) | BIT(0),
 203 };
 204 
 205 static void __init sun8i_a23_usb_setup(struct device_node *node)
 206 {
 207         sunxi_usb_clk_setup(node, &sun8i_a23_usb_clk_data, &sun4i_a10_usb_lock);
 208 }
 209 CLK_OF_DECLARE(sun8i_a23_usb, "allwinner,sun8i-a23-usb-clk", sun8i_a23_usb_setup);
 210 
 211 static const struct usb_clk_data sun8i_h3_usb_clk_data __initconst = {
 212         .clk_mask =  BIT(19) | BIT(18) | BIT(17) | BIT(16) |
 213                      BIT(11) | BIT(10) | BIT(9) | BIT(8),
 214         .reset_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
 215 };
 216 
 217 static void __init sun8i_h3_usb_setup(struct device_node *node)
 218 {
 219         sunxi_usb_clk_setup(node, &sun8i_h3_usb_clk_data, &sun4i_a10_usb_lock);
 220 }
 221 CLK_OF_DECLARE(sun8i_h3_usb, "allwinner,sun8i-h3-usb-clk", sun8i_h3_usb_setup);
 222 
 223 static const struct usb_clk_data sun9i_a80_usb_mod_data __initconst = {
 224         .clk_mask = BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1),
 225         .reset_mask = BIT(19) | BIT(18) | BIT(17),
 226         .reset_needs_clk = 1,
 227 };
 228 
 229 static DEFINE_SPINLOCK(a80_usb_mod_lock);
 230 
 231 static void __init sun9i_a80_usb_mod_setup(struct device_node *node)
 232 {
 233         sunxi_usb_clk_setup(node, &sun9i_a80_usb_mod_data, &a80_usb_mod_lock);
 234 }
 235 CLK_OF_DECLARE(sun9i_a80_usb_mod, "allwinner,sun9i-a80-usb-mod-clk", sun9i_a80_usb_mod_setup);
 236 
 237 static const struct usb_clk_data sun9i_a80_usb_phy_data __initconst = {
 238         .clk_mask = BIT(10) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1),
 239         .reset_mask = BIT(21) | BIT(20) | BIT(19) | BIT(18) | BIT(17),
 240         .reset_needs_clk = 1,
 241 };
 242 
 243 static DEFINE_SPINLOCK(a80_usb_phy_lock);
 244 
 245 static void __init sun9i_a80_usb_phy_setup(struct device_node *node)
 246 {
 247         sunxi_usb_clk_setup(node, &sun9i_a80_usb_phy_data, &a80_usb_phy_lock);
 248 }
 249 CLK_OF_DECLARE(sun9i_a80_usb_phy, "allwinner,sun9i-a80-usb-phy-clk", sun9i_a80_usb_phy_setup);

/* [<][>][^][v][top][bottom][index][help] */